diff --git a/dist/jio-latest.js b/dist/jio-latest.js
index 5a98cc30bce9c5eae939bc37d9aa6792f63a1e12..6a11dbee290f8e70855043333abf2b2ad8cfaed9 100644
--- a/dist/jio-latest.js
+++ b/dist/jio-latest.js
@@ -1527,422 +1527,243 @@ if (typeof define === 'function' && define.amd) {
   module.exports = LZString
 }
 ;//! moment.js
-//! version : 2.5.0
+//! version : 2.13.0
 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
 //! license : MIT
 //! momentjs.com
 
-(function (undefined) {
+;(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';
 
-    /************************************
-        Constants
-    ************************************/
+    var hookCallback;
 
-    var moment,
-        VERSION = "2.5.0",
-        global = this,
-        round = Math.round,
-        i,
-
-        YEAR = 0,
-        MONTH = 1,
-        DATE = 2,
-        HOUR = 3,
-        MINUTE = 4,
-        SECOND = 5,
-        MILLISECOND = 6,
-
-        // internal storage for language config files
-        languages = {},
-
-        // check for nodeJS
-        hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
-
-        // ASP.NET json date format regex
-        aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
-        aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
-
-        // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
-        // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
-        isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
-
-        // format tokens
-        formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
-        localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
-
-        // parsing token regexes
-        parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
-        parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
-        parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
-        parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
-        parseTokenDigits = /\d+/, // nonzero number of digits
-        parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
-        parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
-        parseTokenT = /T/i, // T (ISO separator)
-        parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
-
-        //strict parsing regexes
-        parseTokenOneDigit = /\d/, // 0 - 9
-        parseTokenTwoDigits = /\d\d/, // 00 - 99
-        parseTokenThreeDigits = /\d{3}/, // 000 - 999
-        parseTokenFourDigits = /\d{4}/, // 0000 - 9999
-        parseTokenSixDigits = /[+\-]?\d{6}/, // -999,999 - 999,999
-
-        // iso 8601 regex
-        // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
-        isoRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
-
-        isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
-
-        isoDates = [
-            'YYYY-MM-DD',
-            'GGGG-[W]WW',
-            'GGGG-[W]WW-E',
-            'YYYY-DDD'
-        ],
-
-        // iso time formats and regexes
-        isoTimes = [
-            ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
-            ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
-            ['HH:mm', /(T| )\d\d:\d\d/],
-            ['HH', /(T| )\d\d/]
-        ],
-
-        // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
-        parseTimezoneChunker = /([\+\-]|\d\d)/gi,
-
-        // getter and setter names
-        proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
-        unitMillisecondFactors = {
-            'Milliseconds' : 1,
-            'Seconds' : 1e3,
-            'Minutes' : 6e4,
-            'Hours' : 36e5,
-            'Days' : 864e5,
-            'Months' : 2592e6,
-            'Years' : 31536e6
-        },
-
-        unitAliases = {
-            ms : 'millisecond',
-            s : 'second',
-            m : 'minute',
-            h : 'hour',
-            d : 'day',
-            D : 'date',
-            w : 'week',
-            W : 'isoWeek',
-            M : 'month',
-            y : 'year',
-            DDD : 'dayOfYear',
-            e : 'weekday',
-            E : 'isoWeekday',
-            gg: 'weekYear',
-            GG: 'isoWeekYear'
-        },
-
-        camelFunctions = {
-            dayofyear : 'dayOfYear',
-            isoweekday : 'isoWeekday',
-            isoweek : 'isoWeek',
-            weekyear : 'weekYear',
-            isoweekyear : 'isoWeekYear'
-        },
-
-        // format function strings
-        formatFunctions = {},
-
-        // tokens to ordinalize and pad
-        ordinalizeTokens = 'DDD w W M D d'.split(' '),
-        paddedTokens = 'M D H h m s w W'.split(' '),
-
-        formatTokenFunctions = {
-            M    : function () {
-                return this.month() + 1;
-            },
-            MMM  : function (format) {
-                return this.lang().monthsShort(this, format);
-            },
-            MMMM : function (format) {
-                return this.lang().months(this, format);
-            },
-            D    : function () {
-                return this.date();
-            },
-            DDD  : function () {
-                return this.dayOfYear();
-            },
-            d    : function () {
-                return this.day();
-            },
-            dd   : function (format) {
-                return this.lang().weekdaysMin(this, format);
-            },
-            ddd  : function (format) {
-                return this.lang().weekdaysShort(this, format);
-            },
-            dddd : function (format) {
-                return this.lang().weekdays(this, format);
-            },
-            w    : function () {
-                return this.week();
-            },
-            W    : function () {
-                return this.isoWeek();
-            },
-            YY   : function () {
-                return leftZeroFill(this.year() % 100, 2);
-            },
-            YYYY : function () {
-                return leftZeroFill(this.year(), 4);
-            },
-            YYYYY : function () {
-                return leftZeroFill(this.year(), 5);
-            },
-            YYYYYY : function () {
-                var y = this.year(), sign = y >= 0 ? '+' : '-';
-                return sign + leftZeroFill(Math.abs(y), 6);
-            },
-            gg   : function () {
-                return leftZeroFill(this.weekYear() % 100, 2);
-            },
-            gggg : function () {
-                return this.weekYear();
-            },
-            ggggg : function () {
-                return leftZeroFill(this.weekYear(), 5);
-            },
-            GG   : function () {
-                return leftZeroFill(this.isoWeekYear() % 100, 2);
-            },
-            GGGG : function () {
-                return this.isoWeekYear();
-            },
-            GGGGG : function () {
-                return leftZeroFill(this.isoWeekYear(), 5);
-            },
-            e : function () {
-                return this.weekday();
-            },
-            E : function () {
-                return this.isoWeekday();
-            },
-            a    : function () {
-                return this.lang().meridiem(this.hours(), this.minutes(), true);
-            },
-            A    : function () {
-                return this.lang().meridiem(this.hours(), this.minutes(), false);
-            },
-            H    : function () {
-                return this.hours();
-            },
-            h    : function () {
-                return this.hours() % 12 || 12;
-            },
-            m    : function () {
-                return this.minutes();
-            },
-            s    : function () {
-                return this.seconds();
-            },
-            S    : function () {
-                return toInt(this.milliseconds() / 100);
-            },
-            SS   : function () {
-                return leftZeroFill(toInt(this.milliseconds() / 10), 2);
-            },
-            SSS  : function () {
-                return leftZeroFill(this.milliseconds(), 3);
-            },
-            SSSS : function () {
-                return leftZeroFill(this.milliseconds(), 3);
-            },
-            Z    : function () {
-                var a = -this.zone(),
-                    b = "+";
-                if (a < 0) {
-                    a = -a;
-                    b = "-";
-                }
-                return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
-            },
-            ZZ   : function () {
-                var a = -this.zone(),
-                    b = "+";
-                if (a < 0) {
-                    a = -a;
-                    b = "-";
-                }
-                return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
-            },
-            z : function () {
-                return this.zoneAbbr();
-            },
-            zz : function () {
-                return this.zoneName();
-            },
-            X    : function () {
-                return this.unix();
-            },
-            Q : function () {
-                return this.quarter();
-            }
-        },
-
-        lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
-
-    function padToken(func, count) {
-        return function (a) {
-            return leftZeroFill(func.call(this, a), count);
-        };
-    }
-    function ordinalizeToken(func, period) {
-        return function (a) {
-            return this.lang().ordinal(func.call(this, a), period);
-        };
+    function utils_hooks__hooks () {
+        return hookCallback.apply(null, arguments);
     }
 
-    while (ordinalizeTokens.length) {
-        i = ordinalizeTokens.pop();
-        formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
-    }
-    while (paddedTokens.length) {
-        i = paddedTokens.pop();
-        formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
+    // This is done to register the method called with moment()
+    // without creating circular dependencies.
+    function setHookCallback (callback) {
+        hookCallback = callback;
     }
-    formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
-
-
-    /************************************
-        Constructors
-    ************************************/
-
-    function Language() {
 
+    function isArray(input) {
+        return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
     }
 
-    // Moment prototype object
-    function Moment(config) {
-        checkOverflow(config);
-        extend(this, config);
+    function isDate(input) {
+        return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
     }
 
-    // Duration Constructor
-    function Duration(duration) {
-        var normalizedInput = normalizeObjectUnits(duration),
-            years = normalizedInput.year || 0,
-            months = normalizedInput.month || 0,
-            weeks = normalizedInput.week || 0,
-            days = normalizedInput.day || 0,
-            hours = normalizedInput.hour || 0,
-            minutes = normalizedInput.minute || 0,
-            seconds = normalizedInput.second || 0,
-            milliseconds = normalizedInput.millisecond || 0;
-
-        // representation for dateAddRemove
-        this._milliseconds = +milliseconds +
-            seconds * 1e3 + // 1000
-            minutes * 6e4 + // 1000 * 60
-            hours * 36e5; // 1000 * 60 * 60
-        // Because of dateAddRemove treats 24 hours as different from a
-        // day when working around DST, we need to store them separately
-        this._days = +days +
-            weeks * 7;
-        // It is impossible translate months into days without knowing
-        // which months you are are talking about, so we have to store
-        // it separately.
-        this._months = +months +
-            years * 12;
-
-        this._data = {};
-
-        this._bubble();
+    function map(arr, fn) {
+        var res = [], i;
+        for (i = 0; i < arr.length; ++i) {
+            res.push(fn(arr[i], i));
+        }
+        return res;
     }
 
-    /************************************
-        Helpers
-    ************************************/
-
+    function hasOwnProp(a, b) {
+        return Object.prototype.hasOwnProperty.call(a, b);
+    }
 
     function extend(a, b) {
         for (var i in b) {
-            if (b.hasOwnProperty(i)) {
+            if (hasOwnProp(b, i)) {
                 a[i] = b[i];
             }
         }
 
-        if (b.hasOwnProperty("toString")) {
+        if (hasOwnProp(b, 'toString')) {
             a.toString = b.toString;
         }
 
-        if (b.hasOwnProperty("valueOf")) {
+        if (hasOwnProp(b, 'valueOf')) {
             a.valueOf = b.valueOf;
         }
 
         return a;
     }
 
-    function absRound(number) {
-        if (number < 0) {
-            return Math.ceil(number);
-        } else {
-            return Math.floor(number);
+    function create_utc__createUTC (input, format, locale, strict) {
+        return createLocalOrUTC(input, format, locale, strict, true).utc();
+    }
+
+    function defaultParsingFlags() {
+        // We need to deep clone this object.
+        return {
+            empty           : false,
+            unusedTokens    : [],
+            unusedInput     : [],
+            overflow        : -2,
+            charsLeftOver   : 0,
+            nullInput       : false,
+            invalidMonth    : null,
+            invalidFormat   : false,
+            userInvalidated : false,
+            iso             : false,
+            parsedDateParts : [],
+            meridiem        : null
+        };
+    }
+
+    function getParsingFlags(m) {
+        if (m._pf == null) {
+            m._pf = defaultParsingFlags();
         }
+        return m._pf;
     }
 
-    // left zero fill a number
-    // see http://jsperf.com/left-zero-filling for performance comparison
-    function leftZeroFill(number, targetLength, forceSign) {
-        var output = Math.abs(number) + '',
-            sign = number >= 0;
+    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 valid__isValid(m) {
+        if (m._isValid == null) {
+            var flags = getParsingFlags(m);
+            var parsedParts = some.call(flags.parsedDateParts, function (i) {
+                return i != null;
+            });
+            m._isValid = !isNaN(m._d.getTime()) &&
+                flags.overflow < 0 &&
+                !flags.empty &&
+                !flags.invalidMonth &&
+                !flags.invalidWeekday &&
+                !flags.nullInput &&
+                !flags.invalidFormat &&
+                !flags.userInvalidated &&
+                (!flags.meridiem || (flags.meridiem && parsedParts));
 
-        while (output.length < targetLength) {
-            output = '0' + output;
+            if (m._strict) {
+                m._isValid = m._isValid &&
+                    flags.charsLeftOver === 0 &&
+                    flags.unusedTokens.length === 0 &&
+                    flags.bigHour === undefined;
+            }
         }
-        return (sign ? (forceSign ? '+' : '') : '-') + output;
+        return m._isValid;
     }
 
-    // helper function for _.addTime and _.subtractTime
-    function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
-        var milliseconds = duration._milliseconds,
-            days = duration._days,
-            months = duration._months,
-            minutes,
-            hours;
+    function valid__createInvalid (flags) {
+        var m = create_utc__createUTC(NaN);
+        if (flags != null) {
+            extend(getParsingFlags(m), flags);
+        }
+        else {
+            getParsingFlags(m).userInvalidated = true;
+        }
 
-        if (milliseconds) {
-            mom._d.setTime(+mom._d + milliseconds * isAdding);
+        return m;
+    }
+
+    function isUndefined(input) {
+        return input === void 0;
+    }
+
+    // Plugins that add properties should also add the key here (null value),
+    // so we can properly clone ourselves.
+    var momentProperties = utils_hooks__hooks.momentProperties = [];
+
+    function copyConfig(to, from) {
+        var i, prop, val;
+
+        if (!isUndefined(from._isAMomentObject)) {
+            to._isAMomentObject = from._isAMomentObject;
         }
-        // store the minutes and hours so we can restore them
-        if (days || months) {
-            minutes = mom.minute();
-            hours = mom.hour();
+        if (!isUndefined(from._i)) {
+            to._i = from._i;
         }
-        if (days) {
-            mom.date(mom.date() + days * isAdding);
+        if (!isUndefined(from._f)) {
+            to._f = from._f;
         }
-        if (months) {
-            mom.month(mom.month() + months * isAdding);
+        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 (milliseconds && !ignoreUpdateOffset) {
-            moment.updateOffset(mom);
+        if (!isUndefined(from._locale)) {
+            to._locale = from._locale;
         }
-        // restore the minutes and hours after possibly changing dst
-        if (days || months) {
-            mom.minute(minutes);
-            mom.hour(hours);
+
+        if (momentProperties.length > 0) {
+            for (i in momentProperties) {
+                prop = momentProperties[i];
+                val = from[prop];
+                if (!isUndefined(val)) {
+                    to[prop] = val;
+                }
+            }
         }
+
+        return to;
     }
 
-    // check if is an array
-    function isArray(input) {
-        return Object.prototype.toString.call(input) === '[object Array]';
+    var updateInProgress = false;
+
+    // Moment prototype object
+    function Moment(config) {
+        copyConfig(this, config);
+        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
+        // Prevent infinite loop in case updateOffset creates new moment
+        // objects.
+        if (updateInProgress === false) {
+            updateInProgress = true;
+            utils_hooks__hooks.updateOffset(this);
+            updateInProgress = false;
+        }
     }
 
-    function isDate(input) {
-        return  Object.prototype.toString.call(input) === '[object Date]' ||
-                input instanceof Date;
+    function isMoment (obj) {
+        return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
+    }
+
+    function absFloor (number) {
+        if (number < 0) {
+            return Math.ceil(number);
+        } else {
+            return Math.floor(number);
+        }
+    }
+
+    function toInt(argumentForCoercion) {
+        var coercedNumber = +argumentForCoercion,
+            value = 0;
+
+        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
+            value = absFloor(coercedNumber);
+        }
+
+        return value;
     }
 
     // compare two arrays, return the number of differences
@@ -1960,432 +1781,379 @@ if (typeof define === 'function' && define.amd) {
         return diffs + lengthDiff;
     }
 
-    function normalizeUnits(units) {
-        if (units) {
-            var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
-            units = unitAliases[units] || camelFunctions[lowered] || lowered;
+    function warn(msg) {
+        if (utils_hooks__hooks.suppressDeprecationWarnings === false &&
+                (typeof console !==  'undefined') && console.warn) {
+            console.warn('Deprecation warning: ' + msg);
         }
-        return units;
     }
 
-    function normalizeObjectUnits(inputObject) {
-        var normalizedInput = {},
-            normalizedProp,
-            prop;
+    function deprecate(msg, fn) {
+        var firstTime = true;
 
-        for (prop in inputObject) {
-            if (inputObject.hasOwnProperty(prop)) {
-                normalizedProp = normalizeUnits(prop);
-                if (normalizedProp) {
-                    normalizedInput[normalizedProp] = inputObject[prop];
-                }
+        return extend(function () {
+            if (utils_hooks__hooks.deprecationHandler != null) {
+                utils_hooks__hooks.deprecationHandler(null, msg);
             }
-        }
-
-        return normalizedInput;
+            if (firstTime) {
+                warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack);
+                firstTime = false;
+            }
+            return fn.apply(this, arguments);
+        }, fn);
     }
 
-    function makeList(field) {
-        var count, setter;
+    var deprecations = {};
 
-        if (field.indexOf('week') === 0) {
-            count = 7;
-            setter = 'day';
-        }
-        else if (field.indexOf('month') === 0) {
-            count = 12;
-            setter = 'month';
+    function deprecateSimple(name, msg) {
+        if (utils_hooks__hooks.deprecationHandler != null) {
+            utils_hooks__hooks.deprecationHandler(name, msg);
         }
-        else {
-            return;
+        if (!deprecations[name]) {
+            warn(msg);
+            deprecations[name] = true;
         }
+    }
 
-        moment[field] = function (format, index) {
-            var i, getter,
-                method = moment.fn._lang[field],
-                results = [];
-
-            if (typeof format === 'number') {
-                index = format;
-                format = undefined;
-            }
-
-            getter = function (i) {
-                var m = moment().utc().set(setter, i);
-                return method.call(moment.fn._lang, m, format || '');
-            };
+    utils_hooks__hooks.suppressDeprecationWarnings = false;
+    utils_hooks__hooks.deprecationHandler = null;
 
-            if (index != null) {
-                return getter(index);
-            }
-            else {
-                for (i = 0; i < count; i++) {
-                    results.push(getter(i));
-                }
-                return results;
-            }
-        };
+    function isFunction(input) {
+        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
     }
 
-    function toInt(argumentForCoercion) {
-        var coercedNumber = +argumentForCoercion,
-            value = 0;
+    function isObject(input) {
+        return Object.prototype.toString.call(input) === '[object Object]';
+    }
 
-        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
-            if (coercedNumber >= 0) {
-                value = Math.floor(coercedNumber);
+    function locale_set__set (config) {
+        var prop, i;
+        for (i in config) {
+            prop = config[i];
+            if (isFunction(prop)) {
+                this[i] = prop;
             } else {
-                value = Math.ceil(coercedNumber);
+                this['_' + i] = prop;
             }
         }
-
-        return value;
+        this._config = config;
+        // Lenient ordinal parsing accepts just a number in addition to
+        // number + (possibly) stuff coming from _ordinalParseLenient.
+        this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
     }
 
-    function daysInMonth(year, month) {
-        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
-    }
-
-    function daysInYear(year) {
-        return isLeapYear(year) ? 366 : 365;
+    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];
+                }
+            }
+        }
+        return res;
     }
 
-    function isLeapYear(year) {
-        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+    function Locale(config) {
+        if (config != null) {
+            this.set(config);
+        }
     }
 
-    function checkOverflow(m) {
-        var overflow;
-        if (m._a && m._pf.overflow === -2) {
-            overflow =
-                m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
-                m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
-                m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
-                m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
-                m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
-                m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
-                -1;
+    var keys;
 
-            if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
-                overflow = DATE;
+    if (Object.keys) {
+        keys = Object.keys;
+    } else {
+        keys = function (obj) {
+            var i, res = [];
+            for (i in obj) {
+                if (hasOwnProp(obj, i)) {
+                    res.push(i);
+                }
             }
-
-            m._pf.overflow = overflow;
-        }
+            return res;
+        };
     }
 
-    function initializeParsingFlags(config) {
-        config._pf = {
-            empty : false,
-            unusedTokens : [],
-            unusedInput : [],
-            overflow : -2,
-            charsLeftOver : 0,
-            nullInput : false,
-            invalidMonth : null,
-            invalidFormat : false,
-            userInvalidated : false,
-            iso: false
-        };
+    // internal storage for locale config files
+    var locales = {};
+    var globalLocale;
+
+    function normalizeLocale(key) {
+        return key ? key.toLowerCase().replace('_', '-') : key;
     }
 
-    function isValid(m) {
-        if (m._isValid == null) {
-            m._isValid = !isNaN(m._d.getTime()) &&
-                m._pf.overflow < 0 &&
-                !m._pf.empty &&
-                !m._pf.invalidMonth &&
-                !m._pf.nullInput &&
-                !m._pf.invalidFormat &&
-                !m._pf.userInvalidated;
+    // pick the locale from the array
+    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
+    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
+    function chooseLocale(names) {
+        var i = 0, j, next, locale, split;
 
-            if (m._strict) {
-                m._isValid = m._isValid &&
-                    m._pf.charsLeftOver === 0 &&
-                    m._pf.unusedTokens.length === 0;
+        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) {
+                    //the next array item is better than a shallower substring of this one
+                    break;
+                }
+                j--;
             }
+            i++;
         }
-        return m._isValid;
-    }
-
-    function normalizeLanguage(key) {
-        return key ? key.toLowerCase().replace('_', '-') : key;
+        return null;
     }
 
-    // Return a moment from input, that is local/utc/zone equivalent to model.
-    function makeAs(input, model) {
-        return model._isUTC ? moment(input).zone(model._offset || 0) :
-            moment(input).local();
+    function loadLocale(name) {
+        var oldLocale = null;
+        // TODO: Find a better way to register and load all the locales in Node
+        if (!locales[name] && (typeof module !== 'undefined') &&
+                module && module.exports) {
+            try {
+                oldLocale = globalLocale._abbr;
+                require('./locale/' + name);
+                // because defineLocale currently also sets the global locale, we
+                // want to undo that for lazy loaded locales
+                locale_locales__getSetGlobalLocale(oldLocale);
+            } catch (e) { }
+        }
+        return locales[name];
     }
 
-    /************************************
-        Languages
-    ************************************/
+    // This function will load locale and then set the global locale.  If
+    // no arguments are passed in, it will simply return the current global
+    // locale key.
+    function locale_locales__getSetGlobalLocale (key, values) {
+        var data;
+        if (key) {
+            if (isUndefined(values)) {
+                data = locale_locales__getLocale(key);
+            }
+            else {
+                data = defineLocale(key, values);
+            }
 
+            if (data) {
+                // moment.duration._locale = moment._locale = data;
+                globalLocale = data;
+            }
+        }
 
-    extend(Language.prototype, {
+        return globalLocale._abbr;
+    }
 
-        set : function (config) {
-            var prop, i;
-            for (i in config) {
-                prop = config[i];
-                if (typeof prop === 'function') {
-                    this[i] = prop;
+    function defineLocale (name, config) {
+        if (config !== null) {
+            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');
+                config = mergeConfigs(locales[name]._config, config);
+            } else if (config.parentLocale != null) {
+                if (locales[config.parentLocale] != null) {
+                    config = mergeConfigs(locales[config.parentLocale]._config, config);
                 } else {
-                    this['_' + i] = prop;
+                    // treat as if there is no base config
+                    deprecateSimple('parentLocaleUndefined',
+                            'specified parentLocale is not defined yet');
                 }
             }
-        },
-
-        _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
-        months : function (m) {
-            return this._months[m.month()];
-        },
+            locales[name] = new Locale(config);
 
-        _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
-        monthsShort : function (m) {
-            return this._monthsShort[m.month()];
-        },
+            // backwards compat for now: also set the locale
+            locale_locales__getSetGlobalLocale(name);
 
-        monthsParse : function (monthName) {
-            var i, mom, regex;
+            return locales[name];
+        } else {
+            // useful for testing
+            delete locales[name];
+            return null;
+        }
+    }
 
-            if (!this._monthsParse) {
-                this._monthsParse = [];
+    function updateLocale(name, config) {
+        if (config != null) {
+            var locale;
+            if (locales[name] != null) {
+                config = mergeConfigs(locales[name]._config, config);
             }
+            locale = new Locale(config);
+            locale.parentLocale = locales[name];
+            locales[name] = locale;
 
-            for (i = 0; i < 12; i++) {
-                // make the regex if we don't have it already
-                if (!this._monthsParse[i]) {
-                    mom = moment.utc([2000, i]);
-                    regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
-                    this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
-                }
-                // test the regex
-                if (this._monthsParse[i].test(monthName)) {
-                    return i;
+            // backwards compat for now: also set the locale
+            locale_locales__getSetGlobalLocale(name);
+        } else {
+            // pass null for config to unupdate, useful for tests
+            if (locales[name] != null) {
+                if (locales[name].parentLocale != null) {
+                    locales[name] = locales[name].parentLocale;
+                } else if (locales[name] != null) {
+                    delete locales[name];
                 }
             }
-        },
-
-        _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
-        weekdays : function (m) {
-            return this._weekdays[m.day()];
-        },
+        }
+        return locales[name];
+    }
 
-        _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
-        weekdaysShort : function (m) {
-            return this._weekdaysShort[m.day()];
-        },
+    // returns locale data
+    function locale_locales__getLocale (key) {
+        var locale;
 
-        _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
-        weekdaysMin : function (m) {
-            return this._weekdaysMin[m.day()];
-        },
+        if (key && key._locale && key._locale._abbr) {
+            key = key._locale._abbr;
+        }
 
-        weekdaysParse : function (weekdayName) {
-            var i, mom, regex;
+        if (!key) {
+            return globalLocale;
+        }
 
-            if (!this._weekdaysParse) {
-                this._weekdaysParse = [];
+        if (!isArray(key)) {
+            //short-circuit everything else
+            locale = loadLocale(key);
+            if (locale) {
+                return locale;
             }
+            key = [key];
+        }
 
-            for (i = 0; i < 7; i++) {
-                // make the regex if we don't have it already
-                if (!this._weekdaysParse[i]) {
-                    mom = moment([2000, 1]).day(i);
-                    regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
-                    this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
-                }
-                // test the regex
-                if (this._weekdaysParse[i].test(weekdayName)) {
-                    return i;
-                }
-            }
-        },
+        return chooseLocale(key);
+    }
 
-        _longDateFormat : {
-            LT : "h:mm A",
-            L : "MM/DD/YYYY",
-            LL : "MMMM D YYYY",
-            LLL : "MMMM D YYYY LT",
-            LLLL : "dddd, MMMM D YYYY LT"
-        },
-        longDateFormat : function (key) {
-            var output = this._longDateFormat[key];
-            if (!output && this._longDateFormat[key.toUpperCase()]) {
-                output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
-                    return val.slice(1);
-                });
-                this._longDateFormat[key] = output;
-            }
-            return output;
-        },
-
-        isPM : function (input) {
-            // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
-            // Using charAt should be more compatible.
-            return ((input + '').toLowerCase().charAt(0) === 'p');
-        },
+    function locale_locales__listLocales() {
+        return keys(locales);
+    }
 
-        _meridiemParse : /[ap]\.?m?\.?/i,
-        meridiem : function (hours, minutes, isLower) {
-            if (hours > 11) {
-                return isLower ? 'pm' : 'PM';
-            } else {
-                return isLower ? 'am' : 'AM';
-            }
-        },
+    var aliases = {};
 
-        _calendar : {
-            sameDay : '[Today at] LT',
-            nextDay : '[Tomorrow at] LT',
-            nextWeek : 'dddd [at] LT',
-            lastDay : '[Yesterday at] LT',
-            lastWeek : '[Last] dddd [at] LT',
-            sameElse : 'L'
-        },
-        calendar : function (key, mom) {
-            var output = this._calendar[key];
-            return typeof output === 'function' ? output.apply(mom) : output;
-        },
+    function addUnitAlias (unit, shorthand) {
+        var lowerCase = unit.toLowerCase();
+        aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
+    }
 
-        _relativeTime : {
-            future : "in %s",
-            past : "%s ago",
-            s : "a few 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"
-        },
-        relativeTime : function (number, withoutSuffix, string, isFuture) {
-            var output = this._relativeTime[string];
-            return (typeof output === 'function') ?
-                output(number, withoutSuffix, string, isFuture) :
-                output.replace(/%d/i, number);
-        },
-        pastFuture : function (diff, output) {
-            var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
-            return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
-        },
+    function normalizeUnits(units) {
+        return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
+    }
 
-        ordinal : function (number) {
-            return this._ordinal.replace("%d", number);
-        },
-        _ordinal : "%d",
+    function normalizeObjectUnits(inputObject) {
+        var normalizedInput = {},
+            normalizedProp,
+            prop;
 
-        preparse : function (string) {
-            return string;
-        },
+        for (prop in inputObject) {
+            if (hasOwnProp(inputObject, prop)) {
+                normalizedProp = normalizeUnits(prop);
+                if (normalizedProp) {
+                    normalizedInput[normalizedProp] = inputObject[prop];
+                }
+            }
+        }
 
-        postformat : function (string) {
-            return string;
-        },
+        return normalizedInput;
+    }
 
-        week : function (mom) {
-            return weekOfYear(mom, this._week.dow, this._week.doy).week;
-        },
+    function makeGetSet (unit, keepTime) {
+        return function (value) {
+            if (value != null) {
+                get_set__set(this, unit, value);
+                utils_hooks__hooks.updateOffset(this, keepTime);
+                return this;
+            } else {
+                return get_set__get(this, unit);
+            }
+        };
+    }
 
-        _week : {
-            dow : 0, // Sunday is the first day of the week.
-            doy : 6  // The week that contains Jan 1st is the first week of the year.
-        },
+    function get_set__get (mom, unit) {
+        return mom.isValid() ?
+            mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
+    }
 
-        _invalidDate: 'Invalid date',
-        invalidDate: function () {
-            return this._invalidDate;
+    function get_set__set (mom, unit, value) {
+        if (mom.isValid()) {
+            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
         }
-    });
+    }
 
-    // Loads a language definition into the `languages` cache.  The function
-    // takes a key and optionally values.  If not in the browser and no values
-    // are provided, it will load the language file module.  As a convenience,
-    // this function also returns the language values.
-    function loadLang(key, values) {
-        values.abbr = key;
-        if (!languages[key]) {
-            languages[key] = new Language();
+    // MOMENTS
+
+    function getSet (units, value) {
+        var unit;
+        if (typeof units === 'object') {
+            for (unit in units) {
+                this.set(unit, units[unit]);
+            }
+        } else {
+            units = normalizeUnits(units);
+            if (isFunction(this[units])) {
+                return this[units](value);
+            }
         }
-        languages[key].set(values);
-        return languages[key];
+        return this;
     }
 
-    // Remove a language from the `languages` cache. Mostly useful in tests.
-    function unloadLang(key) {
-        delete languages[key];
+    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;
     }
 
-    // Determines which language definition to use and returns it.
-    //
-    // With no parameters, it will return the global language.  If you
-    // pass in a language key, such as 'en', it will return the
-    // definition for 'en', so long as 'en' has already been loaded using
-    // moment.lang.
-    function getLangDefinition(key) {
-        var i = 0, j, lang, next, split,
-            get = function (k) {
-                if (!languages[k] && hasModule) {
-                    try {
-                        require('./lang/' + k);
-                    } catch (e) { }
-                }
-                return languages[k];
-            };
+    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;
 
-        if (!key) {
-            return moment.fn._lang;
-        }
+    var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
 
-        if (!isArray(key)) {
-            //short-circuit everything else
-            lang = get(key);
-            if (lang) {
-                return lang;
-            }
-            key = [key];
-        }
+    var formatFunctions = {};
 
-        //pick the language from the array
-        //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
-        //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
-        while (i < key.length) {
-            split = normalizeLanguage(key[i]).split('-');
-            j = split.length;
-            next = normalizeLanguage(key[i + 1]);
-            next = next ? next.split('-') : null;
-            while (j > 0) {
-                lang = get(split.slice(0, j).join('-'));
-                if (lang) {
-                    return lang;
-                }
-                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
-                    //the next array item is better than a shallower substring of this one
-                    break;
-                }
-                j--;
-            }
-            i++;
+    var formatTokenFunctions = {};
+
+    // token:    'M'
+    // padded:   ['MM', 2]
+    // ordinal:  'Mo'
+    // callback: function () { this.month() + 1 }
+    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);
+            };
         }
-        return moment.fn._lang;
     }
 
-    /************************************
-        Formatting
-    ************************************/
-
-
     function removeFormattingTokens(input) {
         if (input.match(/\[[\s\S]/)) {
-            return input.replace(/^\[|\]$/g, "");
+            return input.replace(/^\[|\]$/g, '');
         }
-        return input.replace(/\\/g, "");
+        return input.replace(/\\/g, '');
     }
 
     function makeFormatFunction(format) {
@@ -2400,7 +2168,7 @@ if (typeof define === 'function' && define.amd) {
         }
 
         return function (mom) {
-            var output = "";
+            var output = '', i;
             for (i = 0; i < length; i++) {
                 output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
             }
@@ -2410,25 +2178,21 @@ if (typeof define === 'function' && define.amd) {
 
     // format date using native date object
     function formatMoment(m, format) {
-
         if (!m.isValid()) {
-            return m.lang().invalidDate();
+            return m.localeData().invalidDate();
         }
 
-        format = expandFormat(format, m.lang());
-
-        if (!formatFunctions[format]) {
-            formatFunctions[format] = makeFormatFunction(format);
-        }
+        format = expandFormat(format, m.localeData());
+        formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
 
         return formatFunctions[format](m);
     }
 
-    function expandFormat(format, lang) {
+    function expandFormat(format, locale) {
         var i = 5;
 
         function replaceLongDateFormatTokens(input) {
-            return lang.longDateFormat(input) || input;
+            return locale.longDateFormat(input) || input;
         }
 
         localFormattingTokens.lastIndex = 0;
@@ -2441,1455 +2205,3367 @@ if (typeof define === 'function' && define.amd) {
         return format;
     }
 
+    var match1         = /\d/;            //       0 - 9
+    var match2         = /\d\d/;          //      00 - 99
+    var match3         = /\d{3}/;         //     000 - 999
+    var match4         = /\d{4}/;         //    0000 - 9999
+    var match6         = /[+-]?\d{6}/;    // -999999 - 999999
+    var match1to2      = /\d\d?/;         //       0 - 99
+    var match3to4      = /\d\d\d\d?/;     //     999 - 9999
+    var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
+    var match1to3      = /\d{1,3}/;       //       0 - 999
+    var match1to4      = /\d{1,4}/;       //       0 - 9999
+    var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
 
-    /************************************
-        Parsing
-    ************************************/
-
-
-    // get the regex to find the next token
-    function getParseRegexForToken(token, config) {
-        var a, strict = config._strict;
-        switch (token) {
-        case 'DDDD':
-            return parseTokenThreeDigits;
-        case 'YYYY':
-        case 'GGGG':
-        case 'gggg':
-            return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
-        case 'YYYYYY':
-        case 'YYYYY':
-        case 'GGGGG':
-        case 'ggggg':
-            return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
-        case 'S':
-            if (strict) { return parseTokenOneDigit; }
-            /* falls through */
-        case 'SS':
-            if (strict) { return parseTokenTwoDigits; }
-            /* falls through */
-        case 'SSS':
-        case 'DDD':
-            return strict ? parseTokenThreeDigits : parseTokenOneToThreeDigits;
-        case 'MMM':
-        case 'MMMM':
-        case 'dd':
-        case 'ddd':
-        case 'dddd':
-            return parseTokenWord;
-        case 'a':
-        case 'A':
-            return getLangDefinition(config._l)._meridiemParse;
-        case 'X':
-            return parseTokenTimestampMs;
-        case 'Z':
-        case 'ZZ':
-            return parseTokenTimezone;
-        case 'T':
-            return parseTokenT;
-        case 'SSSS':
-            return parseTokenDigits;
-        case 'MM':
-        case 'DD':
-        case 'YY':
-        case 'GG':
-        case 'gg':
-        case 'HH':
-        case 'hh':
-        case 'mm':
-        case 'ss':
-        case 'ww':
-        case 'WW':
-            return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
-        case 'M':
-        case 'D':
-        case 'd':
-        case 'H':
-        case 'h':
-        case 'm':
-        case 's':
-        case 'w':
-        case 'W':
-        case 'e':
-        case 'E':
-            return strict ? parseTokenOneDigit : parseTokenOneOrTwoDigits;
-        default :
-            a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
-            return a;
-        }
+    var matchUnsigned  = /\d+/;           //       0 - inf
+    var matchSigned    = /[+-]?\d+/;      //    -inf - inf
+
+    var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
+    var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
+
+    var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
+
+    // any word (or two) characters or numbers including two/three word month in arabic.
+    // includes scottish gaelic two word and hyphenated months
+    var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
+
+
+    var regexes = {};
+
+    function addRegexToken (token, regex, strictRegex) {
+        regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
+            return (isStrict && strictRegex) ? strictRegex : regex;
+        };
     }
 
-    function timezoneMinutesFromString(string) {
-        string = string || "";
-        var possibleTzMatches = (string.match(parseTokenTimezone) || []),
-            tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
-            parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
-            minutes = +(parts[1] * 60) + toInt(parts[2]);
+    function getParseRegexForToken (token, config) {
+        if (!hasOwnProp(regexes, token)) {
+            return new RegExp(unescapeFormat(token));
+        }
+
+        return regexes[token](config._strict, config._locale);
+    }
 
-        return parts[0] === '+' ? -minutes : minutes;
+    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+    function unescapeFormat(s) {
+        return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
+            return p1 || p2 || p3 || p4;
+        }));
     }
 
-    // function to convert string input to date
-    function addTimeToArrayFromToken(token, input, config) {
-        var a, datePartArray = config._a;
+    function regexEscape(s) {
+        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+    }
 
-        switch (token) {
-        // MONTH
-        case 'M' : // fall through to MM
-        case 'MM' :
-            if (input != null) {
-                datePartArray[MONTH] = toInt(input) - 1;
-            }
-            break;
-        case 'MMM' : // fall through to MMMM
-        case 'MMMM' :
-            a = getLangDefinition(config._l).monthsParse(input);
-            // if we didn't find a month name, mark the date as invalid.
-            if (a != null) {
-                datePartArray[MONTH] = a;
-            } else {
-                config._pf.invalidMonth = input;
-            }
-            break;
-        // DAY OF MONTH
-        case 'D' : // fall through to DD
-        case 'DD' :
-            if (input != null) {
-                datePartArray[DATE] = toInt(input);
-            }
-            break;
-        // DAY OF YEAR
-        case 'DDD' : // fall through to DDDD
-        case 'DDDD' :
-            if (input != null) {
-                config._dayOfYear = toInt(input);
-            }
+    var tokens = {};
 
-            break;
-        // YEAR
-        case 'YY' :
-            datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
-            break;
-        case 'YYYY' :
-        case 'YYYYY' :
-        case 'YYYYYY' :
-            datePartArray[YEAR] = toInt(input);
-            break;
-        // AM / PM
-        case 'a' : // fall through to A
-        case 'A' :
-            config._isPm = getLangDefinition(config._l).isPM(input);
-            break;
-        // 24 HOUR
-        case 'H' : // fall through to hh
-        case 'HH' : // fall through to hh
-        case 'h' : // fall through to hh
-        case 'hh' :
-            datePartArray[HOUR] = toInt(input);
-            break;
-        // MINUTE
-        case 'm' : // fall through to mm
-        case 'mm' :
-            datePartArray[MINUTE] = toInt(input);
-            break;
-        // SECOND
-        case 's' : // fall through to ss
-        case 'ss' :
-            datePartArray[SECOND] = toInt(input);
-            break;
-        // MILLISECOND
-        case 'S' :
-        case 'SS' :
-        case 'SSS' :
-        case 'SSSS' :
-            datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
-            break;
-        // UNIX TIMESTAMP WITH MS
-        case 'X':
-            config._d = new Date(parseFloat(input) * 1000);
-            break;
-        // TIMEZONE
-        case 'Z' : // fall through to ZZ
-        case 'ZZ' :
-            config._useUTC = true;
-            config._tzm = timezoneMinutesFromString(input);
-            break;
-        case 'w':
-        case 'ww':
-        case 'W':
-        case 'WW':
-        case 'd':
-        case 'dd':
-        case 'ddd':
-        case 'dddd':
-        case 'e':
-        case 'E':
-            token = token.substr(0, 1);
-            /* falls through */
-        case 'gg':
-        case 'gggg':
-        case 'GG':
-        case 'GGGG':
-        case 'GGGGG':
-            token = token.substr(0, 2);
-            if (input) {
-                config._w = config._w || {};
-                config._w[token] = input;
-            }
-            break;
+    function addParseToken (token, callback) {
+        var i, func = callback;
+        if (typeof token === 'string') {
+            token = [token];
+        }
+        if (typeof callback === 'number') {
+            func = function (input, array) {
+                array[callback] = toInt(input);
+            };
+        }
+        for (i = 0; i < token.length; i++) {
+            tokens[token[i]] = func;
         }
     }
 
-    // convert an array to a date.
-    // the array should mirror the parameters below
-    // note: all values past the year are optional and will default to the lowest possible value.
-    // [year, month, day , hour, minute, second, millisecond]
-    function dateFromConfig(config) {
-        var i, date, input = [], currentDate,
-            yearToUse, fixYear, w, temp, lang, weekday, week;
+    function addWeekParseToken (token, callback) {
+        addParseToken(token, function (input, array, config, token) {
+            config._w = config._w || {};
+            callback(input, config._w, config, token);
+        });
+    }
 
-        if (config._d) {
-            return;
+    function addTimeToArrayFromToken(token, input, config) {
+        if (input != null && hasOwnProp(tokens, token)) {
+            tokens[token](input, config._a, config, token);
         }
+    }
 
-        currentDate = currentDateArray(config);
+    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;
 
-        //compute day of the year from weeks and weekdays
-        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
-            fixYear = function (val) {
-                var int_val = parseInt(val, 10);
-                return val ?
-                  (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) :
-                  (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
-            };
+    var indexOf;
 
-            w = config._w;
-            if (w.GG != null || w.W != null || w.E != null) {
-                temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1);
+    if (Array.prototype.indexOf) {
+        indexOf = Array.prototype.indexOf;
+    } else {
+        indexOf = function (o) {
+            // I know
+            var i;
+            for (i = 0; i < this.length; ++i) {
+                if (this[i] === o) {
+                    return i;
+                }
             }
-            else {
-                lang = getLangDefinition(config._l);
-                weekday = w.d != null ?  parseWeekday(w.d, lang) :
-                  (w.e != null ?  parseInt(w.e, 10) + lang._week.dow : 0);
+            return -1;
+        };
+    }
 
-                week = parseInt(w.w, 10) || 1;
+    function daysInMonth(year, month) {
+        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
+    }
 
-                //if we're parsing 'd', then the low day numbers may be next week
-                if (w.d != null && weekday < lang._week.dow) {
-                    week++;
-                }
+    // FORMATTING
 
-                temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow);
-            }
+    addFormatToken('M', ['MM', 2], 'Mo', function () {
+        return this.month() + 1;
+    });
 
-            config._a[YEAR] = temp.year;
-            config._dayOfYear = temp.dayOfYear;
-        }
+    addFormatToken('MMM', 0, 0, function (format) {
+        return this.localeData().monthsShort(this, format);
+    });
 
-        //if the day of the year is set, figure out what it is
-        if (config._dayOfYear) {
-            yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
+    addFormatToken('MMMM', 0, 0, function (format) {
+        return this.localeData().months(this, format);
+    });
 
-            if (config._dayOfYear > daysInYear(yearToUse)) {
-                config._pf._overflowDayOfYear = true;
-            }
+    // ALIASES
 
-            date = makeUTCDate(yearToUse, 0, config._dayOfYear);
-            config._a[MONTH] = date.getUTCMonth();
-            config._a[DATE] = date.getUTCDate();
-        }
+    addUnitAlias('month', 'M');
 
-        // Default to current date.
-        // * if no year, month, day of month are given, default to today
-        // * if day of month is given, default month and year
-        // * if month is given, default only year
-        // * if year is given, don't default anything
-        for (i = 0; i < 3 && config._a[i] == null; ++i) {
-            config._a[i] = input[i] = currentDate[i];
-        }
+    // PARSING
 
-        // Zero out whatever was not defaulted, including time
-        for (; i < 7; i++) {
-            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
+    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 we didn't find a month name, mark the date as invalid.
+        if (month != null) {
+            array[MONTH] = month;
+        } else {
+            getParsingFlags(config).invalidMonth = input;
         }
+    });
 
-        // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
-        input[HOUR] += toInt((config._tzm || 0) / 60);
-        input[MINUTE] += toInt((config._tzm || 0) % 60);
+    // LOCALES
 
-        config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, 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) {
+        return isArray(this._months) ? this._months[m.month()] :
+            this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
     }
 
-    function dateFromObject(config) {
-        var normalizedInput;
+    var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
+    function localeMonthsShort (m, format) {
+        return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
+            this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
+    }
 
-        if (config._d) {
-            return;
+    function units_month__handleStrictParse(monthName, format, strict) {
+        var i, ii, mom, llc = monthName.toLocaleLowerCase();
+        if (!this._monthsParse) {
+            // this is not used
+            this._monthsParse = [];
+            this._longMonthsParse = [];
+            this._shortMonthsParse = [];
+            for (i = 0; i < 12; ++i) {
+                mom = create_utc__createUTC([2000, i]);
+                this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
+                this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
+            }
         }
 
-        normalizedInput = normalizeObjectUnits(config._i);
-        config._a = [
-            normalizedInput.year,
-            normalizedInput.month,
-            normalizedInput.day,
-            normalizedInput.hour,
-            normalizedInput.minute,
-            normalizedInput.second,
-            normalizedInput.millisecond
-        ];
-
-        dateFromConfig(config);
-    }
-
-    function currentDateArray(config) {
-        var now = new Date();
-        if (config._useUTC) {
-            return [
-                now.getUTCFullYear(),
-                now.getUTCMonth(),
-                now.getUTCDate()
-            ];
+        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 {
-            return [now.getFullYear(), now.getMonth(), now.getDate()];
+            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;
+            }
         }
     }
 
-    // date from string and format string
-    function makeDateFromStringAndFormat(config) {
-
-        config._a = [];
-        config._pf.empty = true;
+    function localeMonthsParse (monthName, format, strict) {
+        var i, mom, regex;
 
-        // This array is used to make a Date, either with `new Date` or `Date.UTC`
-        var lang = getLangDefinition(config._l),
-            string = '' + config._i,
-            i, parsedInput, tokens, token, skipped,
-            stringLength = string.length,
-            totalParsedInputLength = 0;
+        if (this._monthsParseExact) {
+            return units_month__handleStrictParse.call(this, monthName, format, strict);
+        }
 
-        tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
+        if (!this._monthsParse) {
+            this._monthsParse = [];
+            this._longMonthsParse = [];
+            this._shortMonthsParse = [];
+        }
 
-        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) {
-                    config._pf.unusedInput.push(skipped);
-                }
-                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
-                totalParsedInputLength += parsedInput.length;
+        // TODO: add sorting
+        // Sorting makes sure if one month (or abbr) is a prefix of another
+        // see sorting in computeMonthsParse
+        for (i = 0; i < 12; i++) {
+            // make the regex if we don't have it already
+            mom = create_utc__createUTC([2000, 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');
             }
-            // don't parse if it's not a known token
-            if (formatTokenFunctions[token]) {
-                if (parsedInput) {
-                    config._pf.empty = false;
-                }
-                else {
-                    config._pf.unusedTokens.push(token);
-                }
-                addTimeToArrayFromToken(token, parsedInput, config);
+            if (!strict && !this._monthsParse[i]) {
+                regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
+                this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
             }
-            else if (config._strict && !parsedInput) {
-                config._pf.unusedTokens.push(token);
+            // test the regex
+            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;
             }
         }
+    }
 
-        // add remaining unparsed input length to the string
-        config._pf.charsLeftOver = stringLength - totalParsedInputLength;
-        if (string.length > 0) {
-            config._pf.unusedInput.push(string);
-        }
+    // MOMENTS
 
-        // handle am pm
-        if (config._isPm && config._a[HOUR] < 12) {
-            config._a[HOUR] += 12;
+    function setMonth (mom, value) {
+        var dayOfMonth;
+
+        if (!mom.isValid()) {
+            // No op
+            return mom;
         }
-        // if is 12 am, change hours to 0
-        if (config._isPm === false && config._a[HOUR] === 12) {
-            config._a[HOUR] = 0;
+
+        if (typeof value === 'string') {
+            if (/^\d+$/.test(value)) {
+                value = toInt(value);
+            } else {
+                value = mom.localeData().monthsParse(value);
+                // TODO: Another silent failure?
+                if (typeof value !== 'number') {
+                    return mom;
+                }
+            }
         }
 
-        dateFromConfig(config);
-        checkOverflow(config);
+        dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
+        mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
+        return mom;
     }
 
-    function unescapeFormat(s) {
-        return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
-            return p1 || p2 || p3 || p4;
-        });
+    function getSetMonth (value) {
+        if (value != null) {
+            setMonth(this, value);
+            utils_hooks__hooks.updateOffset(this, true);
+            return this;
+        } else {
+            return get_set__get(this, 'Month');
+        }
     }
 
-    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
-    function regexpEscape(s) {
-        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+    function getDaysInMonth () {
+        return daysInMonth(this.year(), this.month());
     }
 
-    // date from string and array of format strings
-    function makeDateFromStringAndArray(config) {
-        var tempConfig,
-            bestMoment,
+    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 {
+            return this._monthsShortStrictRegex && isStrict ?
+                this._monthsShortStrictRegex : this._monthsShortRegex;
+        }
+    }
 
-            scoreToBeat,
-            i,
-            currentScore;
-
-        if (config._f.length === 0) {
-            config._pf.invalidFormat = true;
-            config._d = new Date(NaN);
-            return;
+    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 {
+            return this._monthsStrictRegex && isStrict ?
+                this._monthsStrictRegex : this._monthsRegex;
         }
+    }
 
-        for (i = 0; i < config._f.length; i++) {
-            currentScore = 0;
-            tempConfig = extend({}, config);
-            initializeParsingFlags(tempConfig);
-            tempConfig._f = config._f[i];
-            makeDateFromStringAndFormat(tempConfig);
+    function computeMonthsParse () {
+        function cmpLenRev(a, b) {
+            return b.length - a.length;
+        }
 
-            if (!isValid(tempConfig)) {
-                continue;
-            }
+        var shortPieces = [], longPieces = [], mixedPieces = [],
+            i, mom;
+        for (i = 0; i < 12; i++) {
+            // make the regex if we don't have it already
+            mom = create_utc__createUTC([2000, i]);
+            shortPieces.push(this.monthsShort(mom, ''));
+            longPieces.push(this.months(mom, ''));
+            mixedPieces.push(this.months(mom, ''));
+            mixedPieces.push(this.monthsShort(mom, ''));
+        }
+        // Sorting makes sure if one month (or abbr) is a prefix of another it
+        // will match the longer piece.
+        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]);
+            mixedPieces[i] = regexEscape(mixedPieces[i]);
+        }
 
-            // if there is any input that was not parsed add a penalty for that format
-            currentScore += tempConfig._pf.charsLeftOver;
+        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');
+    }
 
-            //or tokens
-            currentScore += tempConfig._pf.unusedTokens.length * 10;
+    function checkOverflow (m) {
+        var overflow;
+        var a = m._a;
 
-            tempConfig._pf.score = currentScore;
+        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 (scoreToBeat == null || currentScore < scoreToBeat) {
-                scoreToBeat = currentScore;
-                bestMoment = tempConfig;
+            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;
         }
 
-        extend(config, bestMoment || tempConfig);
+        return m;
     }
 
+    // iso 8601 regex
+    // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
+    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}/],
+        // YYYYMM is NOT allowed by the standard
+        ['GGGG[W]WWE', /\d{4}W\d{3}/],
+        ['GGGG[W]WW', /\d{4}W\d{2}/, false],
+        ['YYYYDDD', /\d{7}/]
+    ];
+
+    // iso time formats and regexes
+    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;
+
     // date from iso format
-    function makeDateFromString(config) {
-        var i,
+    function configFromISO(config) {
+        var i, l,
             string = config._i,
-            match = isoRegex.exec(string);
+            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
+            allowTime, dateFormat, timeFormat, tzFormat;
 
         if (match) {
-            config._pf.iso = true;
-            for (i = 4; i > 0; i--) {
-                if (match[i]) {
-                    // match[5] should be "T" or undefined
-                    config._f = isoDates[i - 1] + (match[6] || " ");
+            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;
                 }
             }
-            for (i = 0; i < 4; i++) {
-                if (isoTimes[i][1].exec(string)) {
-                    config._f += isoTimes[i][0];
-                    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])) {
+                        // match[2] should be 'T' or space
+                        timeFormat = (match[2] || ' ') + isoTimes[i][0];
+                        break;
+                    }
+                }
+                if (timeFormat == null) {
+                    config._isValid = false;
+                    return;
                 }
             }
-            if (string.match(parseTokenTimezone)) {
-                config._f += "Z";
+            if (!allowTime && timeFormat != null) {
+                config._isValid = false;
+                return;
             }
-            makeDateFromStringAndFormat(config);
-        }
-        else {
-            config._d = new Date(string);
+            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;
         }
     }
 
-    function makeDateFromInput(config) {
-        var input = config._i,
-            matched = aspNetJsonRegex.exec(input);
+    // date from iso format or fallback
+    function configFromString(config) {
+        var matched = aspNetJsonRegex.exec(config._i);
 
-        if (input === undefined) {
-            config._d = new Date();
-        } else if (matched) {
+        if (matched !== null) {
             config._d = new Date(+matched[1]);
-        } else if (typeof input === 'string') {
-            makeDateFromString(config);
-        } else if (isArray(input)) {
-            config._a = input.slice(0);
-            dateFromConfig(config);
-        } else if (isDate(input)) {
-            config._d = new Date(+input);
-        } else if (typeof(input) === 'object') {
-            dateFromObject(config);
-        } else {
-            config._d = new Date(input);
+            return;
+        }
+
+        configFromISO(config);
+        if (config._isValid === false) {
+            delete config._isValid;
+            utils_hooks__hooks.createFromInputFallback(config);
         }
     }
 
-    function makeDate(y, m, d, h, M, s, ms) {
+    utils_hooks__hooks.createFromInputFallback = deprecate(
+        'moment construction falls back to js Date. This is ' +
+        'discouraged and will be removed in upcoming major ' +
+        'release. Please refer to ' +
+        'https://github.com/moment/moment/issues/1407 for more info.',
+        function (config) {
+            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
+        }
+    );
+
+    function createDate (y, m, d, h, M, s, ms) {
         //can't just apply() to create a date:
         //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
         var date = new Date(y, m, d, h, M, s, ms);
 
-        //the date constructor doesn't accept years < 1970
-        if (y < 1970) {
+        //the date constructor remaps years 0-99 to 1900-1999
+        if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
             date.setFullYear(y);
         }
         return date;
     }
 
-    function makeUTCDate(y) {
+    function createUTCDate (y) {
         var date = new Date(Date.UTC.apply(null, arguments));
-        if (y < 1970) {
+
+        //the Date.UTC function remaps years 0-99 to 1900-1999
+        if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
             date.setUTCFullYear(y);
         }
         return date;
     }
 
-    function parseWeekday(input, language) {
-        if (typeof input === 'string') {
-            if (!isNaN(input)) {
-                input = parseInt(input, 10);
-            }
-            else {
-                input = language.weekdaysParse(input);
-                if (typeof input !== 'number') {
-                    return null;
-                }
-            }
-        }
-        return input;
-    }
+    // FORMATTING
+
+    addFormatToken('Y', 0, 0, function () {
+        var y = this.year();
+        return y <= 9999 ? '' + y : '+' + y;
+    });
 
-    /************************************
-        Relative Time
-    ************************************/
+    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');
 
-    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
-    function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
-        return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+    // ALIASES
+
+    addUnitAlias('year', 'y');
+
+    // PARSING
+
+    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 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
+    });
+    addParseToken('YY', function (input, array) {
+        array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
+    });
+    addParseToken('Y', function (input, array) {
+        array[YEAR] = parseInt(input, 10);
+    });
+
+    // HELPERS
+
+    function daysInYear(year) {
+        return isLeapYear(year) ? 366 : 365;
     }
 
-    function relativeTime(milliseconds, withoutSuffix, lang) {
-        var seconds = round(Math.abs(milliseconds) / 1000),
-            minutes = round(seconds / 60),
-            hours = round(minutes / 60),
-            days = round(hours / 24),
-            years = round(days / 365),
-            args = seconds < 45 && ['s', seconds] ||
-                minutes === 1 && ['m'] ||
-                minutes < 45 && ['mm', minutes] ||
-                hours === 1 && ['h'] ||
-                hours < 22 && ['hh', hours] ||
-                days === 1 && ['d'] ||
-                days <= 25 && ['dd', days] ||
-                days <= 45 && ['M'] ||
-                days < 345 && ['MM', round(days / 30)] ||
-                years === 1 && ['y'] || ['yy', years];
-        args[2] = withoutSuffix;
-        args[3] = milliseconds > 0;
-        args[4] = lang;
-        return substituteTimeAgo.apply({}, args);
+    function isLeapYear(year) {
+        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
     }
 
+    // HOOKS
+
+    utils_hooks__hooks.parseTwoDigitYear = function (input) {
+        return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
+    };
 
-    /************************************
-        Week of Year
-    ************************************/
+    // MOMENTS
 
+    var getSetYear = makeGetSet('FullYear', true);
 
-    // firstDayOfWeek       0 = sun, 6 = sat
-    //                      the day of the week that starts the week
-    //                      (usually sunday or monday)
-    // firstDayOfWeekOfYear 0 = sun, 6 = sat
-    //                      the first week is the week that contains the first
-    //                      of this day of the week
-    //                      (eg. ISO weeks use thursday (4))
-    function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
-        var end = firstDayOfWeekOfYear - firstDayOfWeek,
-            daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
-            adjustedMoment;
+    function getIsLeapYear () {
+        return isLeapYear(this.year());
+    }
 
+    // start-of-first-week - start-of-year
+    function firstWeekOffset(year, dow, doy) {
+        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
+            fwd = 7 + dow - doy,
+            // first-week day local weekday -- which local weekday is fwd
+            fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
 
-        if (daysToDayOfWeek > end) {
-            daysToDayOfWeek -= 7;
-        }
+        return -fwdlw + fwd - 1;
+    }
 
-        if (daysToDayOfWeek < end - 7) {
-            daysToDayOfWeek += 7;
+    //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
+    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;
         }
 
-        adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
         return {
-            week: Math.ceil(adjustedMoment.dayOfYear() / 7),
-            year: adjustedMoment.year()
+            year: resYear,
+            dayOfYear: resDayOfYear
         };
     }
 
-    //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
-    function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
-        // The only solid way to create an iso date from year is to use
-        // a string format (Date.UTC handles only years > 1900). Don't ask why
-        // it doesn't need Z at the end.
-        var d = new Date(leftZeroFill(year, 6, true) + '-01-01').getUTCDay(),
-            daysToAdd, dayOfYear;
+    function weekOfYear(mom, dow, doy) {
+        var weekOffset = firstWeekOffset(mom.year(), dow, doy),
+            week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
+            resWeek, resYear;
 
-        weekday = weekday != null ? weekday : firstDayOfWeek;
-        daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0);
-        dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
+        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 {
-            year: dayOfYear > 0 ? year : year - 1,
-            dayOfYear: dayOfYear > 0 ?  dayOfYear : daysInYear(year - 1) + dayOfYear
+            week: resWeek,
+            year: resYear
         };
     }
 
-    /************************************
-        Top Level Functions
-    ************************************/
+    function weeksInYear(year, dow, doy) {
+        var weekOffset = firstWeekOffset(year, dow, doy),
+            weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
+        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
+    }
 
-    function makeMoment(config) {
-        var input = config._i,
-            format = config._f;
+    // Pick the first defined of two or three arguments.
+    function defaults(a, b, c) {
+        if (a != null) {
+            return a;
+        }
+        if (b != null) {
+            return b;
+        }
+        return c;
+    }
 
-        if (typeof config._pf === 'undefined') {
-            initializeParsingFlags(config);
+    function currentDateArray(config) {
+        // hooks is actually the exported moment object
+        var nowValue = new Date(utils_hooks__hooks.now());
+        if (config._useUTC) {
+            return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
         }
+        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
+    }
+
+    // convert an array to a date.
+    // the array should mirror the parameters below
+    // note: all values past the year are optional and will default to the lowest possible value.
+    // [year, month, day , hour, minute, second, millisecond]
+    function configFromArray (config) {
+        var i, date, input = [], currentDate, yearToUse;
 
-        if (input === null) {
-            return moment.invalid({nullInput: true});
+        if (config._d) {
+            return;
         }
 
-        if (typeof input === 'string') {
-            config._i = input = getLangDefinition().preparse(input);
+        currentDate = currentDateArray(config);
+
+        //compute day of the year from weeks and weekdays
+        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
+            dayOfYearFromWeekInfo(config);
         }
 
-        if (moment.isMoment(input)) {
-            config = extend({}, input);
+        //if the day of the year is set, figure out what it is
+        if (config._dayOfYear) {
+            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
 
-            config._d = new Date(+input._d);
-        } else if (format) {
-            if (isArray(format)) {
-                makeDateFromStringAndArray(config);
-            } else {
-                makeDateFromStringAndFormat(config);
+            if (config._dayOfYear > daysInYear(yearToUse)) {
+                getParsingFlags(config)._overflowDayOfYear = true;
             }
-        } else {
-            makeDateFromInput(config);
+
+            date = createUTCDate(yearToUse, 0, config._dayOfYear);
+            config._a[MONTH] = date.getUTCMonth();
+            config._a[DATE] = date.getUTCDate();
         }
 
-        return new Moment(config);
-    }
+        // Default to current date.
+        // * if no year, month, day of month are given, default to today
+        // * if day of month is given, default month and year
+        // * if month is given, default only year
+        // * if year is given, don't default anything
+        for (i = 0; i < 3 && config._a[i] == null; ++i) {
+            config._a[i] = input[i] = currentDate[i];
+        }
 
-    moment = function (input, format, lang, strict) {
-        if (typeof(lang) === "boolean") {
-            strict = lang;
-            lang = undefined;
+        // Zero out whatever was not defaulted, including time
+        for (; i < 7; i++) {
+            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
         }
-        return makeMoment({
-            _i : input,
-            _f : format,
-            _l : lang,
-            _strict : strict,
-            _isUTC : false
-        });
-    };
 
-    // creating with utc
-    moment.utc = function (input, format, lang, strict) {
-        var m;
+        // Check for 24:00:00.000
+        if (config._a[HOUR] === 24 &&
+                config._a[MINUTE] === 0 &&
+                config._a[SECOND] === 0 &&
+                config._a[MILLISECOND] === 0) {
+            config._nextDay = true;
+            config._a[HOUR] = 0;
+        }
 
-        if (typeof(lang) === "boolean") {
-            strict = lang;
-            lang = undefined;
+        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
+        // Apply timezone offset from input. The actual utcOffset can be changed
+        // with parseZone.
+        if (config._tzm != null) {
+            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
         }
-        m = makeMoment({
-            _useUTC : true,
-            _isUTC : true,
-            _l : lang,
-            _i : input,
-            _f : format,
-            _strict : strict
-        }).utc();
 
-        return m;
-    };
+        if (config._nextDay) {
+            config._a[HOUR] = 24;
+        }
+    }
 
-    // creating with unix timestamp (in seconds)
-    moment.unix = function (input) {
-        return moment(input * 1000);
-    };
+    function dayOfYearFromWeekInfo(config) {
+        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
 
-    // duration
-    moment.duration = function (input, key) {
-        var duration = input,
-            // matching against regexp is expensive, do it on demand
-            match = null,
-            sign,
-            ret,
-            parseIso;
+        w = config._w;
+        if (w.GG != null || w.W != null || w.E != null) {
+            dow = 1;
+            doy = 4;
 
-        if (moment.isDuration(input)) {
-            duration = {
-                ms: input._milliseconds,
-                d: input._days,
-                M: input._months
-            };
-        } else if (typeof input === 'number') {
-            duration = {};
-            if (key) {
-                duration[key] = input;
+            // TODO: We need to take the current isoWeekYear, but that depends on
+            // how we interpret now (local, utc, fixed offset). So create
+            // a now version of current config (take local/utc/offset flags, and
+            // create now).
+            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__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;
+
+            weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
+            week = defaults(w.w, 1);
+
+            if (w.d != null) {
+                // weekday -- low day numbers are considered next week
+                weekday = w.d;
+                if (weekday < 0 || weekday > 6) {
+                    weekdayOverflow = true;
+                }
+            } else if (w.e != null) {
+                // local weekday -- counting starts from begining of week
+                weekday = w.e + dow;
+                if (w.e < 0 || w.e > 6) {
+                    weekdayOverflow = true;
+                }
             } else {
-                duration.milliseconds = input;
+                // default to begining of week
+                weekday = dow;
             }
-        } else if (!!(match = aspNetTimeSpanJsonRegex.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(match[MILLISECOND]) * sign
-            };
-        } else if (!!(match = isoDurationRegex.exec(input))) {
-            sign = (match[1] === "-") ? -1 : 1;
-            parseIso = function (inp) {
-                // We'd normally use ~~inp for this, but unfortunately it also
-                // converts floats to ints.
-                // inp may be undefined, so careful calling replace on it.
-                var res = inp && parseFloat(inp.replace(',', '.'));
-                // apply sign while we're at it
-                return (isNaN(res) ? 0 : res) * sign;
-            };
-            duration = {
-                y: parseIso(match[2]),
-                M: parseIso(match[3]),
-                d: parseIso(match[4]),
-                h: parseIso(match[5]),
-                m: parseIso(match[6]),
-                s: parseIso(match[7]),
-                w: parseIso(match[8])
-            };
         }
+        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;
+        }
+    }
 
-        ret = new Duration(duration);
+    // constant that refers to the ISO standard
+    utils_hooks__hooks.ISO_8601 = function () {};
 
-        if (moment.isDuration(input) && input.hasOwnProperty('_lang')) {
-            ret._lang = input._lang;
+    // date from string and format string
+    function configFromStringAndFormat(config) {
+        // TODO: Move this to another part of the creation flow to prevent circular deps
+        if (config._f === utils_hooks__hooks.ISO_8601) {
+            configFromISO(config);
+            return;
         }
 
-        return ret;
-    };
+        config._a = [];
+        getParsingFlags(config).empty = true;
 
-    // version number
-    moment.version = VERSION;
+        // This array is used to make a Date, either with `new Date` or `Date.UTC`
+        var string = '' + config._i,
+            i, parsedInput, tokens, token, skipped,
+            stringLength = string.length,
+            totalParsedInputLength = 0;
 
-    // default format
-    moment.defaultFormat = isoFormat;
+        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
 
-    // This function will be called whenever a moment is mutated.
-    // It is intended to keep the offset in sync with the timezone.
-    moment.updateOffset = function () {};
+        for (i = 0; i < tokens.length; i++) {
+            token = tokens[i];
+            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
+            // console.log('token', token, 'parsedInput', parsedInput,
+            //         'regex', getParseRegexForToken(token, config));
+            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;
+            }
+            // don't parse if it's not a known token
+            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);
+            }
+        }
 
-    // This function will load languages and then set the global language.  If
-    // no arguments are passed in, it will simply return the current global
-    // language key.
-    moment.lang = function (key, values) {
-        var r;
-        if (!key) {
-            return moment.fn._lang._abbr;
-        }
-        if (values) {
-            loadLang(normalizeLanguage(key), values);
-        } else if (values === null) {
-            unloadLang(key);
-            key = 'en';
-        } else if (!languages[key]) {
-            getLangDefinition(key);
-        }
-        r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
-        return r._abbr;
-    };
+        // add remaining unparsed input length to the string
+        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
+        if (string.length > 0) {
+            getParsingFlags(config).unusedInput.push(string);
+        }
 
-    // returns language data
-    moment.langData = function (key) {
-        if (key && key._lang && key._lang._abbr) {
-            key = key._lang._abbr;
+        // clear _12h flag if hour is <= 12
+        if (getParsingFlags(config).bigHour === true &&
+                config._a[HOUR] <= 12 &&
+                config._a[HOUR] > 0) {
+            getParsingFlags(config).bigHour = undefined;
         }
-        return getLangDefinition(key);
-    };
 
-    // compare moment object
-    moment.isMoment = function (obj) {
-        return obj instanceof Moment;
-    };
+        getParsingFlags(config).parsedDateParts = config._a.slice(0);
+        getParsingFlags(config).meridiem = config._meridiem;
+        // handle meridiem
+        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
 
-    // for typechecking Duration objects
-    moment.isDuration = function (obj) {
-        return obj instanceof Duration;
-    };
+        configFromArray(config);
+        checkOverflow(config);
+    }
+
+
+    function meridiemFixWrap (locale, hour, meridiem) {
+        var isPm;
+
+        if (meridiem == null) {
+            // nothing to do
+            return hour;
+        }
+        if (locale.meridiemHour != null) {
+            return locale.meridiemHour(hour, meridiem);
+        } else if (locale.isPM != null) {
+            // Fallback
+            isPm = locale.isPM(meridiem);
+            if (isPm && hour < 12) {
+                hour += 12;
+            }
+            if (!isPm && hour === 12) {
+                hour = 0;
+            }
+            return hour;
+        } else {
+            // this is not supposed to happen
+            return hour;
+        }
+    }
+
+    // date from string and array of format strings
+    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 (!valid__isValid(tempConfig)) {
+                continue;
+            }
+
+            // if there is any input that was not parsed add a penalty for that format
+            currentScore += getParsingFlags(tempConfig).charsLeftOver;
+
+            //or tokens
+            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) {
+            // Adding is smart enough around DST
+            res.add(1, 'd');
+            res._nextDay = undefined;
+        }
+
+        return res;
+    }
+
+    function prepareConfig (config) {
+        var input = config._i,
+            format = config._f;
+
+        config._locale = config._locale || locale_locales__getLocale(config._l);
+
+        if (input === null || (format === undefined && input === '')) {
+            return valid__createInvalid({nullInput: true});
+        }
+
+        if (typeof input === 'string') {
+            config._i = input = config._locale.preparse(input);
+        }
+
+        if (isMoment(input)) {
+            return new Moment(checkOverflow(input));
+        } else if (isArray(format)) {
+            configFromStringAndArray(config);
+        } else if (format) {
+            configFromStringAndFormat(config);
+        } else if (isDate(input)) {
+            config._d = input;
+        } else {
+            configFromInput(config);
+        }
+
+        if (!valid__isValid(config)) {
+            config._d = null;
+        }
+
+        return config;
+    }
+
+    function configFromInput(config) {
+        var input = config._i;
+        if (input === undefined) {
+            config._d = new Date(utils_hooks__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 (typeof(input) === 'object') {
+            configFromObject(config);
+        } else if (typeof(input) === 'number') {
+            // from milliseconds
+            config._d = new Date(input);
+        } else {
+            utils_hooks__hooks.createFromInputFallback(config);
+        }
+    }
+
+    function createLocalOrUTC (input, format, locale, strict, isUTC) {
+        var c = {};
+
+        if (typeof(locale) === 'boolean') {
+            strict = locale;
+            locale = undefined;
+        }
+        // object construction must be done this way.
+        // https://github.com/moment/moment/issues/1423
+        c._isAMomentObject = true;
+        c._useUTC = c._isUTC = isUTC;
+        c._l = locale;
+        c._i = input;
+        c._f = format;
+        c._strict = strict;
+
+        return createFromConfig(c);
+    }
+
+    function local__createLocal (input, format, locale, strict) {
+        return createLocalOrUTC(input, format, locale, strict, false);
+    }
+
+    var prototypeMin = deprecate(
+         'moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
+         function () {
+             var other = local__createLocal.apply(null, arguments);
+             if (this.isValid() && other.isValid()) {
+                 return other < this ? this : other;
+             } else {
+                 return valid__createInvalid();
+             }
+         }
+     );
+
+    var prototypeMax = deprecate(
+        'moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
+        function () {
+            var other = local__createLocal.apply(null, arguments);
+            if (this.isValid() && other.isValid()) {
+                return other > this ? this : other;
+            } else {
+                return valid__createInvalid();
+            }
+        }
+    );
+
+    // Pick a moment m from moments so that m[fn](other) is true for all
+    // other. This relies on the function fn to be transitive.
+    //
+    // moments should either be an array of moment objects or an array, whose
+    // first element is an array of moment objects.
+    function pickBy(fn, moments) {
+        var res, i;
+        if (moments.length === 1 && isArray(moments[0])) {
+            moments = moments[0];
+        }
+        if (!moments.length) {
+            return local__createLocal();
+        }
+        res = moments[0];
+        for (i = 1; i < moments.length; ++i) {
+            if (!moments[i].isValid() || moments[i][fn](res)) {
+                res = moments[i];
+            }
+        }
+        return res;
+    }
+
+    // TODO: Use [].sort instead?
+    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());
+    };
+
+    function Duration (duration) {
+        var normalizedInput = normalizeObjectUnits(duration),
+            years = normalizedInput.year || 0,
+            quarters = normalizedInput.quarter || 0,
+            months = normalizedInput.month || 0,
+            weeks = normalizedInput.week || 0,
+            days = normalizedInput.day || 0,
+            hours = normalizedInput.hour || 0,
+            minutes = normalizedInput.minute || 0,
+            seconds = normalizedInput.second || 0,
+            milliseconds = normalizedInput.millisecond || 0;
+
+        // representation for dateAddRemove
+        this._milliseconds = +milliseconds +
+            seconds * 1e3 + // 1000
+            minutes * 6e4 + // 1000 * 60
+            hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
+        // Because of dateAddRemove treats 24 hours as different from a
+        // day when working around DST, we need to store them separately
+        this._days = +days +
+            weeks * 7;
+        // It is impossible translate months into days without knowing
+        // which months you are are talking about, so we have to store
+        // it separately.
+        this._months = +months +
+            quarters * 3 +
+            years * 12;
+
+        this._data = {};
+
+        this._locale = locale_locales__getLocale();
+
+        this._bubble();
+    }
+
+    function isDuration (obj) {
+        return obj instanceof Duration;
+    }
+
+    // FORMATTING
+
+    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', '');
+
+    // PARSING
+
+    addRegexToken('Z',  matchShortOffset);
+    addRegexToken('ZZ', matchShortOffset);
+    addParseToken(['Z', 'ZZ'], function (input, array, config) {
+        config._useUTC = true;
+        config._tzm = offsetFromString(matchShortOffset, input);
+    });
+
+    // HELPERS
+
+    // timezone chunker
+    // '+10:00' > ['10',  '00']
+    // '-1530'  > ['-15', '30']
+    var chunkOffset = /([\+\-]|\d\d)/gi;
+
+    function offsetFromString(matcher, string) {
+        var matches = ((string || '').match(matcher) || []);
+        var chunk   = matches[matches.length - 1] || [];
+        var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
+        var minutes = +(parts[1] * 60) + toInt(parts[2]);
+
+        return parts[0] === '+' ? minutes : -minutes;
+    }
+
+    // Return a moment from input, that is local/utc/zone equivalent to model.
+    function cloneWithOffset(input, model) {
+        var res, diff;
+        if (model._isUTC) {
+            res = model.clone();
+            diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf();
+            // Use low-level api, because this fn is low-level api.
+            res._d.setTime(res._d.valueOf() + diff);
+            utils_hooks__hooks.updateOffset(res, false);
+            return res;
+        } else {
+            return local__createLocal(input).local();
+        }
+    }
+
+    function getDateOffset (m) {
+        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
+        // https://github.com/moment/moment/pull/1871
+        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
+    }
+
+    // HOOKS
+
+    // This function will be called whenever a moment is mutated.
+    // It is intended to keep the offset in sync with the timezone.
+    utils_hooks__hooks.updateOffset = function () {};
+
+    // MOMENTS
+
+    // keepLocalTime = true means only change the timezone, without
+    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
+    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
+    // +0200, so we adjust the time as needed, to be valid.
+    //
+    // Keeping the time actually adds/subtracts (one hour)
+    // from the actual represented time. That is why we call updateOffset
+    // a second time. In case it wants us to change the offset again
+    // _changeInProgress == true case, then we have to adjust, because
+    // there is no such time in the given timezone.
+    function getSetOffset (input, keepLocalTime) {
+        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);
+            } else if (Math.abs(input) < 16) {
+                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) {
+                    add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
+                } else if (!this._changeInProgress) {
+                    this._changeInProgress = true;
+                    utils_hooks__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) {
+            this.utcOffset(this._tzm);
+        } else if (typeof this._i === 'string') {
+            this.utcOffset(offsetFromString(matchOffset, this._i));
+        }
+        return this;
+    }
+
+    function hasAlignedHourOffset (input) {
+        if (!this.isValid()) {
+            return false;
+        }
+        input = input ? local__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 ? create_utc__createUTC(c._a) : local__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;
+    }
+
+    // ASP.NET json date format regex
+    var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/;
+
+    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
+    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
+    // and further modified to allow for strings containing both week and day
+    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 create__createDuration (input, key) {
+        var duration = input,
+            // matching against regexp is expensive, do it on demand
+            match = null,
+            sign,
+            ret,
+            diffRes;
+
+        if (isDuration(input)) {
+            duration = {
+                ms : input._milliseconds,
+                d  : input._days,
+                M  : input._months
+            };
+        } else if (typeof input === 'number') {
+            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(match[MILLISECOND]) * 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) {// checks for null or undefined
+            duration = {};
+        } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
+            diffRes = momentsDifference(local__createLocal(duration.from), local__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;
+    }
+
+    create__createDuration.fn = Duration.prototype;
+
+    function parseIso (inp, sign) {
+        // We'd normally use ~~inp for this, but unfortunately it also
+        // converts floats to ints.
+        // inp may be undefined, so careful calling replace on it.
+        var res = inp && parseFloat(inp.replace(',', '.'));
+        // apply sign while we're at it
+        return (isNaN(res) ? 0 : res) * sign;
+    }
+
+    function positiveMomentsDifference(base, other) {
+        var res = {milliseconds: 0, months: 0};
+
+        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 absRound (number) {
+        if (number < 0) {
+            return Math.round(-1 * number) * -1;
+        } else {
+            return Math.round(number);
+        }
+    }
+
+    // TODO: remove 'name' arg after deprecation is removed
+    function createAdder(direction, name) {
+        return function (val, period) {
+            var dur, tmp;
+            //invert the arguments, but complain about it
+            if (period !== null && !isNaN(+period)) {
+                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
+                tmp = val; val = period; period = tmp;
+            }
+
+            val = typeof val === 'string' ? +val : val;
+            dur = create__createDuration(val, period);
+            add_subtract__addSubtract(this, dur, direction);
+            return this;
+        };
+    }
+
+    function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
+        var milliseconds = duration._milliseconds,
+            days = absRound(duration._days),
+            months = absRound(duration._months);
+
+        if (!mom.isValid()) {
+            // No op
+            return;
+        }
+
+        updateOffset = updateOffset == null ? true : updateOffset;
+
+        if (milliseconds) {
+            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
+        }
+        if (days) {
+            get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
+        }
+        if (months) {
+            setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
+        }
+        if (updateOffset) {
+            utils_hooks__hooks.updateOffset(mom, days || months);
+        }
+    }
+
+    var add_subtract__add      = createAdder(1, 'add');
+    var add_subtract__subtract = createAdder(-1, 'subtract');
+
+    function moment_calendar__calendar (time, formats) {
+        // We want to compare the start of today, vs this.
+        // Getting start-of-today depends on whether we're local/utc/offset or not.
+        var now = time || local__createLocal(),
+            sod = cloneWithOffset(now, this).startOf('day'),
+            diff = this.diff(sod, 'days', true),
+            format = diff < -6 ? 'sameElse' :
+                diff < -1 ? 'lastWeek' :
+                diff < 0 ? 'lastDay' :
+                diff < 1 ? 'sameDay' :
+                diff < 2 ? 'nextDay' :
+                diff < 7 ? 'nextWeek' : 'sameElse';
+
+        var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]);
+
+        return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
+    }
+
+    function clone () {
+        return new Moment(this);
+    }
+
+    function isAfter (input, units) {
+        var localInput = isMoment(input) ? input : local__createLocal(input);
+        if (!(this.isValid() && localInput.isValid())) {
+            return false;
+        }
+        units = normalizeUnits(!isUndefined(units) ? 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 : local__createLocal(input);
+        if (!(this.isValid() && localInput.isValid())) {
+            return false;
+        }
+        units = normalizeUnits(!isUndefined(units) ? 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) {
+        inclusivity = inclusivity || '()';
+        return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
+            (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
+    }
+
+    function isSame (input, units) {
+        var localInput = isMoment(input) ? input : local__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,
+            delta, output;
+
+        if (!this.isValid()) {
+            return NaN;
+        }
+
+        that = cloneWithOffset(input, this);
+
+        if (!that.isValid()) {
+            return NaN;
+        }
+
+        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
+
+        units = normalizeUnits(units);
+
+        if (units === 'year' || units === 'month' || units === 'quarter') {
+            output = monthDiff(this, that);
+            if (units === 'quarter') {
+                output = output / 3;
+            } else if (units === 'year') {
+                output = output / 12;
+            }
+        } else {
+            delta = this - that;
+            output = units === 'second' ? delta / 1e3 : // 1000
+                units === 'minute' ? delta / 6e4 : // 1000 * 60
+                units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
+                units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
+                units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
+                delta;
+        }
+        return asFloat ? output : absFloor(output);
+    }
+
+    function monthDiff (a, b) {
+        // difference in months
+        var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
+            // b is in (anchor - 1 month, anchor + 1 month)
+            anchor = a.clone().add(wholeMonthDiff, 'months'),
+            anchor2, adjust;
+
+        if (b - anchor < 0) {
+            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
+            // linear across the month
+            adjust = (b - anchor) / (anchor - anchor2);
+        } else {
+            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
+            // linear across the month
+            adjust = (b - anchor) / (anchor2 - anchor);
+        }
+
+        //check for negative zero, return zero if negative zero
+        return -(wholeMonthDiff + adjust) || 0;
+    }
+
+    utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
+    utils_hooks__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 moment_format__toISOString () {
+        var m = this.clone().utc();
+        if (0 < m.year() && m.year() <= 9999) {
+            if (isFunction(Date.prototype.toISOString)) {
+                // native implementation is ~50x faster, use it when we can
+                return this.toDate().toISOString();
+            } else {
+                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+            }
+        } else {
+            return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+        }
+    }
+
+    function format (inputString) {
+        if (!inputString) {
+            inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat;
+        }
+        var output = formatMoment(this, inputString);
+        return this.localeData().postformat(output);
+    }
+
+    function from (time, withoutSuffix) {
+        if (this.isValid() &&
+                ((isMoment(time) && time.isValid()) ||
+                 local__createLocal(time).isValid())) {
+            return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
+        } else {
+            return this.localeData().invalidDate();
+        }
+    }
+
+    function fromNow (withoutSuffix) {
+        return this.from(local__createLocal(), withoutSuffix);
+    }
+
+    function to (time, withoutSuffix) {
+        if (this.isValid() &&
+                ((isMoment(time) && time.isValid()) ||
+                 local__createLocal(time).isValid())) {
+            return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
+        } else {
+            return this.localeData().invalidDate();
+        }
+    }
+
+    function toNow (withoutSuffix) {
+        return this.to(local__createLocal(), withoutSuffix);
+    }
+
+    // If passed a locale key, it will set the locale for this
+    // instance.  Otherwise, it will return the locale configuration
+    // variables for this instance.
+    function locale (key) {
+        var newLocaleData;
+
+        if (key === undefined) {
+            return this._locale._abbr;
+        } else {
+            newLocaleData = locale_locales__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;
+    }
+
+    function startOf (units) {
+        units = normalizeUnits(units);
+        // the following switch intentionally omits break keywords
+        // to utilize falling through the cases.
+        switch (units) {
+        case 'year':
+            this.month(0);
+            /* falls through */
+        case 'quarter':
+        case 'month':
+            this.date(1);
+            /* falls through */
+        case 'week':
+        case 'isoWeek':
+        case 'day':
+        case 'date':
+            this.hours(0);
+            /* falls through */
+        case 'hour':
+            this.minutes(0);
+            /* falls through */
+        case 'minute':
+            this.seconds(0);
+            /* falls through */
+        case 'second':
+            this.milliseconds(0);
+        }
+
+        // weeks are a special case
+        if (units === 'week') {
+            this.weekday(0);
+        }
+        if (units === 'isoWeek') {
+            this.isoWeekday(1);
+        }
+
+        // quarters are also special
+        if (units === 'quarter') {
+            this.month(Math.floor(this.month() / 3) * 3);
+        }
+
+        return this;
+    }
+
+    function endOf (units) {
+        units = normalizeUnits(units);
+        if (units === undefined || units === 'millisecond') {
+            return this;
+        }
+
+        // 'date' is an alias for 'day', so it should be considered as such.
+        if (units === 'date') {
+            units = 'day';
+        }
+
+        return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
+    }
+
+    function to_type__valueOf () {
+        return this._d.valueOf() - ((this._offset || 0) * 60000);
+    }
+
+    function unix () {
+        return Math.floor(this.valueOf() / 1000);
+    }
+
+    function toDate () {
+        return this._offset ? new Date(this.valueOf()) : this._d;
+    }
+
+    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 () {
+        // new Date(NaN).toJSON() === null
+        return this.isValid() ? this.toISOString() : null;
+    }
+
+    function moment_valid__isValid () {
+        return valid__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
+        };
+    }
+
+    // FORMATTING
+
+    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');
+
+    // ALIASES
+
+    addUnitAlias('weekYear', 'gg');
+    addUnitAlias('isoWeekYear', 'GG');
+
+    // PARSING
+
+    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] = utils_hooks__hooks.parseTwoDigitYear(input);
+    });
+
+    // MOMENTS
+
+    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;
+    }
+
+    // FORMATTING
+
+    addFormatToken('Q', 0, 'Qo', 'quarter');
+
+    // ALIASES
+
+    addUnitAlias('quarter', 'Q');
+
+    // PARSING
+
+    addRegexToken('Q', match1);
+    addParseToken('Q', function (input, array) {
+        array[MONTH] = (toInt(input) - 1) * 3;
+    });
+
+    // MOMENTS
+
+    function getSetQuarter (input) {
+        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
+    }
+
+    // FORMATTING
+
+    addFormatToken('w', ['ww', 2], 'wo', 'week');
+    addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
+
+    // ALIASES
+
+    addUnitAlias('week', 'w');
+    addUnitAlias('isoWeek', 'W');
+
+    // PARSING
+
+    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);
+    });
+
+    // HELPERS
+
+    // LOCALES
+
+    function localeWeek (mom) {
+        return weekOfYear(mom, this._week.dow, this._week.doy).week;
+    }
+
+    var defaultLocaleWeek = {
+        dow : 0, // Sunday is the first day of the week.
+        doy : 6  // The week that contains Jan 1st is the first week of the year.
+    };
+
+    function localeFirstDayOfWeek () {
+        return this._week.dow;
+    }
+
+    function localeFirstDayOfYear () {
+        return this._week.doy;
+    }
+
+    // MOMENTS
+
+    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');
+    }
+
+    // FORMATTING
+
+    addFormatToken('D', ['DD', 2], 'Do', 'date');
+
+    // ALIASES
+
+    addUnitAlias('date', 'D');
+
+    // PARSING
+
+    addRegexToken('D',  match1to2);
+    addRegexToken('DD', match1to2, match2);
+    addRegexToken('Do', function (isStrict, locale) {
+        return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
+    });
+
+    addParseToken(['D', 'DD'], DATE);
+    addParseToken('Do', function (input, array) {
+        array[DATE] = toInt(input.match(match1to2)[0], 10);
+    });
+
+    // MOMENTS
+
+    var getSetDayOfMonth = makeGetSet('Date', true);
+
+    // FORMATTING
+
+    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');
+
+    // ALIASES
+
+    addUnitAlias('day', 'd');
+    addUnitAlias('weekday', 'e');
+    addUnitAlias('isoWeekday', 'E');
+
+    // PARSING
+
+    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 we didn't get a weekday name, mark the date as invalid
+        if (weekday != null) {
+            week.d = weekday;
+        } else {
+            getParsingFlags(config).invalidWeekday = input;
+        }
+    });
+
+    addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
+        week[token] = toInt(input);
+    });
+
+    // HELPERS
+
+    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;
+    }
+
+    // LOCALES
+
+    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
+    function localeWeekdays (m, format) {
+        return isArray(this._weekdays) ? this._weekdays[m.day()] :
+            this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
+    }
+
+    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
+    function localeWeekdaysShort (m) {
+        return this._weekdaysShort[m.day()];
+    }
+
+    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
+    function localeWeekdaysMin (m) {
+        return this._weekdaysMin[m.day()];
+    }
+
+    function day_of_week__handleStrictParse(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 = create_utc__createUTC([2000, 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 day_of_week__handleStrictParse.call(this, weekdayName, format, strict);
+        }
+
+        if (!this._weekdaysParse) {
+            this._weekdaysParse = [];
+            this._minWeekdaysParse = [];
+            this._shortWeekdaysParse = [];
+            this._fullWeekdaysParse = [];
+        }
+
+        for (i = 0; i < 7; i++) {
+            // make the regex if we don't have it already
+
+            mom = create_utc__createUTC([2000, 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');
+            }
+            // test the regex
+            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;
+            }
+        }
+    }
+
+    // MOMENTS
+
+    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;
+        }
+        // behaves the same as moment#day except
+        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
+        // as a setter, sunday should belong to the previous week.
+        return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 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 {
+            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 {
+            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 {
+            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++) {
+            // make the regex if we don't have it already
+            mom = create_utc__createUTC([2000, 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);
+        }
+        // Sorting makes sure if one weekday (or abbr) is a prefix of another it
+        // will match the longer piece.
+        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');
+    }
+
+    // FORMATTING
+
+    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
+
+    // ALIASES
+
+    addUnitAlias('dayOfYear', 'DDD');
+
+    // PARSING
+
+    addRegexToken('DDD',  match1to3);
+    addRegexToken('DDDD', match3);
+    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
+        config._dayOfYear = toInt(input);
+    });
+
+    // HELPERS
+
+    // MOMENTS
+
+    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');
+    }
+
+    // FORMATTING
+
+    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);
+    });
 
-    for (i = lists.length - 1; i >= 0; --i) {
-        makeList(lists[i]);
+    function meridiem (token, lowercase) {
+        addFormatToken(token, 0, 0, function () {
+            return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
+        });
     }
 
-    moment.normalizeUnits = function (units) {
-        return normalizeUnits(units);
-    };
+    meridiem('a', true);
+    meridiem('A', false);
 
-    moment.invalid = function (flags) {
-        var m = moment.utc(NaN);
-        if (flags != null) {
-            extend(m._pf, flags);
-        }
-        else {
-            m._pf.userInvalidated = true;
-        }
+    // ALIASES
 
-        return m;
-    };
+    addUnitAlias('hour', 'h');
 
-    moment.parseZone = function (input) {
-        return moment(input).parseZone();
-    };
+    // PARSING
 
-    /************************************
-        Moment Prototype
-    ************************************/
+    function matchMeridiem (isStrict, locale) {
+        return locale._meridiemParse;
+    }
 
+    addRegexToken('a',  matchMeridiem);
+    addRegexToken('A',  matchMeridiem);
+    addRegexToken('H',  match1to2);
+    addRegexToken('h',  match1to2);
+    addRegexToken('HH', match1to2, match2);
+    addRegexToken('hh', match1to2, match2);
 
-    extend(moment.fn = Moment.prototype, {
+    addRegexToken('hmm', match3to4);
+    addRegexToken('hmmss', match5to6);
+    addRegexToken('Hmm', match3to4);
+    addRegexToken('Hmmss', match5to6);
 
-        clone : function () {
-            return moment(this);
-        },
+    addParseToken(['H', 'HH'], HOUR);
+    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));
+    });
 
-        valueOf : function () {
-            return +this._d + ((this._offset || 0) * 60000);
-        },
+    // LOCALES
 
-        unix : function () {
-            return Math.floor(+this / 1000);
-        },
+    function localeIsPM (input) {
+        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
+        // Using charAt should be more compatible.
+        return ((input + '').toLowerCase().charAt(0) === 'p');
+    }
 
-        toString : function () {
-            return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
-        },
+    var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
+    function localeMeridiem (hours, minutes, isLower) {
+        if (hours > 11) {
+            return isLower ? 'pm' : 'PM';
+        } else {
+            return isLower ? 'am' : 'AM';
+        }
+    }
 
-        toDate : function () {
-            return this._offset ? new Date(+this) : this._d;
-        },
 
-        toISOString : function () {
-            var m = moment(this).utc();
-            if (0 < m.year() && m.year() <= 9999) {
-                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
-            } else {
-                return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
-            }
-        },
+    // MOMENTS
 
-        toArray : function () {
-            var m = this;
-            return [
-                m.year(),
-                m.month(),
-                m.date(),
-                m.hours(),
-                m.minutes(),
-                m.seconds(),
-                m.milliseconds()
-            ];
-        },
+    // Setting the hour should keep the time, because the user explicitly
+    // specified which hour he wants. So trying to maintain the same hour (in
+    // a new timezone) makes sense. Adding/subtracting hours does not follow
+    // this rule.
+    var getSetHour = makeGetSet('Hours', true);
 
-        isValid : function () {
-            return isValid(this);
-        },
+    // FORMATTING
 
-        isDSTShifted : function () {
+    addFormatToken('m', ['mm', 2], 0, 'minute');
 
-            if (this._a) {
-                return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
-            }
+    // ALIASES
 
-            return false;
-        },
+    addUnitAlias('minute', 'm');
 
-        parsingFlags : function () {
-            return extend({}, this._pf);
-        },
+    // PARSING
 
-        invalidAt: function () {
-            return this._pf.overflow;
-        },
+    addRegexToken('m',  match1to2);
+    addRegexToken('mm', match1to2, match2);
+    addParseToken(['m', 'mm'], MINUTE);
 
-        utc : function () {
-            return this.zone(0);
-        },
+    // MOMENTS
 
-        local : function () {
-            this.zone(0);
-            this._isUTC = false;
-            return this;
-        },
+    var getSetMinute = makeGetSet('Minutes', false);
 
-        format : function (inputString) {
-            var output = formatMoment(this, inputString || moment.defaultFormat);
-            return this.lang().postformat(output);
-        },
+    // FORMATTING
 
-        add : function (input, val) {
-            var dur;
-            // switch args to support add('s', 1) and add(1, 's')
-            if (typeof input === 'string') {
-                dur = moment.duration(+val, input);
-            } else {
-                dur = moment.duration(input, val);
-            }
-            addOrSubtractDurationFromMoment(this, dur, 1);
-            return this;
-        },
+    addFormatToken('s', ['ss', 2], 0, 'second');
 
-        subtract : function (input, val) {
-            var dur;
-            // switch args to support subtract('s', 1) and subtract(1, 's')
-            if (typeof input === 'string') {
-                dur = moment.duration(+val, input);
-            } else {
-                dur = moment.duration(input, val);
-            }
-            addOrSubtractDurationFromMoment(this, dur, -1);
-            return this;
-        },
+    // ALIASES
 
-        diff : function (input, units, asFloat) {
-            var that = makeAs(input, this),
-                zoneDiff = (this.zone() - that.zone()) * 6e4,
-                diff, output;
+    addUnitAlias('second', 's');
 
-            units = normalizeUnits(units);
+    // PARSING
 
-            if (units === 'year' || units === 'month') {
-                // average number of days in the months in the given dates
-                diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
-                // difference in months
-                output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
-                // adjust by taking difference in days, average number of days
-                // and dst in the given months.
-                output += ((this - moment(this).startOf('month')) -
-                        (that - moment(that).startOf('month'))) / diff;
-                // same as above but with zones, to negate all dst
-                output -= ((this.zone() - moment(this).startOf('month').zone()) -
-                        (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
-                if (units === 'year') {
-                    output = output / 12;
-                }
-            } else {
-                diff = (this - that);
-                output = units === 'second' ? diff / 1e3 : // 1000
-                    units === 'minute' ? diff / 6e4 : // 1000 * 60
-                    units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
-                    units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
-                    units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
-                    diff;
-            }
-            return asFloat ? output : absRound(output);
-        },
+    addRegexToken('s',  match1to2);
+    addRegexToken('ss', match1to2, match2);
+    addParseToken(['s', 'ss'], SECOND);
 
-        from : function (time, withoutSuffix) {
-            return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
-        },
+    // MOMENTS
 
-        fromNow : function (withoutSuffix) {
-            return this.from(moment(), withoutSuffix);
-        },
+    var getSetSecond = makeGetSet('Seconds', false);
 
-        calendar : function () {
-            // We want to compare the start of today, vs this.
-            // Getting start-of-today depends on whether we're zone'd or not.
-            var sod = makeAs(moment(), this).startOf('day'),
-                diff = this.diff(sod, 'days', true),
-                format = diff < -6 ? 'sameElse' :
-                    diff < -1 ? 'lastWeek' :
-                    diff < 0 ? 'lastDay' :
-                    diff < 1 ? 'sameDay' :
-                    diff < 2 ? 'nextDay' :
-                    diff < 7 ? 'nextWeek' : 'sameElse';
-            return this.format(this.lang().calendar(format, this));
-        },
+    // FORMATTING
 
-        isLeapYear : function () {
-            return isLeapYear(this.year());
-        },
+    addFormatToken('S', 0, 0, function () {
+        return ~~(this.millisecond() / 100);
+    });
 
-        isDST : function () {
-            return (this.zone() < this.clone().month(0).zone() ||
-                this.zone() < this.clone().month(5).zone());
-        },
+    addFormatToken(0, ['SS', 2], 0, function () {
+        return ~~(this.millisecond() / 10);
+    });
 
-        day : function (input) {
-            var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
-            if (input != null) {
-                input = parseWeekday(input, this.lang());
-                return this.add({ d : input - day });
-            } else {
-                return day;
-            }
-        },
+    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() * 1000;
+    });
+    addFormatToken(0, ['SSSSSSS', 7], 0, function () {
+        return this.millisecond() * 10000;
+    });
+    addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
+        return this.millisecond() * 100000;
+    });
+    addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
+        return this.millisecond() * 1000000;
+    });
 
-        month : function (input) {
-            var utc = this._isUTC ? 'UTC' : '',
-                dayOfMonth;
 
-            if (input != null) {
-                if (typeof input === 'string') {
-                    input = this.lang().monthsParse(input);
-                    if (typeof input !== 'number') {
-                        return this;
-                    }
-                }
+    // ALIASES
 
-                dayOfMonth = this.date();
-                this.date(1);
-                this._d['set' + utc + 'Month'](input);
-                this.date(Math.min(dayOfMonth, this.daysInMonth()));
+    addUnitAlias('millisecond', 'ms');
 
-                moment.updateOffset(this);
-                return this;
-            } else {
-                return this._d['get' + utc + 'Month']();
-            }
-        },
+    // PARSING
 
-        startOf: function (units) {
-            units = normalizeUnits(units);
-            // the following switch intentionally omits break keywords
-            // to utilize falling through the cases.
-            switch (units) {
-            case 'year':
-                this.month(0);
-                /* falls through */
-            case 'month':
-                this.date(1);
-                /* falls through */
-            case 'week':
-            case 'isoWeek':
-            case 'day':
-                this.hours(0);
-                /* falls through */
-            case 'hour':
-                this.minutes(0);
-                /* falls through */
-            case 'minute':
-                this.seconds(0);
-                /* falls through */
-            case 'second':
-                this.milliseconds(0);
-                /* falls through */
-            }
-
-            // weeks are a special case
-            if (units === 'week') {
-                this.weekday(0);
-            } else if (units === 'isoWeek') {
-                this.isoWeekday(1);
-            }
+    addRegexToken('S',    match1to3, match1);
+    addRegexToken('SS',   match1to3, match2);
+    addRegexToken('SSS',  match1to3, match3);
 
-            return this;
-        },
+    var token;
+    for (token = 'SSSS'; token.length <= 9; token += 'S') {
+        addRegexToken(token, matchUnsigned);
+    }
 
-        endOf: function (units) {
-            units = normalizeUnits(units);
-            return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
-        },
+    function parseMs(input, array) {
+        array[MILLISECOND] = toInt(('0.' + input) * 1000);
+    }
 
-        isAfter: function (input, units) {
-            units = typeof units !== 'undefined' ? units : 'millisecond';
-            return +this.clone().startOf(units) > +moment(input).startOf(units);
-        },
+    for (token = 'S'; token.length <= 9; token += 'S') {
+        addParseToken(token, parseMs);
+    }
+    // MOMENTS
 
-        isBefore: function (input, units) {
-            units = typeof units !== 'undefined' ? units : 'millisecond';
-            return +this.clone().startOf(units) < +moment(input).startOf(units);
-        },
+    var getSetMillisecond = makeGetSet('Milliseconds', false);
 
-        isSame: function (input, units) {
-            units = units || 'ms';
-            return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
-        },
+    // FORMATTING
 
-        min: function (other) {
-            other = moment.apply(null, arguments);
-            return other < this ? this : other;
-        },
+    addFormatToken('z',  0, 0, 'zoneAbbr');
+    addFormatToken('zz', 0, 0, 'zoneName');
+
+    // MOMENTS
+
+    function getZoneAbbr () {
+        return this._isUTC ? 'UTC' : '';
+    }
+
+    function getZoneName () {
+        return this._isUTC ? 'Coordinated Universal Time' : '';
+    }
+
+    var momentPrototype__proto = Moment.prototype;
+
+    momentPrototype__proto.add               = add_subtract__add;
+    momentPrototype__proto.calendar          = moment_calendar__calendar;
+    momentPrototype__proto.clone             = clone;
+    momentPrototype__proto.diff              = diff;
+    momentPrototype__proto.endOf             = endOf;
+    momentPrototype__proto.format            = format;
+    momentPrototype__proto.from              = from;
+    momentPrototype__proto.fromNow           = fromNow;
+    momentPrototype__proto.to                = to;
+    momentPrototype__proto.toNow             = toNow;
+    momentPrototype__proto.get               = getSet;
+    momentPrototype__proto.invalidAt         = invalidAt;
+    momentPrototype__proto.isAfter           = isAfter;
+    momentPrototype__proto.isBefore          = isBefore;
+    momentPrototype__proto.isBetween         = isBetween;
+    momentPrototype__proto.isSame            = isSame;
+    momentPrototype__proto.isSameOrAfter     = isSameOrAfter;
+    momentPrototype__proto.isSameOrBefore    = isSameOrBefore;
+    momentPrototype__proto.isValid           = moment_valid__isValid;
+    momentPrototype__proto.lang              = lang;
+    momentPrototype__proto.locale            = locale;
+    momentPrototype__proto.localeData        = localeData;
+    momentPrototype__proto.max               = prototypeMax;
+    momentPrototype__proto.min               = prototypeMin;
+    momentPrototype__proto.parsingFlags      = parsingFlags;
+    momentPrototype__proto.set               = getSet;
+    momentPrototype__proto.startOf           = startOf;
+    momentPrototype__proto.subtract          = add_subtract__subtract;
+    momentPrototype__proto.toArray           = toArray;
+    momentPrototype__proto.toObject          = toObject;
+    momentPrototype__proto.toDate            = toDate;
+    momentPrototype__proto.toISOString       = moment_format__toISOString;
+    momentPrototype__proto.toJSON            = toJSON;
+    momentPrototype__proto.toString          = toString;
+    momentPrototype__proto.unix              = unix;
+    momentPrototype__proto.valueOf           = to_type__valueOf;
+    momentPrototype__proto.creationData      = creationData;
 
-        max: function (other) {
-            other = moment.apply(null, arguments);
-            return other > this ? this : other;
-        },
+    // Year
+    momentPrototype__proto.year       = getSetYear;
+    momentPrototype__proto.isLeapYear = getIsLeapYear;
 
-        zone : function (input) {
-            var offset = this._offset || 0;
-            if (input != null) {
-                if (typeof input === "string") {
-                    input = timezoneMinutesFromString(input);
-                }
-                if (Math.abs(input) < 16) {
-                    input = input * 60;
-                }
-                this._offset = input;
-                this._isUTC = true;
-                if (offset !== input) {
-                    addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
-                }
-            } else {
-                return this._isUTC ? offset : this._d.getTimezoneOffset();
-            }
-            return this;
-        },
+    // Week Year
+    momentPrototype__proto.weekYear    = getSetWeekYear;
+    momentPrototype__proto.isoWeekYear = getSetISOWeekYear;
 
-        zoneAbbr : function () {
-            return this._isUTC ? "UTC" : "";
-        },
+    // Quarter
+    momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;
 
-        zoneName : function () {
-            return this._isUTC ? "Coordinated Universal Time" : "";
-        },
+    // Month
+    momentPrototype__proto.month       = getSetMonth;
+    momentPrototype__proto.daysInMonth = getDaysInMonth;
 
-        parseZone : function () {
-            if (this._tzm) {
-                this.zone(this._tzm);
-            } else if (typeof this._i === 'string') {
-                this.zone(this._i);
-            }
-            return this;
-        },
+    // Week
+    momentPrototype__proto.week           = momentPrototype__proto.weeks        = getSetWeek;
+    momentPrototype__proto.isoWeek        = momentPrototype__proto.isoWeeks     = getSetISOWeek;
+    momentPrototype__proto.weeksInYear    = getWeeksInYear;
+    momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;
+
+    // Day
+    momentPrototype__proto.date       = getSetDayOfMonth;
+    momentPrototype__proto.day        = momentPrototype__proto.days             = getSetDayOfWeek;
+    momentPrototype__proto.weekday    = getSetLocaleDayOfWeek;
+    momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
+    momentPrototype__proto.dayOfYear  = getSetDayOfYear;
+
+    // Hour
+    momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;
+
+    // Minute
+    momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;
+
+    // Second
+    momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;
+
+    // Millisecond
+    momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;
+
+    // Offset
+    momentPrototype__proto.utcOffset            = getSetOffset;
+    momentPrototype__proto.utc                  = setOffsetToUTC;
+    momentPrototype__proto.local                = setOffsetToLocal;
+    momentPrototype__proto.parseZone            = setOffsetToParsedOffset;
+    momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
+    momentPrototype__proto.isDST                = isDaylightSavingTime;
+    momentPrototype__proto.isDSTShifted         = isDaylightSavingTimeShifted;
+    momentPrototype__proto.isLocal              = isLocal;
+    momentPrototype__proto.isUtcOffset          = isUtcOffset;
+    momentPrototype__proto.isUtc                = isUtc;
+    momentPrototype__proto.isUTC                = isUtc;
+
+    // Timezone
+    momentPrototype__proto.zoneAbbr = getZoneAbbr;
+    momentPrototype__proto.zoneName = getZoneName;
+
+    // Deprecations
+    momentPrototype__proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
+    momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
+    momentPrototype__proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
+    momentPrototype__proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);
+
+    var momentPrototype = momentPrototype__proto;
+
+    function moment__createUnix (input) {
+        return local__createLocal(input * 1000);
+    }
+
+    function moment__createInZone () {
+        return local__createLocal.apply(null, arguments).parseZone();
+    }
+
+    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'
+    };
 
-        hasAlignedHourOffset : function (input) {
-            if (!input) {
-                input = 0;
-            }
-            else {
-                input = moment(input).zone();
-            }
+    function locale_calendar__calendar (key, mom, now) {
+        var output = this._calendar[key];
+        return isFunction(output) ? output.call(mom, now) : output;
+    }
 
-            return (this.zone() - input) % 60 === 0;
-        },
+    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'
+    };
 
-        daysInMonth : function () {
-            return daysInMonth(this.year(), this.month());
-        },
+    function longDateFormat (key) {
+        var format = this._longDateFormat[key],
+            formatUpper = this._longDateFormat[key.toUpperCase()];
 
-        dayOfYear : function (input) {
-            var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
-            return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
-        },
+        if (format || !formatUpper) {
+            return format;
+        }
 
-        quarter : function () {
-            return Math.ceil((this.month() + 1.0) / 3.0);
-        },
+        this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
+            return val.slice(1);
+        });
 
-        weekYear : function (input) {
-            var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
-            return input == null ? year : this.add("y", (input - year));
-        },
+        return this._longDateFormat[key];
+    }
 
-        isoWeekYear : function (input) {
-            var year = weekOfYear(this, 1, 4).year;
-            return input == null ? year : this.add("y", (input - year));
-        },
+    var defaultInvalidDate = 'Invalid date';
 
-        week : function (input) {
-            var week = this.lang().week(this);
-            return input == null ? week : this.add("d", (input - week) * 7);
-        },
+    function invalidDate () {
+        return this._invalidDate;
+    }
 
-        isoWeek : function (input) {
-            var week = weekOfYear(this, 1, 4).week;
-            return input == null ? week : this.add("d", (input - week) * 7);
-        },
+    var defaultOrdinal = '%d';
+    var defaultOrdinalParse = /\d{1,2}/;
 
-        weekday : function (input) {
-            var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
-            return input == null ? weekday : this.add("d", input - weekday);
-        },
+    function ordinal (number) {
+        return this._ordinal.replace('%d', number);
+    }
 
-        isoWeekday : function (input) {
-            // behaves the same as moment#day except
-            // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
-            // as a setter, sunday should belong to the previous week.
-            return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
-        },
+    function preParsePostFormat (string) {
+        return string;
+    }
 
-        get : function (units) {
-            units = normalizeUnits(units);
-            return this[units]();
-        },
+    var defaultRelativeTime = {
+        future : 'in %s',
+        past   : '%s ago',
+        s  : 'a few 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'
+    };
 
-        set : function (units, value) {
-            units = normalizeUnits(units);
-            if (typeof this[units] === 'function') {
-                this[units](value);
+    function relative__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 prototype__proto = Locale.prototype;
+
+    prototype__proto._calendar       = defaultCalendar;
+    prototype__proto.calendar        = locale_calendar__calendar;
+    prototype__proto._longDateFormat = defaultLongDateFormat;
+    prototype__proto.longDateFormat  = longDateFormat;
+    prototype__proto._invalidDate    = defaultInvalidDate;
+    prototype__proto.invalidDate     = invalidDate;
+    prototype__proto._ordinal        = defaultOrdinal;
+    prototype__proto.ordinal         = ordinal;
+    prototype__proto._ordinalParse   = defaultOrdinalParse;
+    prototype__proto.preparse        = preParsePostFormat;
+    prototype__proto.postformat      = preParsePostFormat;
+    prototype__proto._relativeTime   = defaultRelativeTime;
+    prototype__proto.relativeTime    = relative__relativeTime;
+    prototype__proto.pastFuture      = pastFuture;
+    prototype__proto.set             = locale_set__set;
+
+    // Month
+    prototype__proto.months            =        localeMonths;
+    prototype__proto._months           = defaultLocaleMonths;
+    prototype__proto.monthsShort       =        localeMonthsShort;
+    prototype__proto._monthsShort      = defaultLocaleMonthsShort;
+    prototype__proto.monthsParse       =        localeMonthsParse;
+    prototype__proto._monthsRegex      = defaultMonthsRegex;
+    prototype__proto.monthsRegex       = monthsRegex;
+    prototype__proto._monthsShortRegex = defaultMonthsShortRegex;
+    prototype__proto.monthsShortRegex  = monthsShortRegex;
+
+    // Week
+    prototype__proto.week = localeWeek;
+    prototype__proto._week = defaultLocaleWeek;
+    prototype__proto.firstDayOfYear = localeFirstDayOfYear;
+    prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;
+
+    // Day of Week
+    prototype__proto.weekdays       =        localeWeekdays;
+    prototype__proto._weekdays      = defaultLocaleWeekdays;
+    prototype__proto.weekdaysMin    =        localeWeekdaysMin;
+    prototype__proto._weekdaysMin   = defaultLocaleWeekdaysMin;
+    prototype__proto.weekdaysShort  =        localeWeekdaysShort;
+    prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;
+    prototype__proto.weekdaysParse  =        localeWeekdaysParse;
+
+    prototype__proto._weekdaysRegex      = defaultWeekdaysRegex;
+    prototype__proto.weekdaysRegex       =        weekdaysRegex;
+    prototype__proto._weekdaysShortRegex = defaultWeekdaysShortRegex;
+    prototype__proto.weekdaysShortRegex  =        weekdaysShortRegex;
+    prototype__proto._weekdaysMinRegex   = defaultWeekdaysMinRegex;
+    prototype__proto.weekdaysMinRegex    =        weekdaysMinRegex;
+
+    // Hours
+    prototype__proto.isPM = localeIsPM;
+    prototype__proto._meridiemParse = defaultLocaleMeridiemParse;
+    prototype__proto.meridiem = localeMeridiem;
+
+    function lists__get (format, index, field, setter) {
+        var locale = locale_locales__getLocale();
+        var utc = create_utc__createUTC().set(setter, index);
+        return locale[field](utc, format);
+    }
+
+    function listMonthsImpl (format, index, field) {
+        if (typeof format === 'number') {
+            index = format;
+            format = undefined;
+        }
+
+        format = format || '';
+
+        if (index != null) {
+            return lists__get(format, index, field, 'month');
+        }
+
+        var i;
+        var out = [];
+        for (i = 0; i < 12; i++) {
+            out[i] = lists__get(format, i, field, 'month');
+        }
+        return out;
+    }
+
+    // ()
+    // (5)
+    // (fmt, 5)
+    // (fmt)
+    // (true)
+    // (true, 5)
+    // (true, fmt, 5)
+    // (true, fmt)
+    function listWeekdaysImpl (localeSorted, format, index, field) {
+        if (typeof localeSorted === 'boolean') {
+            if (typeof format === 'number') {
+                index = format;
+                format = undefined;
             }
-            return this;
-        },
 
-        // If passed a language key, it will set the language for this
-        // instance.  Otherwise, it will return the language configuration
-        // variables for this instance.
-        lang : function (key) {
-            if (key === undefined) {
-                return this._lang;
-            } else {
-                this._lang = getLangDefinition(key);
-                return this;
+            format = format || '';
+        } else {
+            format = localeSorted;
+            index = format;
+            localeSorted = false;
+
+            if (typeof format === 'number') {
+                index = format;
+                format = undefined;
             }
+
+            format = format || '';
         }
-    });
 
-    // helper for adding shortcuts
-    function makeGetterAndSetter(name, key) {
-        moment.fn[name] = moment.fn[name + 's'] = function (input) {
-            var utc = this._isUTC ? 'UTC' : '';
-            if (input != null) {
-                this._d['set' + utc + key](input);
-                moment.updateOffset(this);
-                return this;
-            } else {
-                return this._d['get' + utc + key]();
-            }
-        };
-    }
+        var locale = locale_locales__getLocale(),
+            shift = localeSorted ? locale._week.dow : 0;
 
-    // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
-    for (i = 0; i < proxyGettersAndSetters.length; i ++) {
-        makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
-    }
+        if (index != null) {
+            return lists__get(format, (index + shift) % 7, field, 'day');
+        }
 
-    // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
-    makeGetterAndSetter('year', 'FullYear');
+        var i;
+        var out = [];
+        for (i = 0; i < 7; i++) {
+            out[i] = lists__get(format, (i + shift) % 7, field, 'day');
+        }
+        return out;
+    }
 
-    // add plural methods
-    moment.fn.days = moment.fn.day;
-    moment.fn.months = moment.fn.month;
-    moment.fn.weeks = moment.fn.week;
-    moment.fn.isoWeeks = moment.fn.isoWeek;
+    function lists__listMonths (format, index) {
+        return listMonthsImpl(format, index, 'months');
+    }
 
-    // add aliased format methods
-    moment.fn.toJSON = moment.fn.toISOString;
+    function lists__listMonthsShort (format, index) {
+        return listMonthsImpl(format, index, 'monthsShort');
+    }
 
-    /************************************
-        Duration Prototype
-    ************************************/
+    function lists__listWeekdays (localeSorted, format, index) {
+        return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
+    }
 
+    function lists__listWeekdaysShort (localeSorted, format, index) {
+        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
+    }
 
-    extend(moment.duration.fn = Duration.prototype, {
+    function lists__listWeekdaysMin (localeSorted, format, index) {
+        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
+    }
 
-        _bubble : function () {
-            var milliseconds = this._milliseconds,
-                days = this._days,
-                months = this._months,
-                data = this._data,
-                seconds, minutes, hours, years;
+    locale_locales__getSetGlobalLocale('en', {
+        ordinalParse: /\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;
+        }
+    });
 
-            // The following code bubbles up values, see the tests for
-            // examples of what that means.
-            data.milliseconds = milliseconds % 1000;
+    // Side effect imports
+    utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);
+    utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);
 
-            seconds = absRound(milliseconds / 1000);
-            data.seconds = seconds % 60;
+    var mathAbs = Math.abs;
 
-            minutes = absRound(seconds / 60);
-            data.minutes = minutes % 60;
+    function duration_abs__abs () {
+        var data           = this._data;
 
-            hours = absRound(minutes / 60);
-            data.hours = hours % 24;
+        this._milliseconds = mathAbs(this._milliseconds);
+        this._days         = mathAbs(this._days);
+        this._months       = mathAbs(this._months);
 
-            days += absRound(hours / 24);
-            data.days = days % 30;
+        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);
 
-            months += absRound(days / 30);
-            data.months = months % 12;
+        return this;
+    }
 
-            years = absRound(months / 12);
-            data.years = years;
-        },
+    function duration_add_subtract__addSubtract (duration, input, value, direction) {
+        var other = create__createDuration(input, value);
 
-        weeks : function () {
-            return absRound(this.days() / 7);
-        },
+        duration._milliseconds += direction * other._milliseconds;
+        duration._days         += direction * other._days;
+        duration._months       += direction * other._months;
 
-        valueOf : function () {
-            return this._milliseconds +
-              this._days * 864e5 +
-              (this._months % 12) * 2592e6 +
-              toInt(this._months / 12) * 31536e6;
-        },
+        return duration._bubble();
+    }
 
-        humanize : function (withSuffix) {
-            var difference = +this,
-                output = relativeTime(difference, !withSuffix, this.lang());
+    // supports only 2.0-style add(1, 's') or add(duration)
+    function duration_add_subtract__add (input, value) {
+        return duration_add_subtract__addSubtract(this, input, value, 1);
+    }
 
-            if (withSuffix) {
-                output = this.lang().pastFuture(difference, output);
-            }
+    // supports only 2.0-style subtract(1, 's') or subtract(duration)
+    function duration_add_subtract__subtract (input, value) {
+        return duration_add_subtract__addSubtract(this, input, value, -1);
+    }
 
-            return this.lang().postformat(output);
-        },
+    function absCeil (number) {
+        if (number < 0) {
+            return Math.floor(number);
+        } else {
+            return Math.ceil(number);
+        }
+    }
 
-        add : function (input, val) {
-            // supports only 2.0-style add(1, 's') or add(moment)
-            var dur = moment.duration(input, val);
+    function bubble () {
+        var milliseconds = this._milliseconds;
+        var days         = this._days;
+        var months       = this._months;
+        var data         = this._data;
+        var seconds, minutes, hours, years, monthsFromDays;
 
-            this._milliseconds += dur._milliseconds;
-            this._days += dur._days;
-            this._months += dur._months;
+        // if we have a mix of positive and negative values, bubble down first
+        // check: https://github.com/moment/moment/issues/2166
+        if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
+                (milliseconds <= 0 && days <= 0 && months <= 0))) {
+            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
+            days = 0;
+            months = 0;
+        }
 
-            this._bubble();
+        // The following code bubbles up values, see the tests for
+        // examples of what that means.
+        data.milliseconds = milliseconds % 1000;
 
-            return this;
-        },
+        seconds           = absFloor(milliseconds / 1000);
+        data.seconds      = seconds % 60;
 
-        subtract : function (input, val) {
-            var dur = moment.duration(input, val);
+        minutes           = absFloor(seconds / 60);
+        data.minutes      = minutes % 60;
 
-            this._milliseconds -= dur._milliseconds;
-            this._days -= dur._days;
-            this._months -= dur._months;
+        hours             = absFloor(minutes / 60);
+        data.hours        = hours % 24;
 
-            this._bubble();
+        days += absFloor(hours / 24);
 
-            return this;
-        },
+        // convert days to months
+        monthsFromDays = absFloor(daysToMonths(days));
+        months += monthsFromDays;
+        days -= absCeil(monthsToDays(monthsFromDays));
 
-        get : function (units) {
-            units = normalizeUnits(units);
-            return this[units.toLowerCase() + 's']();
-        },
+        // 12 months -> 1 year
+        years = absFloor(months / 12);
+        months %= 12;
 
-        as : function (units) {
-            units = normalizeUnits(units);
-            return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
-        },
+        data.days   = days;
+        data.months = months;
+        data.years  = years;
 
-        lang : moment.fn.lang,
-
-        toIsoString : function () {
-            // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
-            var years = Math.abs(this.years()),
-                months = Math.abs(this.months()),
-                days = Math.abs(this.days()),
-                hours = Math.abs(this.hours()),
-                minutes = Math.abs(this.minutes()),
-                seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
-
-            if (!this.asSeconds()) {
-                // this is the same as C#'s (Noda) and python (isodate)...
-                // but not other JS (goog.date)
-                return 'P0D';
-            }
-
-            return (this.asSeconds() < 0 ? '-' : '') +
-                'P' +
-                (years ? years + 'Y' : '') +
-                (months ? months + 'M' : '') +
-                (days ? days + 'D' : '') +
-                ((hours || minutes || seconds) ? 'T' : '') +
-                (hours ? hours + 'H' : '') +
-                (minutes ? minutes + 'M' : '') +
-                (seconds ? seconds + 'S' : '');
-        }
-    });
+        return this;
+    }
 
-    function makeDurationGetter(name) {
-        moment.duration.fn[name] = function () {
-            return this._data[name];
-        };
+    function daysToMonths (days) {
+        // 400 years have 146097 days (taking into account leap year rules)
+        // 400 years have 12 months === 4800
+        return days * 4800 / 146097;
     }
 
-    function makeDurationAsGetter(name, factor) {
-        moment.duration.fn['as' + name] = function () {
-            return +this / factor;
-        };
+    function monthsToDays (months) {
+        // the reverse of daysToMonths
+        return months * 146097 / 4800;
     }
 
-    for (i in unitMillisecondFactors) {
-        if (unitMillisecondFactors.hasOwnProperty(i)) {
-            makeDurationAsGetter(i, unitMillisecondFactors[i]);
-            makeDurationGetter(i.toLowerCase());
+    function as (units) {
+        var days;
+        var months;
+        var milliseconds = this._milliseconds;
+
+        units = normalizeUnits(units);
+
+        if (units === 'month' || units === 'year') {
+            days   = this._days   + milliseconds / 864e5;
+            months = this._months + daysToMonths(days);
+            return units === 'month' ? months : months / 12;
+        } else {
+            // handle milliseconds separately because of floating point math errors (issue #1867)
+            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 / 1000;
+                // Math.floor prevents floating point math errors here
+                case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
+                default: throw new Error('Unknown unit ' + units);
+            }
         }
     }
 
-    makeDurationAsGetter('Weeks', 6048e5);
-    moment.duration.fn.asMonths = function () {
-        return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
-    };
+    // TODO: Use this.as('ms')?
+    function duration_as__valueOf () {
+        return (
+            this._milliseconds +
+            this._days * 864e5 +
+            (this._months % 12) * 2592e6 +
+            toInt(this._months / 12) * 31536e6
+        );
+    }
 
+    function makeAs (alias) {
+        return function () {
+            return this.as(alias);
+        };
+    }
 
-    /************************************
-        Default Lang
-    ************************************/
+    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 asYears        = makeAs('y');
 
+    function duration_get__get (units) {
+        units = normalizeUnits(units);
+        return this[units + 's']();
+    }
 
-    // Set default language, other languages will inherit from English.
-    moment.lang('en', {
-        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;
-        }
-    });
+    function makeGetter(name) {
+        return function () {
+            return this._data[name];
+        };
+    }
+
+    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');
 
-    /* EMBED_LANGUAGES */
+    function weeks () {
+        return absFloor(this.days() / 7);
+    }
 
-    /************************************
-        Exposing Moment
-    ************************************/
+    var round = Math.round;
+    var thresholds = {
+        s: 45,  // seconds to minute
+        m: 45,  // minutes to hour
+        h: 22,  // hours to day
+        d: 26,  // days to month
+        M: 11   // months to year
+    };
 
-    function makeGlobal(deprecate) {
-        var warned = false, local_moment = moment;
-        /*global ender:false */
-        if (typeof ender !== 'undefined') {
-            return;
+    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
+    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
+        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+    }
+
+    function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {
+        var duration = create__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.s && ['s', 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);
+    }
+
+    // This function allows you to set a threshold for relative time strings
+    function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {
+        if (thresholds[threshold] === undefined) {
+            return false;
         }
-        // here, `this` means `window` in the browser, or `global` on the server
-        // add `moment` as a global object via a string identifier,
-        // for Closure Compiler "advanced" mode
-        if (deprecate) {
-            global.moment = function () {
-                if (!warned && console && console.warn) {
-                    warned = true;
-                    console.warn(
-                            "Accessing Moment through the global scope is " +
-                            "deprecated, and will be removed in an upcoming " +
-                            "release.");
-                }
-                return local_moment.apply(null, arguments);
-            };
-            extend(global.moment, local_moment);
-        } else {
-            global['moment'] = moment;
+        if (limit === undefined) {
+            return thresholds[threshold];
         }
+        thresholds[threshold] = limit;
+        return true;
     }
 
-    // CommonJS module is defined
-    if (hasModule) {
-        module.exports = moment;
-        makeGlobal(true);
-    } else if (typeof define === "function" && define.amd) {
-        define("moment", function (require, exports, module) {
-            if (module.config && module.config() && module.config().noGlobal !== true) {
-                // If user provided noGlobal, he is aware of global
-                makeGlobal(module.config().noGlobal === undefined);
-            }
+    function humanize (withSuffix) {
+        var locale = this.localeData();
+        var output = duration_humanize__relativeTime(this, !withSuffix, locale);
+
+        if (withSuffix) {
+            output = locale.pastFuture(+this, output);
+        }
+
+        return locale.postformat(output);
+    }
+
+    var iso_string__abs = Math.abs;
+
+    function iso_string__toISOString() {
+        // for ISO strings we do not use the normal bubbling rules:
+        //  * milliseconds bubble up until they become hours
+        //  * days do not bubble at all
+        //  * months bubble up until they become years
+        // This is because there is no context-free conversion between hours and days
+        // (think of clock changes)
+        // and also not between days and months (28-31 days per month)
+        var seconds = iso_string__abs(this._milliseconds) / 1000;
+        var days         = iso_string__abs(this._days);
+        var months       = iso_string__abs(this._months);
+        var minutes, hours, years;
+
+        // 3600 seconds -> 60 minutes -> 1 hour
+        minutes           = absFloor(seconds / 60);
+        hours             = absFloor(minutes / 60);
+        seconds %= 60;
+        minutes %= 60;
+
+        // 12 months -> 1 year
+        years  = absFloor(months / 12);
+        months %= 12;
+
+
+        // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
+        var Y = years;
+        var M = months;
+        var D = days;
+        var h = hours;
+        var m = minutes;
+        var s = seconds;
+        var total = this.asSeconds();
+
+        if (!total) {
+            // this is the same as C#'s (Noda) and python (isodate)...
+            // but not other JS (goog.date)
+            return 'P0D';
+        }
+
+        return (total < 0 ? '-' : '') +
+            'P' +
+            (Y ? Y + 'Y' : '') +
+            (M ? M + 'M' : '') +
+            (D ? D + 'D' : '') +
+            ((h || m || s) ? 'T' : '') +
+            (h ? h + 'H' : '') +
+            (m ? m + 'M' : '') +
+            (s ? s + 'S' : '');
+    }
+
+    var duration_prototype__proto = Duration.prototype;
+
+    duration_prototype__proto.abs            = duration_abs__abs;
+    duration_prototype__proto.add            = duration_add_subtract__add;
+    duration_prototype__proto.subtract       = duration_add_subtract__subtract;
+    duration_prototype__proto.as             = as;
+    duration_prototype__proto.asMilliseconds = asMilliseconds;
+    duration_prototype__proto.asSeconds      = asSeconds;
+    duration_prototype__proto.asMinutes      = asMinutes;
+    duration_prototype__proto.asHours        = asHours;
+    duration_prototype__proto.asDays         = asDays;
+    duration_prototype__proto.asWeeks        = asWeeks;
+    duration_prototype__proto.asMonths       = asMonths;
+    duration_prototype__proto.asYears        = asYears;
+    duration_prototype__proto.valueOf        = duration_as__valueOf;
+    duration_prototype__proto._bubble        = bubble;
+    duration_prototype__proto.get            = duration_get__get;
+    duration_prototype__proto.milliseconds   = milliseconds;
+    duration_prototype__proto.seconds        = seconds;
+    duration_prototype__proto.minutes        = minutes;
+    duration_prototype__proto.hours          = hours;
+    duration_prototype__proto.days           = days;
+    duration_prototype__proto.weeks          = weeks;
+    duration_prototype__proto.months         = months;
+    duration_prototype__proto.years          = years;
+    duration_prototype__proto.humanize       = humanize;
+    duration_prototype__proto.toISOString    = iso_string__toISOString;
+    duration_prototype__proto.toString       = iso_string__toISOString;
+    duration_prototype__proto.toJSON         = iso_string__toISOString;
+    duration_prototype__proto.locale         = locale;
+    duration_prototype__proto.localeData     = localeData;
+
+    // Deprecations
+    duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);
+    duration_prototype__proto.lang = lang;
+
+    // Side effect imports
+
+    // FORMATTING
+
+    addFormatToken('X', 0, 0, 'unix');
+    addFormatToken('x', 0, 0, 'valueOf');
+
+    // PARSING
+
+    addRegexToken('x', matchSigned);
+    addRegexToken('X', matchTimestamp);
+    addParseToken('X', function (input, array, config) {
+        config._d = new Date(parseFloat(input, 10) * 1000);
+    });
+    addParseToken('x', function (input, array, config) {
+        config._d = new Date(toInt(input));
+    });
 
-            return moment;
-        });
-    } else {
-        makeGlobal();
-    }
-}).call(this);
-;/**
+    // Side effect imports
+
+
+    utils_hooks__hooks.version = '2.13.0';
+
+    setHookCallback(local__createLocal);
+
+    utils_hooks__hooks.fn                    = momentPrototype;
+    utils_hooks__hooks.min                   = min;
+    utils_hooks__hooks.max                   = max;
+    utils_hooks__hooks.now                   = now;
+    utils_hooks__hooks.utc                   = create_utc__createUTC;
+    utils_hooks__hooks.unix                  = moment__createUnix;
+    utils_hooks__hooks.months                = lists__listMonths;
+    utils_hooks__hooks.isDate                = isDate;
+    utils_hooks__hooks.locale                = locale_locales__getSetGlobalLocale;
+    utils_hooks__hooks.invalid               = valid__createInvalid;
+    utils_hooks__hooks.duration              = create__createDuration;
+    utils_hooks__hooks.isMoment              = isMoment;
+    utils_hooks__hooks.weekdays              = lists__listWeekdays;
+    utils_hooks__hooks.parseZone             = moment__createInZone;
+    utils_hooks__hooks.localeData            = locale_locales__getLocale;
+    utils_hooks__hooks.isDuration            = isDuration;
+    utils_hooks__hooks.monthsShort           = lists__listMonthsShort;
+    utils_hooks__hooks.weekdaysMin           = lists__listWeekdaysMin;
+    utils_hooks__hooks.defineLocale          = defineLocale;
+    utils_hooks__hooks.updateLocale          = updateLocale;
+    utils_hooks__hooks.locales               = locale_locales__listLocales;
+    utils_hooks__hooks.weekdaysShort         = lists__listWeekdaysShort;
+    utils_hooks__hooks.normalizeUnits        = normalizeUnits;
+    utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
+    utils_hooks__hooks.prototype             = momentPrototype;
+
+    var _moment = utils_hooks__hooks;
+
+    return _moment;
+
+}));;/**
  * Parse a text request to a json query object tree
  *
  * @param  {String} string The string to parse
@@ -5688,7 +7364,22 @@ return new Parser;
       this.mom = moment(str);
       this.setPrecision(MONTH);
     } else if (str.match(/\d\d\d\d/)) {
-      this.mom = moment(str);
+      // Creating a moment with only the year will show this deprecation
+      // warning:
+      //
+      // Deprecation warning: moment construction falls back to js Date. This is
+      // discouraged and will be removed in upcoming major release. Please refer
+      // to https://github.com/moment/moment/issues/1407 for more info.
+      //
+      // TL;DR: parsing year-only strings with momentjs falls back to native
+      // Date and it won't correctly represent the year in local time if UTF
+      // offset is negative.
+      //
+      // The solution is to use the format parameter, so momentjs won't fall
+      // back to the native Date and we will have the correct year in local
+      // time.
+      //
+      this.mom = moment(str, 'YYYY');
       this.setPrecision(YEAR);
     }
 
@@ -6898,7 +8589,9 @@ return new Parser;
                                          id, options);
           }
           // Already exists on destination
-          throw new jIO.util.jIOError("Conflict on '" + id + "'",
+          throw new jIO.util.jIOError("Conflict on '" + id + "': " +
+                                      JSON.stringify(doc) + " !== " +
+                                      JSON.stringify(remote_doc),
                                       409);
         });
     }
@@ -7003,7 +8696,9 @@ return new Parser;
                     return;
                   }
                   if (conflict_force !== true) {
-                    throw new jIO.util.jIOError("Conflict on '" + id + "'",
+                    throw new jIO.util.jIOError("Conflict on '" + id + "': " +
+                                                JSON.stringify(doc) + " !== " +
+                                                JSON.stringify(remote_doc),
                                                 409);
                   }
                 }
@@ -7361,7 +9056,7 @@ return new Parser;
  */
 
 /*jslint nomen: true*/
-/*global jIO*/
+/*global jIO, RSVP*/
 
 /**
  * JIO Memory Storage. Type = 'memory'.
@@ -7376,7 +9071,7 @@ return new Parser;
  * @class MemoryStorage
  */
 
-(function (jIO) {
+(function (jIO, JSON, RSVP) {
   "use strict";
 
   /**
@@ -7395,13 +9090,13 @@ return new Parser;
         attachments: {}
       };
     }
-    this._database[id].doc = metadata;
+    this._database[id].doc = JSON.stringify(metadata);
     return id;
   };
 
   MemoryStorage.prototype.get = function (id) {
     try {
-      return this._database[id].doc;
+      return JSON.parse(this._database[id].doc);
     } catch (error) {
       if (error instanceof TypeError) {
         throw new jIO.util.jIOError(
@@ -7448,7 +9143,7 @@ return new Parser;
           404
         );
       }
-      return result;
+      return jIO.util.dataURItoBlob(result);
     } catch (error) {
       if (error instanceof TypeError) {
         throw new jIO.util.jIOError(
@@ -7470,7 +9165,13 @@ return new Parser;
       }
       throw error;
     }
-    attachment_dict[name] = blob;
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.readBlobAsDataURL(blob);
+      })
+      .push(function (evt) {
+        attachment_dict[name] = evt.target.result;
+      });
   };
 
   MemoryStorage.prototype.removeAttachment = function (id, name) {
@@ -7501,7 +9202,7 @@ return new Parser;
           rows.push({
             id: i,
             value: {},
-            doc: this._database[i]
+            doc: JSON.parse(this._database[i].doc)
           });
         } else {
           rows.push({
@@ -7517,7 +9218,7 @@ return new Parser;
 
   jIO.addStorage('memory', MemoryStorage);
 
-}(jIO));
+}(jIO, JSON, RSVP));
 ;/*jslint nomen: true*/
 /*global RSVP, Blob, LZString, DOMException*/
 (function (RSVP, Blob, LZString, DOMException) {
@@ -8778,7 +10479,7 @@ return new Parser;
       .push(function () {
         var form = json._embedded._view,
           converted_json = {
-            portal_type: json.portal_type
+            portal_type: json._links.type.name
           },
           form_data_json = {},
           field,
@@ -8786,6 +10487,11 @@ return new Parser;
           prefix_length,
           result;
 
+        if (json._links.hasOwnProperty('parent')) {
+          converted_json.parent_relative_url =
+            new URI(json._links.parent.href).segment(2);
+        }
+
         form_data_json.form_id = {
           "key": [form.form_id.key],
           "default": form.form_id["default"]
@@ -8905,7 +10611,6 @@ return new Parser;
           hateoas = JSON.parse(response.target.responseText);
 
         function pushResult(json) {
-          json.portal_type = json._links.type.name;
           return extractPropertyFromFormJSON(json)
             .push(function (json2) {
               return convertJSONToGet(json2);
@@ -9023,7 +10728,6 @@ return new Parser;
                                    {"_view": this._default_view_reference})
         .push(function (response) {
           var result = JSON.parse(response.target.responseText);
-          result.portal_type = result._links.type.name;
           // Remove all ERP5 hateoas links / convert them into jIO ID
 
           // XXX Change default action to an jio urn with attachment name inside
@@ -9332,10 +11036,18 @@ return new Parser;
   };
 
   QueryStorage.prototype.hasCapacity = function (name) {
+    var this_storage_capacity_list = ["limit",
+                                      "sort",
+                                      "select",
+                                      "query"];
+
+    if (this_storage_capacity_list.indexOf(name) !== -1) {
+      return true;
+    }
     if (name === "list") {
       return this._sub_storage.hasCapacity(name);
     }
-    return true;
+    return false;
   };
   QueryStorage.prototype.buildQuery = function (options) {
     var substorage = this._sub_storage,
diff --git a/dist/jio-latest.min.js b/dist/jio-latest.min.js
index 9396715117f923355cce25d5b7fc23191edd9771..93a1e3ff4e5b43f9883ead595eac0bdfeebf5812 100644
--- a/dist/jio-latest.min.js
+++ b/dist/jio-latest.min.js
@@ -1,7 +1,7 @@
-/*! jio v3.10.2 2016-04-08 */
+/*! jio v3.11.0 2016-06-23 */
 function parseStringToObject(a){var b=function(){var a,b,c=[],d=arguments;for(a=0;a<d.length;a+=1)for(b=0;b<d[a].length;b+=1)c.push(d[a][b]);return c},c=function(a,b,c){var d={type:"simple",key:a,value:b};return void 0!==c&&(d.operator=c),d},d=function(a){return"NOT"===a.operator?a.query_list[0]:{type:"complex",operator:"NOT",query_list:[a]}},e=function(a,c){var d,e=[];for(d=0;d<c.length;d+=1)c[d].operator===a?e=b(e,c[d].query_list):e.push(c[d]);return{type:"complex",operator:a,query_list:e}},f=function(a,b){var c;if("complex"===a.type){for(c=0;c<a.query_list.length;++c)f(a.query_list[c],b);return!0}return"simple"!==a.type||a.key?!1:(a.key=b,!0)},g=function(){function a(){this.yy={}}var b=function(a,b,c,d){for(c=c||{},d=a.length;d--;c[a[d]]=b);return c},g=[1,5],h=[1,7],i=[1,8],j=[1,10],k=[1,12],l=[1,6,7,15],m=[1,6,7,9,12,14,15,16,19,21],n=[1,6,7,9,11,12,14,15,16,19,21],o=[2,17],p={trace:function(){},yy:{},symbols_:{error:2,begin:3,search_text:4,end:5,EOF:6,NEWLINE:7,and_expression:8,OR:9,boolean_expression:10,AND:11,NOT:12,expression:13,LEFT_PARENTHESE:14,RIGHT_PARENTHESE:15,WORD:16,DEFINITION:17,value:18,OPERATOR:19,string:20,QUOTE:21,QUOTED_STRING:22,$accept:0,$end:1},terminals_:{2:"error",6:"EOF",7:"NEWLINE",9:"OR",11:"AND",12:"NOT",14:"LEFT_PARENTHESE",15:"RIGHT_PARENTHESE",16:"WORD",17:"DEFINITION",19:"OPERATOR",21:"QUOTE",22:"QUOTED_STRING"},productions_:[0,[3,2],[5,0],[5,1],[5,1],[4,1],[4,2],[4,3],[8,1],[8,3],[10,2],[10,1],[13,3],[13,3],[13,1],[18,2],[18,1],[20,1],[20,3]],performAction:function(a,b,g,h,i,j,k){var l=j.length-1;switch(i){case 1:return j[l-1];case 5:case 8:case 11:case 14:case 16:this.$=j[l];break;case 6:this.$=e("OR",[j[l-1],j[l]]);break;case 7:this.$=e("OR",[j[l-2],j[l]]);break;case 9:this.$=e("AND",[j[l-2],j[l]]);break;case 10:this.$=d(j[l]);break;case 12:this.$=j[l-1];break;case 13:f(j[l],j[l-2]),this.$=j[l];break;case 15:j[l].operator=j[l-1],this.$=j[l];break;case 17:this.$=c("",j[l]);break;case 18:this.$=c("",j[l-1])}},table:[{3:1,4:2,8:3,10:4,12:g,13:6,14:h,16:i,18:9,19:j,20:11,21:k},{1:[3]},{1:[2,2],5:13,6:[1,14],7:[1,15]},b(l,[2,5],{8:3,10:4,13:6,18:9,20:11,4:16,9:[1,17],12:g,14:h,16:i,19:j,21:k}),b(m,[2,8],{11:[1,18]}),{13:19,14:h,16:i,18:9,19:j,20:11,21:k},b(n,[2,11]),{4:20,8:3,10:4,12:g,13:6,14:h,16:i,18:9,19:j,20:11,21:k},b(n,o,{17:[1,21]}),b(n,[2,14]),{16:[1,23],20:22,21:k},b(n,[2,16]),{22:[1,24]},{1:[2,1]},{1:[2,3]},{1:[2,4]},b(l,[2,6]),{4:25,8:3,10:4,12:g,13:6,14:h,16:i,18:9,19:j,20:11,21:k},{8:26,10:4,12:g,13:6,14:h,16:i,18:9,19:j,20:11,21:k},b(n,[2,10]),{15:[1,27]},{13:28,14:h,16:i,18:9,19:j,20:11,21:k},b(n,[2,15]),b(n,o),{21:[1,29]},b(l,[2,7]),b(m,[2,9]),b(n,[2,12]),b(n,[2,13]),b(n,[2,18])],defaultActions:{13:[2,1],14:[2,3],15:[2,4]},parseError:function(a,b){function c(a,b){this.message=a,this.hash=b}if(!b.recoverable)throw c.prototype=new Error,new c(a,b);this.trace(a)},parse:function(a){var b=this,c=[0],d=[null],e=[],f=this.table,g="",h=0,i=0,j=0,k=2,l=1,m=e.slice.call(arguments,1),n=Object.create(this.lexer),o={yy:{}};for(var p in this.yy)Object.prototype.hasOwnProperty.call(this.yy,p)&&(o.yy[p]=this.yy[p]);n.setInput(a,o.yy),o.yy.lexer=n,o.yy.parser=this,"undefined"==typeof n.yylloc&&(n.yylloc={});var q=n.yylloc;e.push(q);var r=n.options&&n.options.ranges;"function"==typeof o.yy.parseError?this.parseError=o.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var s,t,u,v,w,x,y,z,A,B=function(){var a;return a=n.lex()||l,"number"!=typeof a&&(a=b.symbols_[a]||a),a},C={};;){if(u=c[c.length-1],this.defaultActions[u]?v=this.defaultActions[u]:((null===s||"undefined"==typeof s)&&(s=B()),v=f[u]&&f[u][s]),"undefined"==typeof v||!v.length||!v[0]){var D="";A=[];for(x in f[u])this.terminals_[x]&&x>k&&A.push("'"+this.terminals_[x]+"'");D=n.showPosition?"Parse error on line "+(h+1)+":\n"+n.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[s]||s)+"'":"Parse error on line "+(h+1)+": Unexpected "+(s==l?"end of input":"'"+(this.terminals_[s]||s)+"'"),this.parseError(D,{text:n.match,token:this.terminals_[s]||s,line:n.yylineno,loc:q,expected:A})}if(v[0]instanceof Array&&v.length>1)throw new Error("Parse Error: multiple actions possible at state: "+u+", token: "+s);switch(v[0]){case 1:c.push(s),d.push(n.yytext),e.push(n.yylloc),c.push(v[1]),s=null,t?(s=t,t=null):(i=n.yyleng,g=n.yytext,h=n.yylineno,q=n.yylloc,j>0&&j--);break;case 2:if(y=this.productions_[v[1]][1],C.$=d[d.length-y],C._$={first_line:e[e.length-(y||1)].first_line,last_line:e[e.length-1].last_line,first_column:e[e.length-(y||1)].first_column,last_column:e[e.length-1].last_column},r&&(C._$.range=[e[e.length-(y||1)].range[0],e[e.length-1].range[1]]),w=this.performAction.apply(C,[g,i,h,o.yy,v[1],d,e].concat(m)),"undefined"!=typeof w)return w;y&&(c=c.slice(0,-1*y*2),d=d.slice(0,-1*y),e=e.slice(0,-1*y)),c.push(this.productions_[v[1]][0]),d.push(C.$),e.push(C._$),z=f[c[c.length-2]][c[c.length-1]],c.push(z);break;case 3:return!0}}return!0}},q=function(){var a={EOF:1,parseError:function(a,b){if(!this.yy.parser)throw new Error(a);this.yy.parser.parseError(a,b)},setInput:function(a,b){return this.yy=b||this.yy||{},this._input=a,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.offset++,this.match+=a,this.matched+=a;var b=a.match(/(?:\r\n?|\n).*/g);return b?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),a},unput:function(a){var b=a.length,c=a.split(/(?:\r\n?|\n)/g);this._input=a+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-b),this.offset-=b;var d=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var e=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===d.length?this.yylloc.first_column:0)+d[d.length-c.length].length-c[0].length:this.yylloc.first_column-b},this.options.ranges&&(this.yylloc.range=[e[0],e[0]+this.yyleng-b]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(a){this.unput(this.match.slice(a))},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var a=this.pastInput(),b=new Array(a.length+1).join("-");return a+this.upcomingInput()+"\n"+b+"^"},test_match:function(a,b){var c,d,e;if(this.options.backtrack_lexer&&(e={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(e.yylloc.range=this.yylloc.range.slice(0))),d=a[0].match(/(?:\r\n?|\n).*/g),d&&(this.yylineno+=d.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:d?d[d.length-1].length-d[d.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+a[0].length},this.yytext+=a[0],this.match+=a[0],this.matches=a,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(a[0].length),this.matched+=a[0],c=this.performAction.call(this,this.yy,this,b,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),c)return c;if(this._backtrack){for(var f in e)this[f]=e[f];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var a,b,c,d;this._more||(this.yytext="",this.match="");for(var e=this._currentRules(),f=0;f<e.length;f++)if(c=this._input.match(this.rules[e[f]]),c&&(!b||c[0].length>b[0].length)){if(b=c,d=f,this.options.backtrack_lexer){if(a=this.test_match(c,e[f]),a!==!1)return a;if(this._backtrack){b=!1;continue}return!1}if(!this.options.flex)break}return b?(a=this.test_match(b,e[d]),a!==!1?a:!1):""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var a=this.next();return a?a:this.lex()},begin:function(a){this.conditionStack.push(a)},popState:function(){var a=this.conditionStack.length-1;return a>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(a){return a=this.conditionStack.length-1-Math.abs(a||0),a>=0?this.conditionStack[a]:"INITIAL"},pushState:function(a){this.begin(a)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(a,b,c,d){switch(c){case 0:return this.begin("letsquote"),"QUOTE";case 1:return this.popState(),this.begin("endquote"),"QUOTED_STRING";case 2:return this.popState(),"QUOTE";case 3:break;case 4:return"LEFT_PARENTHESE";case 5:return"RIGHT_PARENTHESE";case 6:return"AND";case 7:return"OR";case 8:return"NOT";case 9:return"DEFINITION";case 10:return 19;case 11:return 16;case 12:return 6}},rules:[/^(?:")/,/^(?:(\\"|[^"])*)/,/^(?:")/,/^(?:[^\S]+)/,/^(?:\()/,/^(?:\))/,/^(?:AND\b)/,/^(?:OR\b)/,/^(?:NOT\b)/,/^(?::)/,/^(?:(!?=|<=?|>=?))/,/^(?:[^\s\n"():><!=]+)/,/^(?:$)/],conditions:{endquote:{rules:[2],inclusive:!1},letsquote:{rules:[1],inclusive:!1},INITIAL:{rules:[0,3,4,5,6,7,8,9,10,11,12],inclusive:!0}}};return a}();return p.lexer=q,a.prototype=p,p.Parser=a,new a}();return g.parse(a)}!function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define(b):a.IPv6=b(a)}(this,function(a){var b=a&&a.IPv6;return{best:function(a){a=a.toLowerCase().split(":");var b=a.length,c=8;""===a[0]&&""===a[1]&&""===a[2]?(a.shift(),a.shift()):""===a[0]&&""===a[1]?a.shift():""===a[b-1]&&""===a[b-2]&&a.pop(),b=a.length,-1!==a[b-1].indexOf(".")&&(c=7);var d;for(d=0;b>d&&""!==a[d];d++);if(c>d)for(a.splice(d,1,"0000");a.length<c;)a.splice(d,0,"0000");for(d=0;c>d;d++){for(var b=a[d].split(""),e=0;3>e&&("0"===b[0]&&1<b.length);e++)b.splice(0,1);a[d]=b.join("")}var b=-1,f=e=0,g=-1,h=!1;for(d=0;c>d;d++)h?"0"===a[d]?f+=1:(h=!1,f>e&&(b=g,e=f)):"0"==a[d]&&(h=!0,g=d,f=1);for(f>e&&(b=g,e=f),e>1&&a.splice(b,e,""),b=a.length,c="",""===a[0]&&(beststr=":"),d=0;b>d&&(c+=a[d],d!==b-1);d++)c+=":";return""===a[b-1]&&(c+=":"),c},noConflict:function(){return a.IPv6===this&&(a.IPv6=b),this}}}),function(a){function b(a){throw RangeError(B[a])}function c(a,b){for(var c=a.length;c--;)a[c]=b(a[c]);return a}function d(a,b){return c(a.split(A),b).join(".")}function e(a){for(var b,c,d=[],e=0,f=a.length;f>e;)b=a.charCodeAt(e++),b>=55296&&56319>=b&&f>e?(c=a.charCodeAt(e++),56320==(64512&c)?d.push(((1023&b)<<10)+(1023&c)+65536):(d.push(b),e--)):d.push(b);return d}function f(a){return c(a,function(a){var b="";return a>65535&&(a-=65536,b+=E(a>>>10&1023|55296),a=56320|1023&a),b+=E(a)}).join("")}function g(a,b){return a+22+75*(26>a)-((0!=b)<<5)}function h(a,b,c){var d=0;for(a=c?D(a/u):a>>1,a+=D(a/b);a>C*s>>1;d+=q)a=D(a/C);return D(d+(C+1)*a/(a+t))}function i(a){var c,d,e,g,i,j,k=[],l=a.length,m=0,n=w,o=v;for(d=a.lastIndexOf(x),0>d&&(d=0),e=0;d>e;++e)128<=a.charCodeAt(e)&&b("not-basic"),k.push(a.charCodeAt(e));for(d=d>0?d+1:0;l>d;){for(e=m,c=1,g=q;d>=l&&b("invalid-input"),i=a.charCodeAt(d++),i=10>i-48?i-22:26>i-65?i-65:26>i-97?i-97:q,(i>=q||i>D((p-m)/c))&&b("overflow"),m+=i*c,j=o>=g?r:g>=o+s?s:g-o,!(j>i);g+=q)i=q-j,c>D(p/i)&&b("overflow"),c*=i;c=k.length+1,o=h(m-e,c,0==e),D(m/c)>p-n&&b("overflow"),n+=D(m/c),m%=c,k.splice(m++,0,n)}return f(k)}function j(a){var c,d,f,i,j,k,l,m,n,o,t,u,y=[];for(a=e(a),o=a.length,c=w,d=0,j=v,k=0;o>k;++k)n=a[k],128>n&&y.push(E(n));for((f=i=y.length)&&y.push(x);o>f;){for(l=p,k=0;o>k;++k)n=a[k],n>=c&&l>n&&(l=n);for(t=f+1,l-c>D((p-d)/t)&&b("overflow"),d+=(l-c)*t,c=l,k=0;o>k;++k)if(n=a[k],c>n&&++d>p&&b("overflow"),n==c){for(m=d,l=q;n=j>=l?r:l>=j+s?s:l-j,!(n>m);l+=q)u=m-n,m=q-n,y.push(E(g(n+u%m,0))),m=D(u/m);y.push(E(g(m,0))),j=h(d,t,f==i),d=0,++f}++d,++c}return y.join("")}var k="object"==typeof exports&&exports,l="object"==typeof module&&module&&module.exports==k&&module,m="object"==typeof global&&global;(m.global===m||m.window===m)&&(a=m);var n,o,p=2147483647,q=36,r=1,s=26,t=38,u=700,v=72,w=128,x="-",y=/^xn--/,z=/[^ -~]/,A=/\x2E|\u3002|\uFF0E|\uFF61/g,B={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},C=q-r,D=Math.floor,E=String.fromCharCode;if(n={version:"1.2.3",ucs2:{decode:e,encode:f},decode:i,encode:j,toASCII:function(a){return d(a,function(a){return z.test(a)?"xn--"+j(a):a})},toUnicode:function(a){return d(a,function(a){return y.test(a)?i(a.slice(4).toLowerCase()):a})}},"function"==typeof define&&"object"==typeof define.amd&&define.amd)define(function(){return n});else if(k&&!k.nodeType)if(l)l.exports=n;else for(o in n)n.hasOwnProperty(o)&&(k[o]=n[o]);else a.punycode=n}(this),function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define(b):a.SecondLevelDomains=b(a)}(this,function(a){var b=a&&a.SecondLevelDomains,c=Object.prototype.hasOwnProperty,d={list:{ac:"com|gov|mil|net|org",ae:"ac|co|gov|mil|name|net|org|pro|sch",af:"com|edu|gov|net|org",al:"com|edu|gov|mil|net|org",ao:"co|ed|gv|it|og|pb",ar:"com|edu|gob|gov|int|mil|net|org|tur",at:"ac|co|gv|or",au:"asn|com|csiro|edu|gov|id|net|org",ba:"co|com|edu|gov|mil|net|org|rs|unbi|unmo|unsa|untz|unze",bb:"biz|co|com|edu|gov|info|net|org|store|tv",bh:"biz|cc|com|edu|gov|info|net|org",bn:"com|edu|gov|net|org",bo:"com|edu|gob|gov|int|mil|net|org|tv",br:"adm|adv|agr|am|arq|art|ato|b|bio|blog|bmd|cim|cng|cnt|com|coop|ecn|edu|eng|esp|etc|eti|far|flog|fm|fnd|fot|fst|g12|ggf|gov|imb|ind|inf|jor|jus|lel|mat|med|mil|mus|net|nom|not|ntr|odo|org|ppg|pro|psc|psi|qsl|rec|slg|srv|tmp|trd|tur|tv|vet|vlog|wiki|zlg",bs:"com|edu|gov|net|org",bz:"du|et|om|ov|rg",ca:"ab|bc|mb|nb|nf|nl|ns|nt|nu|on|pe|qc|sk|yk",ck:"biz|co|edu|gen|gov|info|net|org",cn:"ac|ah|bj|com|cq|edu|fj|gd|gov|gs|gx|gz|ha|hb|he|hi|hl|hn|jl|js|jx|ln|mil|net|nm|nx|org|qh|sc|sd|sh|sn|sx|tj|tw|xj|xz|yn|zj",co:"com|edu|gov|mil|net|nom|org",cr:"ac|c|co|ed|fi|go|or|sa",cy:"ac|biz|com|ekloges|gov|ltd|name|net|org|parliament|press|pro|tm","do":"art|com|edu|gob|gov|mil|net|org|sld|web",dz:"art|asso|com|edu|gov|net|org|pol",ec:"com|edu|fin|gov|info|med|mil|net|org|pro",eg:"com|edu|eun|gov|mil|name|net|org|sci",er:"com|edu|gov|ind|mil|net|org|rochest|w",es:"com|edu|gob|nom|org",et:"biz|com|edu|gov|info|name|net|org",fj:"ac|biz|com|info|mil|name|net|org|pro",fk:"ac|co|gov|net|nom|org",fr:"asso|com|f|gouv|nom|prd|presse|tm",gg:"co|net|org",gh:"com|edu|gov|mil|org",gn:"ac|com|gov|net|org",gr:"com|edu|gov|mil|net|org",gt:"com|edu|gob|ind|mil|net|org",gu:"com|edu|gov|net|org",hk:"com|edu|gov|idv|net|org",id:"ac|co|go|mil|net|or|sch|web",il:"ac|co|gov|idf|k12|muni|net|org","in":"ac|co|edu|ernet|firm|gen|gov|i|ind|mil|net|nic|org|res",iq:"com|edu|gov|i|mil|net|org",ir:"ac|co|dnssec|gov|i|id|net|org|sch",it:"edu|gov",je:"co|net|org",jo:"com|edu|gov|mil|name|net|org|sch",jp:"ac|ad|co|ed|go|gr|lg|ne|or",ke:"ac|co|go|info|me|mobi|ne|or|sc",kh:"com|edu|gov|mil|net|org|per",ki:"biz|com|de|edu|gov|info|mob|net|org|tel",km:"asso|com|coop|edu|gouv|k|medecin|mil|nom|notaires|pharmaciens|presse|tm|veterinaire",kn:"edu|gov|net|org",kr:"ac|busan|chungbuk|chungnam|co|daegu|daejeon|es|gangwon|go|gwangju|gyeongbuk|gyeonggi|gyeongnam|hs|incheon|jeju|jeonbuk|jeonnam|k|kg|mil|ms|ne|or|pe|re|sc|seoul|ulsan",kw:"com|edu|gov|net|org",ky:"com|edu|gov|net|org",kz:"com|edu|gov|mil|net|org",lb:"com|edu|gov|net|org",lk:"assn|com|edu|gov|grp|hotel|int|ltd|net|ngo|org|sch|soc|web",lr:"com|edu|gov|net|org",lv:"asn|com|conf|edu|gov|id|mil|net|org",ly:"com|edu|gov|id|med|net|org|plc|sch",ma:"ac|co|gov|m|net|org|press",mc:"asso|tm",me:"ac|co|edu|gov|its|net|org|priv",mg:"com|edu|gov|mil|nom|org|prd|tm",mk:"com|edu|gov|inf|name|net|org|pro",ml:"com|edu|gov|net|org|presse",mn:"edu|gov|org",mo:"com|edu|gov|net|org",mt:"com|edu|gov|net|org",mv:"aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro",mw:"ac|co|com|coop|edu|gov|int|museum|net|org",mx:"com|edu|gob|net|org",my:"com|edu|gov|mil|name|net|org|sch",nf:"arts|com|firm|info|net|other|per|rec|store|web",ng:"biz|com|edu|gov|mil|mobi|name|net|org|sch",ni:"ac|co|com|edu|gob|mil|net|nom|org",np:"com|edu|gov|mil|net|org",nr:"biz|com|edu|gov|info|net|org",om:"ac|biz|co|com|edu|gov|med|mil|museum|net|org|pro|sch",pe:"com|edu|gob|mil|net|nom|org|sld",ph:"com|edu|gov|i|mil|net|ngo|org",pk:"biz|com|edu|fam|gob|gok|gon|gop|gos|gov|net|org|web",pl:"art|bialystok|biz|com|edu|gda|gdansk|gorzow|gov|info|katowice|krakow|lodz|lublin|mil|net|ngo|olsztyn|org|poznan|pwr|radom|slupsk|szczecin|torun|warszawa|waw|wroc|wroclaw|zgora",pr:"ac|biz|com|edu|est|gov|info|isla|name|net|org|pro|prof",ps:"com|edu|gov|net|org|plo|sec",pw:"belau|co|ed|go|ne|or",ro:"arts|com|firm|info|nom|nt|org|rec|store|tm|www",rs:"ac|co|edu|gov|in|org",sb:"com|edu|gov|net|org",sc:"com|edu|gov|net|org",sh:"co|com|edu|gov|net|nom|org",sl:"com|edu|gov|net|org",st:"co|com|consulado|edu|embaixada|gov|mil|net|org|principe|saotome|store",sv:"com|edu|gob|org|red",sz:"ac|co|org",tr:"av|bbs|bel|biz|com|dr|edu|gen|gov|info|k12|name|net|org|pol|tel|tsk|tv|web",tt:"aero|biz|cat|co|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel",tw:"club|com|ebiz|edu|game|gov|idv|mil|net|org",mu:"ac|co|com|gov|net|or|org",mz:"ac|co|edu|gov|org",na:"co|com",nz:"ac|co|cri|geek|gen|govt|health|iwi|maori|mil|net|org|parliament|school",pa:"abo|ac|com|edu|gob|ing|med|net|nom|org|sld",pt:"com|edu|gov|int|net|nome|org|publ",py:"com|edu|gov|mil|net|org",qa:"com|edu|gov|mil|net|org",re:"asso|com|nom",ru:"ac|adygeya|altai|amur|arkhangelsk|astrakhan|bashkiria|belgorod|bir|bryansk|buryatia|cbg|chel|chelyabinsk|chita|chukotka|chuvashia|com|dagestan|e-burg|edu|gov|grozny|int|irkutsk|ivanovo|izhevsk|jar|joshkar-ola|kalmykia|kaluga|kamchatka|karelia|kazan|kchr|kemerovo|khabarovsk|khakassia|khv|kirov|koenig|komi|kostroma|kranoyarsk|kuban|kurgan|kursk|lipetsk|magadan|mari|mari-el|marine|mil|mordovia|mosreg|msk|murmansk|nalchik|net|nnov|nov|novosibirsk|nsk|omsk|orenburg|org|oryol|penza|perm|pp|pskov|ptz|rnd|ryazan|sakhalin|samara|saratov|simbirsk|smolensk|spb|stavropol|stv|surgut|tambov|tatarstan|tom|tomsk|tsaritsyn|tsk|tula|tuva|tver|tyumen|udm|udmurtia|ulan-ude|vladikavkaz|vladimir|vladivostok|volgograd|vologda|voronezh|vrn|vyatka|yakutia|yamal|yekaterinburg|yuzhno-sakhalinsk",rw:"ac|co|com|edu|gouv|gov|int|mil|net",sa:"com|edu|gov|med|net|org|pub|sch",sd:"com|edu|gov|info|med|net|org|tv",se:"a|ac|b|bd|c|d|e|f|g|h|i|k|l|m|n|o|org|p|parti|pp|press|r|s|t|tm|u|w|x|y|z",sg:"com|edu|gov|idn|net|org|per",sn:"art|com|edu|gouv|org|perso|univ",sy:"com|edu|gov|mil|net|news|org",th:"ac|co|go|in|mi|net|or",tj:"ac|biz|co|com|edu|go|gov|info|int|mil|name|net|nic|org|test|web",tn:"agrinet|com|defense|edunet|ens|fin|gov|ind|info|intl|mincom|nat|net|org|perso|rnrt|rns|rnu|tourism",tz:"ac|co|go|ne|or",ua:"biz|cherkassy|chernigov|chernovtsy|ck|cn|co|com|crimea|cv|dn|dnepropetrovsk|donetsk|dp|edu|gov|if|in|ivano-frankivsk|kh|kharkov|kherson|khmelnitskiy|kiev|kirovograd|km|kr|ks|kv|lg|lugansk|lutsk|lviv|me|mk|net|nikolaev|od|odessa|org|pl|poltava|pp|rovno|rv|sebastopol|sumy|te|ternopil|uzhgorod|vinnica|vn|zaporizhzhe|zhitomir|zp|zt",ug:"ac|co|go|ne|or|org|sc",uk:"ac|bl|british-library|co|cym|gov|govt|icnet|jet|lea|ltd|me|mil|mod|national-library-scotland|nel|net|nhs|nic|nls|org|orgn|parliament|plc|police|sch|scot|soc",us:"dni|fed|isa|kids|nsn",uy:"com|edu|gub|mil|net|org",ve:"co|com|edu|gob|info|mil|net|org|web",vi:"co|com|k12|net|org",vn:"ac|biz|com|edu|gov|health|info|int|name|net|org|pro",ye:"co|com|gov|ltd|me|net|org|plc",yu:"ac|co|edu|gov|org",za:"ac|agric|alt|bourse|city|co|cybernet|db|edu|gov|grondar|iaccess|imt|inca|landesign|law|mil|net|ngo|nis|nom|olivetti|org|pix|school|tm|web",zm:"ac|co|com|edu|gov|net|org|sch"},has_expression:null,is_expression:null,has:function(a){return!!a.match(d.has_expression)},is:function(a){return!!a.match(d.is_expression)},get:function(a){return(a=a.match(d.has_expression))&&a[1]||null},noConflict:function(){return a.SecondLevelDomains===this&&(a.SecondLevelDomains=b),this},init:function(){var a,b="";for(a in d.list)c.call(d.list,a)&&(b+="|("+("("+d.list[a]+")."+a)+")");d.has_expression=RegExp("\\.("+b.substr(1)+")$","i"),d.is_expression=RegExp("^("+b.substr(1)+")$","i")}};return d.init(),d}),function(a,b){"object"==typeof exports?module.exports=b(require("./punycode"),require("./IPv6"),require("./SecondLevelDomains")):"function"==typeof define&&define.amd?define(["./punycode","./IPv6","./SecondLevelDomains"],b):a.URI=b(a.punycode,a.IPv6,a.SecondLevelDomains,a)}(this,function(a,b,c,d){function e(a,b){return this instanceof e?(void 0===a&&(a="undefined"!=typeof location?location.href+"":""),this.href(a),void 0!==b?this.absoluteTo(b):this):new e(a,b)}function f(a){return a.replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")}function g(a){return void 0===a?"Undefined":String(Object.prototype.toString.call(a)).slice(8,-1)}function h(a){return"Array"===g(a)}function i(a,b){var c,d;if(h(b)){for(c=0,d=b.length;d>c;c++)if(!i(a,b[c]))return!1;return!0}var e=g(b);for(c=0,d=a.length;d>c;c++)if("RegExp"===e){if("string"==typeof a[c]&&a[c].match(b))return!0}else if(a[c]===b)return!0;return!1}function j(a,b){if(!h(a)||!h(b)||a.length!==b.length)return!1;a.sort(),b.sort();for(var c=0,d=a.length;d>c;c++)if(a[c]!==b[c])return!1;return!0}function k(a){return escape(a)}function l(a){return encodeURIComponent(a).replace(/[!'()*]/g,k).replace(/\*/g,"%2A")}var m=d&&d.URI;e.version="1.12.0";var n=e.prototype,o=Object.prototype.hasOwnProperty;e._parts=function(){return{protocol:null,username:null,password:null,hostname:null,urn:null,port:null,path:null,query:null,fragment:null,duplicateQueryParameters:e.duplicateQueryParameters,escapeQuerySpace:e.escapeQuerySpace}},e.duplicateQueryParameters=!1,e.escapeQuerySpace=!0,e.protocol_expression=/^[a-z][a-z0-9.+-]*$/i,e.idn_expression=/[^a-z0-9\.-]/i,e.punycode_expression=/(xn--)/i,e.ip4_expression=/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,e.ip6_expression=/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,e.find_uri_expression=/\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u2018\u2019]))/gi,e.findUri={start:/\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,end:/[\s\r\n]|$/,trim:/[`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u201e\u2018\u2019]+$/},e.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"},e.invalid_hostname_characters=/[^a-zA-Z0-9\.-]/,e.domAttributes={a:"href",blockquote:"cite",link:"href",base:"href",script:"src",form:"action",img:"src",area:"href",iframe:"src",embed:"src",source:"src",track:"src",input:"src"},e.getDomAttribute=function(a){if(a&&a.nodeName){var b=a.nodeName.toLowerCase();return"input"===b&&"image"!==a.type?void 0:e.domAttributes[b]}},e.encode=l,e.decode=decodeURIComponent,e.iso8859=function(){e.encode=escape,e.decode=unescape},e.unicode=function(){e.encode=l,e.decode=decodeURIComponent},e.characters={pathname:{encode:{expression:/%(24|26|2B|2C|3B|3D|3A|40)/gi,map:{"%24":"$","%26":"&","%2B":"+","%2C":",","%3B":";","%3D":"=","%3A":":","%40":"@"}},decode:{expression:/[\/\?#]/g,map:{"/":"%2F","?":"%3F","#":"%23"}}},reserved:{encode:{expression:/%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/gi,map:{"%3A":":","%2F":"/","%3F":"?","%23":"#","%5B":"[","%5D":"]","%40":"@","%21":"!","%24":"$","%26":"&","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"="}}}},e.encodeQuery=function(a,b){var c=e.encode(a+"");return b?c.replace(/%20/g,"+"):c},e.decodeQuery=function(a,b){a+="";try{return e.decode(b?a.replace(/\+/g,"%20"):a)}catch(c){return a}},e.recodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;c>b;b++)a[b]=e.encodePathSegment(e.decode(a[b]));return a.join("/")},e.decodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;c>b;b++)a[b]=e.decodePathSegment(a[b]);return a.join("/")};var p,q={encode:"encode",decode:"decode"},r=function(a,b){return function(c){return e[b](c+"").replace(e.characters[a][b].expression,function(c){return e.characters[a][b].map[c]})}};for(p in q)e[p+"PathSegment"]=r("pathname",q[p]);e.encodeReserved=r("reserved","encode"),e.parse=function(a,b){var c;return b||(b={}),c=a.indexOf("#"),c>-1&&(b.fragment=a.substring(c+1)||null,a=a.substring(0,c)),c=a.indexOf("?"),c>-1&&(b.query=a.substring(c+1)||null,a=a.substring(0,c)),"//"===a.substring(0,2)?(b.protocol=null,a=a.substring(2),a=e.parseAuthority(a,b)):(c=a.indexOf(":"),c>-1&&(b.protocol=a.substring(0,c)||null,b.protocol&&!b.protocol.match(e.protocol_expression)?b.protocol=void 0:"file"===b.protocol?a=a.substring(c+3):"//"===a.substring(c+1,c+3)?(a=a.substring(c+3),a=e.parseAuthority(a,b)):(a=a.substring(c+1),b.urn=!0))),b.path=a,b},e.parseHost=function(a,b){var c,d=a.indexOf("/");return-1===d&&(d=a.length),"["===a.charAt(0)?(c=a.indexOf("]"),b.hostname=a.substring(1,c)||null,b.port=a.substring(c+2,d)||null):a.indexOf(":")!==a.lastIndexOf(":")?(b.hostname=a.substring(0,d)||null,b.port=null):(c=a.substring(0,d).split(":"),b.hostname=c[0]||null,b.port=c[1]||null),b.hostname&&"/"!==a.substring(d).charAt(0)&&(d++,a="/"+a),a.substring(d)||"/"},e.parseAuthority=function(a,b){return a=e.parseUserinfo(a,b),e.parseHost(a,b)},e.parseUserinfo=function(a,b){var c=a.indexOf("/"),d=c>-1?a.lastIndexOf("@",c):a.indexOf("@");return d>-1&&(-1===c||c>d)?(c=a.substring(0,d).split(":"),b.username=c[0]?e.decode(c[0]):null,c.shift(),b.password=c[0]?e.decode(c.join(":")):null,a=a.substring(d+1)):(b.username=null,b.password=null),a},e.parseQuery=function(a,b){if(!a)return{};if(a=a.replace(/&+/g,"&").replace(/^\?*&*|&+$/g,""),!a)return{};for(var c,d,f={},g=a.split("&"),h=g.length,i=0;h>i;i++)c=g[i].split("="),d=e.decodeQuery(c.shift(),b),c=c.length?e.decodeQuery(c.join("="),b):null,f[d]?("string"==typeof f[d]&&(f[d]=[f[d]]),f[d].push(c)):f[d]=c;return f},e.build=function(a){var b="";return a.protocol&&(b+=a.protocol+":"),a.urn||!b&&!a.hostname||(b+="//"),b+=e.buildAuthority(a)||"","string"==typeof a.path&&("/"!==a.path.charAt(0)&&"string"==typeof a.hostname&&(b+="/"),b+=a.path),"string"==typeof a.query&&a.query&&(b+="?"+a.query),"string"==typeof a.fragment&&a.fragment&&(b+="#"+a.fragment),b},e.buildHost=function(a){var b="";return a.hostname?(e.ip6_expression.test(a.hostname)?b=a.port?b+("["+a.hostname+"]:"+a.port):b+a.hostname:(b+=a.hostname,a.port&&(b+=":"+a.port)),b):""},e.buildAuthority=function(a){return e.buildUserinfo(a)+e.buildHost(a)},e.buildUserinfo=function(a){var b="";return a.username&&(b+=e.encode(a.username),a.password&&(b+=":"+e.encode(a.password)),b+="@"),b},e.buildQuery=function(a,b,c){var d,f,g,i,j="";for(f in a)if(o.call(a,f)&&f)if(h(a[f]))for(d={},g=0,i=a[f].length;i>g;g++)void 0!==a[f][g]&&void 0===d[a[f][g]+""]&&(j+="&"+e.buildQueryParameter(f,a[f][g],c),!0!==b&&(d[a[f][g]+""]=!0));else void 0!==a[f]&&(j+="&"+e.buildQueryParameter(f,a[f],c));return j.substring(1)},e.buildQueryParameter=function(a,b,c){return e.encodeQuery(a,c)+(null!==b?"="+e.encodeQuery(b,c):"")},e.addQuery=function(a,b,c){if("object"==typeof b)for(var d in b)o.call(b,d)&&e.addQuery(a,d,b[d]);else{if("string"!=typeof b)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");void 0===a[b]?a[b]=c:("string"==typeof a[b]&&(a[b]=[a[b]]),h(c)||(c=[c]),a[b]=a[b].concat(c))}},e.removeQuery=function(a,b,c){var d;if(h(b))for(c=0,d=b.length;d>c;c++)a[b[c]]=void 0;else if("object"==typeof b)for(d in b)o.call(b,d)&&e.removeQuery(a,d,b[d]);else{if("string"!=typeof b)throw new TypeError("URI.addQuery() accepts an object, string as the first parameter");if(void 0!==c){if(a[b]===c)a[b]=void 0;else if(h(a[b])){d=a[b];var f,g,i={};if(h(c))for(f=0,g=c.length;g>f;f++)i[c[f]]=!0;else i[c]=!0;for(f=0,g=d.length;g>f;f++)void 0!==i[d[f]]&&(d.splice(f,1),g--,f--);a[b]=d}}else a[b]=void 0}},e.hasQuery=function(a,b,c,d){if("object"==typeof b){for(var f in b)if(o.call(b,f)&&!e.hasQuery(a,f,b[f]))return!1;return!0}if("string"!=typeof b)throw new TypeError("URI.hasQuery() accepts an object, string as the name parameter");switch(g(c)){case"Undefined":return b in a;case"Boolean":return a=Boolean(h(a[b])?a[b].length:a[b]),c===a;case"Function":return!!c(a[b],b,a);case"Array":return h(a[b])?(d?i:j)(a[b],c):!1;case"RegExp":return h(a[b])?d?i(a[b],c):!1:Boolean(a[b]&&a[b].match(c));case"Number":c=String(c);case"String":return h(a[b])?d?i(a[b],c):!1:a[b]===c;default:throw new TypeError("URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter")}},e.commonPath=function(a,b){var c,d=Math.min(a.length,b.length);for(c=0;d>c;c++)if(a.charAt(c)!==b.charAt(c)){c--;break}return 1>c?a.charAt(0)===b.charAt(0)&&"/"===a.charAt(0)?"/":"":(("/"!==a.charAt(c)||"/"!==b.charAt(c))&&(c=a.substring(0,c).lastIndexOf("/")),a.substring(0,c+1))},e.withinString=function(a,b,c){c||(c={});var d=c.start||e.findUri.start,f=c.end||e.findUri.end,g=c.trim||e.findUri.trim,h=/[a-z0-9-]=["']?$/i;for(d.lastIndex=0;;){var i=d.exec(a);if(!i)break;if(i=i.index,c.ignoreHtml){var j=a.slice(Math.max(i-3,0),i);if(j&&h.test(j))continue}var j=i+a.slice(i).search(f),k=a.slice(i,j).replace(g,"");c.ignore&&c.ignore.test(k)||(j=i+k.length,k=b(k,i,j,a),a=a.slice(0,i)+k+a.slice(j),d.lastIndex=i+k.length)}return d.lastIndex=0,a},e.ensureValidHostname=function(b){if(b.match(e.invalid_hostname_characters)){if(!a)throw new TypeError("Hostname '"+b+"' contains characters other than [A-Z0-9.-] and Punycode.js is not available");
-if(a.toASCII(b).match(e.invalid_hostname_characters))throw new TypeError("Hostname '"+b+"' contains characters other than [A-Z0-9.-]")}},e.noConflict=function(a){return a?(a={URI:this.noConflict()},URITemplate&&"function"==typeof URITemplate.noConflict&&(a.URITemplate=URITemplate.noConflict()),b&&"function"==typeof b.noConflict&&(a.IPv6=b.noConflict()),SecondLevelDomains&&"function"==typeof SecondLevelDomains.noConflict&&(a.SecondLevelDomains=SecondLevelDomains.noConflict()),a):(d.URI===this&&(d.URI=m),this)},n.build=function(a){return!0===a?this._deferred_build=!0:(void 0===a||this._deferred_build)&&(this._string=e.build(this._parts),this._deferred_build=!1),this},n.clone=function(){return new e(this)},n.valueOf=n.toString=function(){return this.build(!1)._string},q={protocol:"protocol",username:"username",password:"password",hostname:"hostname",port:"port"},r=function(a){return function(b,c){return void 0===b?this._parts[a]||"":(this._parts[a]=b||null,this.build(!c),this)}};for(p in q)n[p]=r(q[p]);q={query:"?",fragment:"#"},r=function(a,b){return function(c,d){return void 0===c?this._parts[a]||"":(null!==c&&(c+="",c.charAt(0)===b&&(c=c.substring(1))),this._parts[a]=c,this.build(!d),this)}};for(p in q)n[p]=r(p,q[p]);q={search:["?","query"],hash:["#","fragment"]},r=function(a,b){return function(c,d){var e=this[a](c,d);return"string"==typeof e&&e.length?b+e:e}};for(p in q)n[p]=r(q[p][1],q[p][0]);n.pathname=function(a,b){if(void 0===a||!0===a){var c=this._parts.path||(this._parts.hostname?"/":"");return a?e.decodePath(c):c}return this._parts.path=a?e.recodePath(a):"/",this.build(!b),this},n.path=n.pathname,n.href=function(a,b){var c;if(void 0===a)return this.toString();this._string="",this._parts=e._parts();var d=a instanceof e,f="object"==typeof a&&(a.hostname||a.path||a.pathname);if(a.nodeName&&(f=e.getDomAttribute(a),a=a[f]||"",f=!1),!d&&f&&void 0!==a.pathname&&(a=a.toString()),"string"==typeof a)this._parts=e.parse(a,this._parts);else{if(!d&&!f)throw new TypeError("invalid input");for(c in d=d?a._parts:a)o.call(this._parts,c)&&(this._parts[c]=d[c])}return this.build(!b),this},n.is=function(a){var b=!1,d=!1,f=!1,g=!1,h=!1,i=!1,j=!1,k=!this._parts.urn;switch(this._parts.hostname&&(k=!1,d=e.ip4_expression.test(this._parts.hostname),f=e.ip6_expression.test(this._parts.hostname),b=d||f,h=(g=!b)&&c&&c.has(this._parts.hostname),i=g&&e.idn_expression.test(this._parts.hostname),j=g&&e.punycode_expression.test(this._parts.hostname)),a.toLowerCase()){case"relative":return k;case"absolute":return!k;case"domain":case"name":return g;case"sld":return h;case"ip":return b;case"ip4":case"ipv4":case"inet4":return d;case"ip6":case"ipv6":case"inet6":return f;case"idn":return i;case"url":return!this._parts.urn;case"urn":return!!this._parts.urn;case"punycode":return j}return null};var s=n.protocol,t=n.port,u=n.hostname;n.protocol=function(a,b){if(void 0!==a&&a&&(a=a.replace(/:(\/\/)?$/,""),!a.match(e.protocol_expression)))throw new TypeError("Protocol '"+a+"' contains characters other than [A-Z0-9.+-] or doesn't start with [A-Z]");return s.call(this,a,b)},n.scheme=n.protocol,n.port=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a&&(0===a&&(a=null),a&&(a+="",":"===a.charAt(0)&&(a=a.substring(1)),a.match(/[^0-9]/))))throw new TypeError("Port '"+a+"' contains characters other than [0-9]");return t.call(this,a,b)},n.hostname=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a){var c={};e.parseHost(a,c),a=c.hostname}return u.call(this,a,b)},n.host=function(a,b){return this._parts.urn?void 0===a?"":this:void 0===a?this._parts.hostname?e.buildHost(this._parts):"":(e.parseHost(a,this._parts),this.build(!b),this)},n.authority=function(a,b){return this._parts.urn?void 0===a?"":this:void 0===a?this._parts.hostname?e.buildAuthority(this._parts):"":(e.parseAuthority(a,this._parts),this.build(!b),this)},n.userinfo=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.username)return"";var c=e.buildUserinfo(this._parts);return c.substring(0,c.length-1)}return"@"!==a[a.length-1]&&(a+="@"),e.parseUserinfo(a,this._parts),this.build(!b),this},n.resource=function(a,b){var c;return void 0===a?this.path()+this.search()+this.hash():(c=e.parse(a),this._parts.path=c.path,this._parts.query=c.query,this._parts.fragment=c.fragment,this.build(!b),this)},n.subdomain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.length-this.domain().length-1;return this._parts.hostname.substring(0,c)||""}return c=this._parts.hostname.length-this.domain().length,c=this._parts.hostname.substring(0,c),c=RegExp("^"+f(c)),a&&"."!==a.charAt(a.length-1)&&(a+="."),a&&e.ensureValidHostname(a),this._parts.hostname=this._parts.hostname.replace(c,a),this.build(!b),this},n.domain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if("boolean"==typeof a&&(b=a,a=void 0),void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.match(/\./g);return c&&2>c.length?this._parts.hostname:(c=this._parts.hostname.length-this.tld(b).length-1,c=this._parts.hostname.lastIndexOf(".",c-1)+1,this._parts.hostname.substring(c)||"")}if(!a)throw new TypeError("cannot set domain empty");return e.ensureValidHostname(a),!this._parts.hostname||this.is("IP")?this._parts.hostname=a:(c=RegExp(f(this.domain())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a)),this.build(!b),this},n.tld=function(a,b){if(this._parts.urn)return void 0===a?"":this;if("boolean"==typeof a&&(b=a,a=void 0),void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var d=this._parts.hostname.lastIndexOf("."),d=this._parts.hostname.substring(d+1);return!0!==b&&c&&c.list[d.toLowerCase()]?c.get(this._parts.hostname)||d:d}if(!a)throw new TypeError("cannot set TLD empty");if(a.match(/[^a-zA-Z0-9-]/)){if(!c||!c.is(a))throw new TypeError("TLD '"+a+"' contains characters other than [A-Z0-9]");d=RegExp(f(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(d,a)}else{if(!this._parts.hostname||this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");d=RegExp(f(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(d,a)}return this.build(!b),this},n.directory=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var c=this._parts.path.length-this.filename().length-1,c=this._parts.path.substring(0,c)||(this._parts.hostname?"/":"");return a?e.decodePath(c):c}return c=this._parts.path.length-this.filename().length,c=this._parts.path.substring(0,c),c=RegExp("^"+f(c)),this.is("relative")||(a||(a="/"),"/"!==a.charAt(0)&&(a="/"+a)),a&&"/"!==a.charAt(a.length-1)&&(a+="/"),a=e.recodePath(a),this._parts.path=this._parts.path.replace(c,a),this.build(!b),this},n.filename=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var c=this._parts.path.lastIndexOf("/"),c=this._parts.path.substring(c+1);return a?e.decodePathSegment(c):c}c=!1,"/"===a.charAt(0)&&(a=a.substring(1)),a.match(/\.?\//)&&(c=!0);var d=RegExp(f(this.filename())+"$");return a=e.recodePath(a),this._parts.path=this._parts.path.replace(d,a),c?this.normalizePath(b):this.build(!b),this},n.suffix=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var c=this.filename(),d=c.lastIndexOf(".");return-1===d?"":(c=c.substring(d+1),c=/^[a-z0-9%]+$/i.test(c)?c:"",a?e.decodePathSegment(c):c)}if("."===a.charAt(0)&&(a=a.substring(1)),c=this.suffix())d=a?RegExp(f(c)+"$"):RegExp(f("."+c)+"$");else{if(!a)return this;this._parts.path+="."+e.recodePath(a)}return d&&(a=e.recodePath(a),this._parts.path=this._parts.path.replace(d,a)),this.build(!b),this},n.segment=function(a,b,c){var d=this._parts.urn?":":"/",e=this.path(),f="/"===e.substring(0,1),e=e.split(d);if(void 0!==a&&"number"!=typeof a&&(c=b,b=a,a=void 0),void 0!==a&&"number"!=typeof a)throw Error("Bad segment '"+a+"', must be 0-based integer");if(f&&e.shift(),0>a&&(a=Math.max(e.length+a,0)),void 0===b)return void 0===a?e:e[a];if(null===a||void 0===e[a])if(h(b)){e=[],a=0;for(var g=b.length;g>a;a++)(b[a].length||e.length&&e[e.length-1].length)&&(e.length&&!e[e.length-1].length&&e.pop(),e.push(b[a]))}else(b||"string"==typeof b)&&(""===e[e.length-1]?e[e.length-1]=b:e.push(b));else b||"string"==typeof b&&b.length?e[a]=b:e.splice(a,1);return f&&e.unshift(""),this.path(e.join(d),c)},n.segmentCoded=function(a,b,c){var d,f;if("number"!=typeof a&&(c=b,b=a,a=void 0),void 0===b){if(a=this.segment(a,b,c),h(a))for(d=0,f=a.length;f>d;d++)a[d]=e.decode(a[d]);else a=void 0!==a?e.decode(a):void 0;return a}if(h(b))for(d=0,f=b.length;f>d;d++)b[d]=e.decode(b[d]);else b="string"==typeof b?e.encode(b):b;return this.segment(a,b,c)};var v=n.query;return n.query=function(a,b){if(!0===a)return e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("function"==typeof a){var c=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace),d=a.call(this,c);return this._parts.query=e.buildQuery(d||c,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!b),this}return void 0!==a&&"string"!=typeof a?(this._parts.query=e.buildQuery(a,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!b),this):v.call(this,a,b)},n.setQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("object"==typeof a)for(var f in a)o.call(a,f)&&(d[f]=a[f]);else{if("string"!=typeof a)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");d[a]=void 0!==b?b:null}return this._parts.query=e.buildQuery(d,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof a&&(c=b),this.build(!c),this},n.addQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return e.addQuery(d,a,void 0===b?null:b),this._parts.query=e.buildQuery(d,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof a&&(c=b),this.build(!c),this},n.removeQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return e.removeQuery(d,a,b),this._parts.query=e.buildQuery(d,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof a&&(c=b),this.build(!c),this},n.hasQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return e.hasQuery(d,a,b,c)},n.setSearch=n.setQuery,n.addSearch=n.addQuery,n.removeSearch=n.removeQuery,n.hasSearch=n.hasQuery,n.normalize=function(){return this._parts.urn?this.normalizeProtocol(!1).normalizeQuery(!1).normalizeFragment(!1).build():this.normalizeProtocol(!1).normalizeHostname(!1).normalizePort(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build()},n.normalizeProtocol=function(a){return"string"==typeof this._parts.protocol&&(this._parts.protocol=this._parts.protocol.toLowerCase(),this.build(!a)),this},n.normalizeHostname=function(c){return this._parts.hostname&&(this.is("IDN")&&a?this._parts.hostname=a.toASCII(this._parts.hostname):this.is("IPv6")&&b&&(this._parts.hostname=b.best(this._parts.hostname)),this._parts.hostname=this._parts.hostname.toLowerCase(),this.build(!c)),this},n.normalizePort=function(a){return"string"==typeof this._parts.protocol&&this._parts.port===e.defaultPorts[this._parts.protocol]&&(this._parts.port=null,this.build(!a)),this},n.normalizePath=function(a){if(this._parts.urn||!this._parts.path||"/"===this._parts.path)return this;var b,c,d,f=this._parts.path,g="";for("/"!==f.charAt(0)&&(b=!0,f="/"+f),f=f.replace(/(\/(\.\/)+)|(\/\.$)/g,"/").replace(/\/{2,}/g,"/"),b&&(g=f.substring(1).match(/^(\.\.\/)+/)||"")&&(g=g[0]);c=f.indexOf("/.."),-1!==c;)0!==c?(d=f.substring(0,c).lastIndexOf("/"),-1===d&&(d=c),f=f.substring(0,d)+f.substring(c+3)):f=f.substring(3);return b&&this.is("relative")&&(f=g+f.substring(1)),f=e.recodePath(f),this._parts.path=f,this.build(!a),this},n.normalizePathname=n.normalizePath,n.normalizeQuery=function(a){return"string"==typeof this._parts.query&&(this._parts.query.length?this.query(e.parseQuery(this._parts.query,this._parts.escapeQuerySpace)):this._parts.query=null,this.build(!a)),this},n.normalizeFragment=function(a){return this._parts.fragment||(this._parts.fragment=null,this.build(!a)),this},n.normalizeSearch=n.normalizeQuery,n.normalizeHash=n.normalizeFragment,n.iso8859=function(){var a=e.encode,b=e.decode;return e.encode=escape,e.decode=decodeURIComponent,this.normalize(),e.encode=a,e.decode=b,this},n.unicode=function(){var a=e.encode,b=e.decode;return e.encode=l,e.decode=unescape,this.normalize(),e.encode=a,e.decode=b,this},n.readable=function(){var b=this.clone();b.username("").password("").normalize();var c="";if(b._parts.protocol&&(c+=b._parts.protocol+"://"),b._parts.hostname&&(b.is("punycode")&&a?(c+=a.toUnicode(b._parts.hostname),b._parts.port&&(c+=":"+b._parts.port)):c+=b.host()),b._parts.hostname&&b._parts.path&&"/"!==b._parts.path.charAt(0)&&(c+="/"),c+=b.path(!0),b._parts.query){for(var d="",f=0,g=b._parts.query.split("&"),h=g.length;h>f;f++){var i=(g[f]||"").split("="),d=d+("&"+e.decodeQuery(i[0],this._parts.escapeQuerySpace).replace(/&/g,"%26"));void 0!==i[1]&&(d+="="+e.decodeQuery(i[1],this._parts.escapeQuerySpace).replace(/&/g,"%26"))}c+="?"+d.substring(1)}return c+=e.decodeQuery(b.hash(),!0)},n.absoluteTo=function(a){var b,c,d=this.clone(),f=["protocol","username","password","hostname","port"];if(this._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");if(a instanceof e||(a=new e(a)),d._parts.protocol||(d._parts.protocol=a._parts.protocol),this._parts.hostname)return d;for(b=0;c=f[b];b++)d._parts[c]=a._parts[c];return d._parts.path?".."===d._parts.path.substring(-2)&&(d._parts.path+="/"):(d._parts.path=a._parts.path,d._parts.query||(d._parts.query=a._parts.query)),"/"!==d.path().charAt(0)&&(a=a.directory(),d._parts.path=(a?a+"/":"")+d._parts.path,d.normalizePath()),d.build(),d},n.relativeTo=function(a){var b,c,d,f,g=this.clone().normalize();if(g._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");if(a=new e(a).normalize(),b=g._parts,c=a._parts,d=g.path(),f=a.path(),"/"!==d.charAt(0))throw Error("URI is already relative");if("/"!==f.charAt(0))throw Error("Cannot calculate a URI relative to another relative URI");return b.protocol===c.protocol&&(b.protocol=null),b.username!==c.username||b.password!==c.password||null!==b.protocol||null!==b.username||null!==b.password||b.hostname!==c.hostname||b.port!==c.port?g.build():(b.hostname=null,b.port=null,d===f?(b.path="",g.build()):(a=e.commonPath(g.path(),a.path()))?(c=c.path.substring(a.length).replace(/[^\/]*$/,"").replace(/.*?\//g,"../"),b.path=c+b.path.substring(a.length),g.build()):g.build())},n.equals=function(a){var b=this.clone();a=new e(a);var c,d={},f={},g={};if(b.normalize(),a.normalize(),b.toString()===a.toString())return!0;if(d=b.query(),f=a.query(),b.query(""),a.query(""),b.toString()!==a.toString()||d.length!==f.length)return!1;d=e.parseQuery(d,this._parts.escapeQuerySpace),f=e.parseQuery(f,this._parts.escapeQuerySpace);for(c in d)if(o.call(d,c)){if(h(d[c])){if(!j(d[c],f[c]))return!1}else if(d[c]!==f[c])return!1;g[c]=!0}for(c in f)if(o.call(f,c)&&!g[c])return!1;return!0},n.duplicateQueryParameters=function(a){return this._parts.duplicateQueryParameters=!!a,this},n.escapeQuerySpace=function(a){return this._parts.escapeQuerySpace=!!a,this},e}),function(a,b){"object"==typeof exports?module.exports=b(require("./URI")):"function"==typeof define&&define.amd?define(["./URI"],b):b(a.URI)}(this,function(a){var b=a.prototype,c=b.fragment;a.fragmentPrefix="?";var d=a._parts;return a._parts=function(){var b=d();return b.fragmentPrefix=a.fragmentPrefix,b},b.fragmentPrefix=function(a){return this._parts.fragmentPrefix=a,this},b.fragment=function(b,d){var e=this._parts.fragmentPrefix,f=this._parts.fragment||"";return!0===b?f.substring(0,e.length)!==e?{}:a.parseQuery(f.substring(e.length)):void 0!==b&&"string"!=typeof b?(this._parts.fragment=e+a.buildQuery(b),this.build(!d),this):c.call(this,b,d)},b.addFragment=function(b,c,d){var e=this._parts.fragmentPrefix,f=a.parseQuery((this._parts.fragment||"").substring(e.length));return a.addQuery(f,b,c),this._parts.fragment=e+a.buildQuery(f),"string"!=typeof b&&(d=c),this.build(!d),this},b.removeFragment=function(b,c,d){var e=this._parts.fragmentPrefix,f=a.parseQuery((this._parts.fragment||"").substring(e.length));return a.removeQuery(f,b,c),this._parts.fragment=e+a.buildQuery(f),"string"!=typeof b&&(d=c),this.build(!d),this},b.addHash=b.addFragment,b.removeHash=b.removeFragment,{}}),function(a){"use strict";function b(a){var c;if(null===a||void 0===a)return!1;if(d.isArray(a))return a.length>0;if("string"==typeof a||"number"==typeof a||"boolean"==typeof a)return!0;for(c in a)if(a.hasOwnProperty(c)&&b(a[c]))return!0;return!1}var c=function(){function a(a){this.options=a}return a.prototype.toString=function(){return JSON&&JSON.stringify?JSON.stringify(this.options):this.options},a}(),d=function(){function a(a){return"[object Array]"===Object.prototype.toString.apply(a)}function b(a){return"[object String]"===Object.prototype.toString.apply(a)}function c(a){return"[object Number]"===Object.prototype.toString.apply(a)}function d(a){return"[object Boolean]"===Object.prototype.toString.apply(a)}function e(a,b){var c,d="",e=!0;for(c=0;c<a.length;c+=1)e?e=!1:d+=b,d+=a[c];return d}function f(a,b){for(var c=[],d=0;d<a.length;d+=1)c.push(b(a[d]));return c}function g(a,b){for(var c=[],d=0;d<a.length;d+=1)b(a[d])&&c.push(a[d]);return c}function h(a){if("object"!=typeof a||null===a)return a;Object.freeze(a);var b,c;for(c in a)a.hasOwnProperty(c)&&(b=a[c],"object"!=typeof b||b instanceof RegExp||i(b));return a}function i(a){return"function"==typeof Object.freeze?h(a):a}return{isArray:a,isString:b,isNumber:c,isBoolean:d,join:e,map:f,filter:g,deepFreeze:i}}(),e=function(){function a(a){return a>="a"&&"z">=a||a>="A"&&"Z">=a}function b(a){return a>="0"&&"9">=a}function c(a){return b(a)||a>="a"&&"f">=a||a>="A"&&"F">=a}return{isAlpha:a,isDigit:b,isHexDigit:c}}(),f=function(){function a(a){var b,c,d="",e=g.encode(a);for(c=0;c<e.length;c+=1)b=e.charCodeAt(c),d+="%"+(16>b?"0":"")+b.toString(16).toUpperCase();return d}function b(a,b){return"%"===a.charAt(b)&&e.isHexDigit(a.charAt(b+1))&&e.isHexDigit(a.charAt(b+2))}function c(a,b){return parseInt(a.substr(b,2),16)}function d(a){if(!b(a,0))return!1;var d=c(a,1),e=g.numBytes(d);if(0===e)return!1;for(var f=1;e>f;f+=1)if(!b(a,3*f)||!g.isValidFollowingCharCode(c(a,3*f+1)))return!1;return!0}function f(a,d){var e=a.charAt(d);if(!b(a,d))return e;var f=c(a,d+1),h=g.numBytes(f);if(0===h)return e;for(var i=1;h>i;i+=1)if(!b(a,d+3*i)||!g.isValidFollowingCharCode(c(a,d+3*i+1)))return e;return a.substr(d,3*h)}var g={encode:function(a){return unescape(encodeURIComponent(a))},numBytes:function(a){return 127>=a?1:a>=194&&223>=a?2:a>=224&&239>=a?3:a>=240&&244>=a?4:0},isValidFollowingCharCode:function(a){return a>=128&&191>=a}};return{encodeCharacter:a,isPctEncoded:d,pctCharAt:f}}(),g=function(){function a(a){return e.isAlpha(a)||e.isDigit(a)||"_"===a||f.isPctEncoded(a)}function b(a){return e.isAlpha(a)||e.isDigit(a)||"-"===a||"."===a||"_"===a||"~"===a}function c(a){return":"===a||"/"===a||"?"===a||"#"===a||"["===a||"]"===a||"@"===a||"!"===a||"$"===a||"&"===a||"("===a||")"===a||"*"===a||"+"===a||","===a||";"===a||"="===a||"'"===a}return{isVarchar:a,isUnreserved:b,isReserved:c}}(),h=function(){function a(a,b){var c,d="",e="";for(("number"==typeof a||"boolean"==typeof a)&&(a=a.toString()),c=0;c<a.length;c+=e.length)e=a.charAt(c),d+=g.isUnreserved(e)||b&&g.isReserved(e)?e:f.encodeCharacter(e);return d}function b(b){return a(b,!0)}function c(a,b){var c=f.pctCharAt(a,b);return c.length>1?c:g.isReserved(c)||g.isUnreserved(c)?c:f.encodeCharacter(c)}function d(a){var b,c="",d="";for(b=0;b<a.length;b+=d.length)d=f.pctCharAt(a,b),c+=d.length>1?d:g.isReserved(d)||g.isUnreserved(d)?d:f.encodeCharacter(d);return c}return{encode:a,encodePassReserved:b,encodeLiteral:d,encodeLiteralCharacter:c}}(),i=function(){function a(a){b[a]={symbol:a,separator:"?"===a?"&":""===a||"+"===a||"#"===a?",":a,named:";"===a||"&"===a||"?"===a,ifEmpty:"&"===a||"?"===a?"=":"",first:"+"===a?"":a,encode:"+"===a||"#"===a?h.encodePassReserved:h.encode,toString:function(){return this.symbol}}}var b={};return a(""),a("+"),a("#"),a("."),a("/"),a(";"),a("?"),a("&"),{valueOf:function(a){return b[a]?b[a]:"=,!@|".indexOf(a)>=0?null:b[""]}}}(),j=function(){function a(a){this.literal=h.encodeLiteral(a)}return a.prototype.expand=function(){return this.literal},a.prototype.toString=a.prototype.expand,a}(),k=function(){function a(a){function b(){var b=a.substring(n,j);if(0===b.length)throw new c({expressionText:a,message:"a varname must be specified",position:j});m={varname:b,exploded:!1,maxLength:null},n=null}function d(){if(o===j)throw new c({expressionText:a,message:"after a ':' you have to specify the length",position:j});m.maxLength=parseInt(a.substring(o,j),10),o=null}var h,j,k=[],m=null,n=null,o=null,p="";for(h=function(b){var d=i.valueOf(b);if(null===d)throw new c({expressionText:a,message:"illegal use of reserved operator",position:j,operator:b});return d}(a.charAt(0)),j=h.symbol.length,n=j;j<a.length;j+=p.length){if(p=f.pctCharAt(a,j),null!==n){if("."===p){if(n===j)throw new c({expressionText:a,message:"a varname MUST NOT start with a dot",position:j});continue}if(g.isVarchar(p))continue;b()}if(null!==o){if(j===o&&"0"===p)throw new c({expressionText:a,message:"A :prefix must not start with digit 0",position:j});if(e.isDigit(p)){if(j-o>=4)throw new c({expressionText:a,message:"A :prefix must have max 4 digits",position:j});continue}d()}if(":"!==p)if("*"!==p){if(","!==p)throw new c({expressionText:a,message:"illegal character",character:p,position:j});k.push(m),m=null,n=j+1}else{if(null===m)throw new c({expressionText:a,message:"exploded without varspec",position:j});if(m.exploded)throw new c({expressionText:a,message:"exploded twice",position:j});if(m.maxLength)throw new c({expressionText:a,message:"an explode (*) MUST NOT follow to a prefix",position:j});m.exploded=!0}else{if(null!==m.maxLength)throw new c({expressionText:a,message:"only one :maxLength is allowed per varspec",position:j});if(m.exploded)throw new c({expressionText:a,message:"an exploeded varspec MUST NOT be varspeced",position:j});o=j+1}}return null!==n&&b(),null!==o&&d(),k.push(m),new l(a,h,k)}function b(a){return a.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function d(d){var e,f,g,h=[],i=null,k="",l=!0,n=0;for(e=0;e<d.length;e+=1)if(f=d.charAt(e),null===n){if(null===i)throw new Error("reached unreachable code");if("{"===f)throw new c({templateText:d,message:"brace already opened",position:e});if("}"===f){if(i+1===e)throw new c({templateText:d,message:"empty braces",position:i});try{g=a(d.substring(i+1,e))}catch(o){if(o.prototype===c.prototype)throw new c({templateText:d,message:o.options.message,position:i+o.options.position,details:o.options});throw o}h.push(g),0===g.operator.symbol.length?k+="([^/]+)":l=!1,i=null,n=e+1}}else{if("}"===f)throw new c({templateText:d,message:"unopened brace closed",position:e});"{"===f&&(e>n&&(g=new j(d.substring(n,e)),h.push(g),k+=b(g.literal)),n=null,i=e)}if(null!==i)throw new c({templateText:d,message:"unclosed brace",position:i});return n<d.length&&(g=new j(d.substring(n)),h.push(g),k+=b(g.literal)),l===!1&&(k=void 0),new m(d,h,k)}return d}(),l=function(){function a(a){return JSON&&JSON.stringify?JSON.stringify(a):a}function c(a){if(!b(a))return!0;if(d.isString(a))return""===a;if(d.isNumber(a)||d.isBoolean(a))return!1;if(d.isArray(a))return 0===a.length;for(var c in a)if(a.hasOwnProperty(c))return!1;return!0}function e(a){var b,c=[];for(b in a)a.hasOwnProperty(b)&&c.push({name:b,value:a[b]});return c}function f(a,b,c){this.templateText=a,this.operator=b,this.varspecs=c}function g(a,b,c){var d="";if(c=c.toString(),b.named){if(d+=h.encodeLiteral(a.varname),""===c)return d+=b.ifEmpty;d+="="}return null!==a.maxLength&&(c=c.substr(0,a.maxLength)),d+=b.encode(c)}function i(a){return b(a.value)}function j(a,f,g){var j=[],k="";if(f.named){if(k+=h.encodeLiteral(a.varname),c(g))return k+=f.ifEmpty;k+="="}return d.isArray(g)?(j=g,j=d.filter(j,b),j=d.map(j,f.encode),k+=d.join(j,",")):(j=e(g),j=d.filter(j,i),j=d.map(j,function(a){return f.encode(a.name)+","+f.encode(a.value)}),k+=d.join(j,",")),k}function k(a,f,g){var j=d.isArray(g),k=[];return j?(k=g,k=d.filter(k,b),k=d.map(k,function(b){var d=h.encodeLiteral(a.varname);return d+=c(b)?f.ifEmpty:"="+f.encode(b)})):(k=e(g),k=d.filter(k,i),k=d.map(k,function(a){var b=h.encodeLiteral(a.name);return b+=c(a.value)?f.ifEmpty:"="+f.encode(a.value)})),d.join(k,f.separator)}function l(a,c){var f=[],g="";return d.isArray(c)?(f=c,f=d.filter(f,b),f=d.map(f,a.encode),g+=d.join(f,a.separator)):(f=e(c),f=d.filter(f,function(a){return b(a.value)}),f=d.map(f,function(b){return a.encode(b.name)+"="+a.encode(b.value)}),g+=d.join(f,a.separator)),g}return f.prototype.toString=function(){return this.templateText},f.prototype.expand=function(e){var f,h,i,m,n=[],o=!1,p=this.operator;for(f=0;f<this.varspecs.length;f+=1)if(h=this.varspecs[f],i=e[h.varname],null!==i&&void 0!==i)if(h.exploded&&(o=!0),m=d.isArray(i),"string"==typeof i||"number"==typeof i||"boolean"==typeof i)n.push(g(h,p,i));else{if(h.maxLength&&b(i))throw new Error("Prefix modifiers are not applicable to variables that have composite values. You tried to expand "+this+" with "+a(i));h.exploded?b(i)&&(p.named?n.push(k(h,p,i)):n.push(l(p,i))):(p.named||!c(i))&&n.push(j(h,p,i))}return 0===n.length?"":p.first+d.join(n,p.separator)},f}(),m=function(){function a(a,b,c){this.templateText=a,this.expressions=b,void 0!==c&&(this.regexp=new RegExp("^"+c+"$")),d.deepFreeze(this)}return a.prototype.toString=function(){return this.templateText},a.prototype.expand=function(a){var b,c="";for(b=0;b<this.expressions.length;b+=1)c+=this.expressions[b].expand(a);return c},a.prototype.extract=function(a){var b,c,d,e,f=1,g=!0,h={};if(void 0!==this.regexp&&this.regexp.test(a)){for(e=this.regexp.exec(a),b=0;b<this.expressions.length;b+=1)c=this.expressions[b],void 0===c.literal&&(void 0!==c.operator&&0===c.operator.symbol.length&&1===c.varspecs.length?(d=c.varspecs[0],d.exploded===!1&&null===d.maxLength&&-1===e[f].indexOf(",")?(h[d.varname]=decodeURIComponent(e[f]),f+=1):g=!1):g=!1);if(g)return h}return!1},a.parse=k,a.UriTemplateError=c,a}();a(m)}(function(a){"use strict";"undefined"!=typeof module?module.exports=a:"function"==typeof define?define([],function(){return a}):"undefined"!=typeof window?window.UriTemplate=a:global.UriTemplate=a});var LZString=function(){function a(a,b){if(!e[a]){e[a]={};for(var c=0;c<a.length;c++)e[a][a.charAt(c)]=c}return e[a][b]}var b=String.fromCharCode,c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",e={},f={compressToBase64:function(a){if(null==a)return"";var b=f._compress(a,6,function(a){return c.charAt(a)});switch(b.length%4){default:case 0:return b;case 1:return b+"===";case 2:return b+"==";case 3:return b+"="}},decompressFromBase64:function(b){return null==b?"":""==b?null:f._decompress(b.length,32,function(d){return a(c,b.charAt(d))})},compressToUTF16:function(a){return null==a?"":f._compress(a,15,function(a){return b(a+32)})+" "},decompressFromUTF16:function(a){return null==a?"":""==a?null:f._decompress(a.length,16384,function(b){return a.charCodeAt(b)-32})},compressToUint8Array:function(a){for(var b=f.compress(a),c=new Uint8Array(2*b.length),d=0,e=b.length;e>d;d++){var g=b.charCodeAt(d);c[2*d]=g>>>8,c[2*d+1]=g%256}return c},decompressFromUint8Array:function(a){if(null===a||void 0===a)return f.decompress(a);for(var c=new Array(a.length/2),d=0,e=c.length;e>d;d++)c[d]=256*a[2*d]+a[2*d+1];var g=[];return c.forEach(function(a){g.push(b(a))}),f.decompress(g.join(""))},compressToEncodedURIComponent:function(a){return null==a?"":f._compress(a,6,function(a){return d.charAt(a)})},decompressFromEncodedURIComponent:function(b){return null==b?"":""==b?null:(b=b.replace(/ /g,"+"),f._decompress(b.length,32,function(c){return a(d,b.charAt(c))}))},compress:function(a){return f._compress(a,16,function(a){return b(a)})},_compress:function(a,b,c){if(null==a)return"";var d,e,f,g={},h={},i="",j="",k="",l=2,m=3,n=2,o=[],p=0,q=0;for(f=0;f<a.length;f+=1)if(i=a.charAt(f),Object.prototype.hasOwnProperty.call(g,i)||(g[i]=m++,h[i]=!0),j=k+i,Object.prototype.hasOwnProperty.call(g,j))k=j;else{if(Object.prototype.hasOwnProperty.call(h,k)){if(k.charCodeAt(0)<256){for(d=0;n>d;d++)p<<=1,q==b-1?(q=0,o.push(c(p)),p=0):q++;for(e=k.charCodeAt(0),d=0;8>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}else{for(e=1,d=0;n>d;d++)p=p<<1|e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e=0;for(e=k.charCodeAt(0),d=0;16>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}l--,0==l&&(l=Math.pow(2,n),n++),delete h[k]}else for(e=g[k],d=0;n>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1;l--,0==l&&(l=Math.pow(2,n),n++),g[j]=m++,k=String(i)}if(""!==k){if(Object.prototype.hasOwnProperty.call(h,k)){if(k.charCodeAt(0)<256){for(d=0;n>d;d++)p<<=1,q==b-1?(q=0,o.push(c(p)),p=0):q++;for(e=k.charCodeAt(0),d=0;8>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}else{for(e=1,d=0;n>d;d++)p=p<<1|e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e=0;for(e=k.charCodeAt(0),d=0;16>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}l--,0==l&&(l=Math.pow(2,n),n++),delete h[k]}else for(e=g[k],d=0;n>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1;l--,0==l&&(l=Math.pow(2,n),n++)}for(e=2,d=0;n>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1;for(;;){if(p<<=1,q==b-1){o.push(c(p));break}q++}return o.join("")},decompress:function(a){return null==a?"":""==a?null:f._decompress(a.length,32768,function(b){return a.charCodeAt(b)})},_decompress:function(a,c,d){var e,f,g,h,i,j,k,l,m=[],n=4,o=4,p=3,q="",r=[],s={val:d(0),position:c,index:1};for(f=0;3>f;f+=1)m[f]=f;for(h=0,j=Math.pow(2,2),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;switch(e=h){case 0:for(h=0,j=Math.pow(2,8),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;l=b(h);break;case 1:for(h=0,j=Math.pow(2,16),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;l=b(h);break;case 2:return""}for(m[3]=l,g=l,r.push(l);;){if(s.index>a)return"";for(h=0,j=Math.pow(2,p),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;switch(l=h){case 0:for(h=0,j=Math.pow(2,8),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;m[o++]=b(h),l=o-1,n--;break;case 1:for(h=0,j=Math.pow(2,16),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;m[o++]=b(h),l=o-1,n--;break;case 2:return r.join("")}if(0==n&&(n=Math.pow(2,p),p++),m[l])q=m[l];else{if(l!==o)return null;q=g+g.charAt(0)}r.push(q),m[o++]=g+q.charAt(0),n--,g=q,0==n&&(n=Math.pow(2,p),p++)}}};return f}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module&&(module.exports=LZString),function(a){function b(a,b){return function(c){return i(a.call(this,c),b)}}function c(a,b){return function(c){return this.lang().ordinal(a.call(this,c),b)}}function d(){}function e(a){u(a),g(this,a)}function f(a){var b=o(a),c=b.year||0,d=b.month||0,e=b.week||0,f=b.day||0,g=b.hour||0,h=b.minute||0,i=b.second||0,j=b.millisecond||0;this._milliseconds=+j+1e3*i+6e4*h+36e5*g,
-this._days=+f+7*e,this._months=+d+12*c,this._data={},this._bubble()}function g(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return b.hasOwnProperty("toString")&&(a.toString=b.toString),b.hasOwnProperty("valueOf")&&(a.valueOf=b.valueOf),a}function h(a){return 0>a?Math.ceil(a):Math.floor(a)}function i(a,b,c){for(var d=Math.abs(a)+"",e=a>=0;d.length<b;)d="0"+d;return(e?c?"+":"":"-")+d}function j(a,b,c,d){var e,f,g=b._milliseconds,h=b._days,i=b._months;g&&a._d.setTime(+a._d+g*c),(h||i)&&(e=a.minute(),f=a.hour()),h&&a.date(a.date()+h*c),i&&a.month(a.month()+i*c),g&&!d&&ca.updateOffset(a),(h||i)&&(a.minute(e),a.hour(f))}function k(a){return"[object Array]"===Object.prototype.toString.call(a)}function l(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function m(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&q(a[d])!==q(b[d]))&&g++;return g+f}function n(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=Qa[a]||Ra[b]||b}return a}function o(a){var b,c,d={};for(c in a)a.hasOwnProperty(c)&&(b=n(c),b&&(d[b]=a[c]));return d}function p(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}ca[b]=function(e,f){var g,h,i=ca.fn._lang[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=ca().utc().set(d,a);return i.call(ca.fn._lang,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function q(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function r(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function s(a){return t(a)?366:365}function t(a){return a%4===0&&a%100!==0||a%400===0}function u(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[ia]<0||a._a[ia]>11?ia:a._a[ja]<1||a._a[ja]>r(a._a[ha],a._a[ia])?ja:a._a[ka]<0||a._a[ka]>23?ka:a._a[la]<0||a._a[la]>59?la:a._a[ma]<0||a._a[ma]>59?ma:a._a[na]<0||a._a[na]>999?na:-1,a._pf._overflowDayOfYear&&(ha>b||b>ja)&&(b=ja),a._pf.overflow=b)}function v(a){a._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function w(a){return null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&a._pf.overflow<0&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length)),a._isValid}function x(a){return a?a.toLowerCase().replace("_","-"):a}function y(a,b){return b._isUTC?ca(a).zone(b._offset||0):ca(a).local()}function z(a,b){return b.abbr=a,oa[a]||(oa[a]=new d),oa[a].set(b),oa[a]}function A(a){delete oa[a]}function B(a){var b,c,d,e,f=0,g=function(a){if(!oa[a]&&pa)try{require("./lang/"+a)}catch(b){}return oa[a]};if(!a)return ca.fn._lang;if(!k(a)){if(c=g(a))return c;a=[a]}for(;f<a.length;){for(e=x(a[f]).split("-"),b=e.length,d=x(a[f+1]),d=d?d.split("-"):null;b>0;){if(c=g(e.slice(0,b).join("-")))return c;if(d&&d.length>=b&&m(e,d,!0)>=b-1)break;b--}f++}return ca.fn._lang}function C(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function D(a){var b,c,d=a.match(ta);for(b=0,c=d.length;c>b;b++)Va[d[b]]?d[b]=Va[d[b]]:d[b]=C(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function E(a,b){return a.isValid()?(b=F(b,a.lang()),Sa[b]||(Sa[b]=D(b)),Sa[b](a)):a.lang().invalidDate()}function F(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(ua.lastIndex=0;d>=0&&ua.test(a);)a=a.replace(ua,c),ua.lastIndex=0,d-=1;return a}function G(a,b){var c,d=b._strict;switch(a){case"DDDD":return Ga;case"YYYY":case"GGGG":case"gggg":return d?Ha:xa;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?Ia:ya;case"S":if(d)return Ea;case"SS":if(d)return Fa;case"SSS":case"DDD":return d?Ga:wa;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Aa;case"a":case"A":return B(b._l)._meridiemParse;case"X":return Da;case"Z":case"ZZ":return Ba;case"T":return Ca;case"SSSS":return za;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?Fa:va;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return d?Ea:va;default:return c=new RegExp(O(N(a.replace("\\","")),"i"))}}function H(a){a=a||"";var b=a.match(Ba)||[],c=b[b.length-1]||[],d=(c+"").match(Na)||["-",0,0],e=+(60*d[1])+q(d[2]);return"+"===d[0]?-e:e}function I(a,b,c){var d,e=c._a;switch(a){case"M":case"MM":null!=b&&(e[ia]=q(b)-1);break;case"MMM":case"MMMM":d=B(c._l).monthsParse(b),null!=d?e[ia]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[ja]=q(b));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=q(b));break;case"YY":e[ha]=q(b)+(q(b)>68?1900:2e3);break;case"YYYY":case"YYYYY":case"YYYYYY":e[ha]=q(b);break;case"a":case"A":c._isPm=B(c._l).isPM(b);break;case"H":case"HH":case"h":case"hh":e[ka]=q(b);break;case"m":case"mm":e[la]=q(b);break;case"s":case"ss":e[ma]=q(b);break;case"S":case"SS":case"SSS":case"SSSS":e[na]=q(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=H(b);break;case"w":case"ww":case"W":case"WW":case"d":case"dd":case"ddd":case"dddd":case"e":case"E":a=a.substr(0,1);case"gg":case"gggg":case"GG":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=b)}}function J(a){var b,c,d,e,f,g,h,i,j,k,l=[];if(!a._d){for(d=L(a),a._w&&null==a._a[ja]&&null==a._a[ia]&&(f=function(b){var c=parseInt(b,10);return b?b.length<3?c>68?1900+c:2e3+c:c:null==a._a[ha]?ca().weekYear():a._a[ha]},g=a._w,null!=g.GG||null!=g.W||null!=g.E?h=Y(f(g.GG),g.W||1,g.E,4,1):(i=B(a._l),j=null!=g.d?U(g.d,i):null!=g.e?parseInt(g.e,10)+i._week.dow:0,k=parseInt(g.w,10)||1,null!=g.d&&j<i._week.dow&&k++,h=Y(f(g.gg),k,j,i._week.doy,i._week.dow)),a._a[ha]=h.year,a._dayOfYear=h.dayOfYear),a._dayOfYear&&(e=null==a._a[ha]?d[ha]:a._a[ha],a._dayOfYear>s(e)&&(a._pf._overflowDayOfYear=!0),c=T(e,0,a._dayOfYear),a._a[ia]=c.getUTCMonth(),a._a[ja]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=l[b]=d[b];for(;7>b;b++)a._a[b]=l[b]=null==a._a[b]?2===b?1:0:a._a[b];l[ka]+=q((a._tzm||0)/60),l[la]+=q((a._tzm||0)%60),a._d=(a._useUTC?T:S).apply(null,l)}}function K(a){var b;a._d||(b=o(a._i),a._a=[b.year,b.month,b.day,b.hour,b.minute,b.second,b.millisecond],J(a))}function L(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function M(a){a._a=[],a._pf.empty=!0;var b,c,d,e,f,g=B(a._l),h=""+a._i,i=h.length,j=0;for(d=F(a._f,g).match(ta)||[],b=0;b<d.length;b++)e=d[b],c=(h.match(G(e,a))||[])[0],c&&(f=h.substr(0,h.indexOf(c)),f.length>0&&a._pf.unusedInput.push(f),h=h.slice(h.indexOf(c)+c.length),j+=c.length),Va[e]?(c?a._pf.empty=!1:a._pf.unusedTokens.push(e),I(e,c,a)):a._strict&&!c&&a._pf.unusedTokens.push(e);a._pf.charsLeftOver=i-j,h.length>0&&a._pf.unusedInput.push(h),a._isPm&&a._a[ka]<12&&(a._a[ka]+=12),a._isPm===!1&&12===a._a[ka]&&(a._a[ka]=0),J(a),u(a)}function N(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function O(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function P(a){var b,c,d,e,f;if(0===a._f.length)return a._pf.invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=g({},a),v(b),b._f=a._f[e],M(b),w(b)&&(f+=b._pf.charsLeftOver,f+=10*b._pf.unusedTokens.length,b._pf.score=f,(null==d||d>f)&&(d=f,c=b));g(a,c||b)}function Q(a){var b,c=a._i,d=Ja.exec(c);if(d){for(a._pf.iso=!0,b=4;b>0;b--)if(d[b]){a._f=La[b-1]+(d[6]||" ");break}for(b=0;4>b;b++)if(Ma[b][1].exec(c)){a._f+=Ma[b][0];break}c.match(Ba)&&(a._f+="Z"),M(a)}else a._d=new Date(c)}function R(b){var c=b._i,d=qa.exec(c);c===a?b._d=new Date:d?b._d=new Date(+d[1]):"string"==typeof c?Q(b):k(c)?(b._a=c.slice(0),J(b)):l(c)?b._d=new Date(+c):"object"==typeof c?K(b):b._d=new Date(c)}function S(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function T(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function U(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function V(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function W(a,b,c){var d=ga(Math.abs(a)/1e3),e=ga(d/60),f=ga(e/60),g=ga(f/24),h=ga(g/365),i=45>d&&["s",d]||1===e&&["m"]||45>e&&["mm",e]||1===f&&["h"]||22>f&&["hh",f]||1===g&&["d"]||25>=g&&["dd",g]||45>=g&&["M"]||345>g&&["MM",ga(g/30)]||1===h&&["y"]||["yy",h];return i[2]=b,i[3]=a>0,i[4]=c,V.apply({},i)}function X(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=ca(a).add("d",f),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function Y(a,b,c,d,e){var f,g,h=new Date(i(a,6,!0)+"-01-01").getUTCDay();return c=null!=c?c:e,f=e-h+(h>d?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:s(a-1)+g}}function Z(a){var b=a._i,c=a._f;return"undefined"==typeof a._pf&&v(a),null===b?ca.invalid({nullInput:!0}):("string"==typeof b&&(a._i=b=B().preparse(b)),ca.isMoment(b)?(a=g({},b),a._d=new Date(+b._d)):c?k(c)?P(a):M(a):R(a),new e(a))}function $(a,b){ca.fn[a]=ca.fn[a+"s"]=function(a){var c=this._isUTC?"UTC":"";return null!=a?(this._d["set"+c+b](a),ca.updateOffset(this),this):this._d["get"+c+b]()}}function _(a){ca.duration.fn[a]=function(){return this._data[a]}}function aa(a,b){ca.duration.fn["as"+a]=function(){return+this/b}}function ba(a){var b=!1,c=ca;"undefined"==typeof ender&&(a?(fa.moment=function(){return!b&&console&&console.warn&&(b=!0,console.warn("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.")),c.apply(null,arguments)},g(fa.moment,c)):fa.moment=ca)}for(var ca,da,ea="2.5.0",fa=this,ga=Math.round,ha=0,ia=1,ja=2,ka=3,la=4,ma=5,na=6,oa={},pa="undefined"!=typeof module&&module.exports&&"undefined"!=typeof require,qa=/^\/?Date\((\-?\d+)/i,ra=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,sa=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,ta=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,ua=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,va=/\d\d?/,wa=/\d{1,3}/,xa=/\d{1,4}/,ya=/[+\-]?\d{1,6}/,za=/\d+/,Aa=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Ba=/Z|[\+\-]\d\d:?\d\d/gi,Ca=/T/i,Da=/[\+\-]?\d+(\.\d{1,3})?/,Ea=/\d/,Fa=/\d\d/,Ga=/\d{3}/,Ha=/\d{4}/,Ia=/[+\-]?\d{6}/,Ja=/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Ka="YYYY-MM-DDTHH:mm:ssZ",La=["YYYY-MM-DD","GGGG-[W]WW","GGGG-[W]WW-E","YYYY-DDD"],Ma=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],Na=/([\+\-]|\d\d)/gi,Oa="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),Pa={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},Qa={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",y:"year",DDD:"dayOfYear",e:"weekday",E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},Ra={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},Sa={},Ta="DDD w W M D d".split(" "),Ua="M D H h m s w W".split(" "),Va={M:function(){return this.month()+1},MMM:function(a){return this.lang().monthsShort(this,a)},MMMM:function(a){return this.lang().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.lang().weekdaysMin(this,a)},ddd:function(a){return this.lang().weekdaysShort(this,a)},dddd:function(a){return this.lang().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return i(this.year()%100,2)},YYYY:function(){return i(this.year(),4)},YYYYY:function(){return i(this.year(),5)},YYYYYY:function(){var a=this.year(),b=a>=0?"+":"-";return b+i(Math.abs(a),6)},gg:function(){return i(this.weekYear()%100,2)},gggg:function(){return this.weekYear()},ggggg:function(){return i(this.weekYear(),5)},GG:function(){return i(this.isoWeekYear()%100,2)},GGGG:function(){return this.isoWeekYear()},GGGGG:function(){return i(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return q(this.milliseconds()/100)},SS:function(){return i(q(this.milliseconds()/10),2)},SSS:function(){return i(this.milliseconds(),3)},SSSS:function(){return i(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+i(q(a/60),2)+":"+i(q(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+i(q(a/60),2)+i(q(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},Wa=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];Ta.length;)da=Ta.pop(),Va[da+"o"]=c(Va[da],da);for(;Ua.length;)da=Ua.pop(),Va[da+da]=b(Va[da],2);for(Va.DDDD=b(Va.DDD,3),g(d.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=ca.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=ca([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few 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"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return X(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),ca=function(b,c,d,e){return"boolean"==typeof d&&(e=d,d=a),Z({_i:b,_f:c,_l:d,_strict:e,_isUTC:!1})},ca.utc=function(b,c,d,e){var f;return"boolean"==typeof d&&(e=d,d=a),f=Z({_useUTC:!0,_isUTC:!0,_l:d,_i:b,_f:c,_strict:e}).utc()},ca.unix=function(a){return ca(1e3*a)},ca.duration=function(a,b){var c,d,e,g=a,h=null;return ca.isDuration(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=ra.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:q(h[ja])*c,h:q(h[ka])*c,m:q(h[la])*c,s:q(h[ma])*c,ms:q(h[na])*c}):(h=sa.exec(a))&&(c="-"===h[1]?-1:1,e=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*c},g={y:e(h[2]),M:e(h[3]),d:e(h[4]),h:e(h[5]),m:e(h[6]),s:e(h[7]),w:e(h[8])}),d=new f(g),ca.isDuration(a)&&a.hasOwnProperty("_lang")&&(d._lang=a._lang),d},ca.version=ea,ca.defaultFormat=Ka,ca.updateOffset=function(){},ca.lang=function(a,b){var c;return a?(b?z(x(a),b):null===b?(A(a),a="en"):oa[a]||B(a),c=ca.duration.fn._lang=ca.fn._lang=B(a),c._abbr):ca.fn._lang._abbr},ca.langData=function(a){return a&&a._lang&&a._lang._abbr&&(a=a._lang._abbr),B(a)},ca.isMoment=function(a){return a instanceof e},ca.isDuration=function(a){return a instanceof f},da=Wa.length-1;da>=0;--da)p(Wa[da]);for(ca.normalizeUnits=function(a){return n(a)},ca.invalid=function(a){var b=ca.utc(NaN);return null!=a?g(b._pf,a):b._pf.userInvalidated=!0,b},ca.parseZone=function(a){return ca(a).parseZone()},g(ca.fn=e.prototype,{clone:function(){return ca(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=ca(this).utc();return 0<a.year()&&a.year()<=9999?E(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):E(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds()]},isValid:function(){return w(this)},isDSTShifted:function(){return this._a?this.isValid()&&m(this._a,(this._isUTC?ca.utc(this._a):ca(this._a)).toArray())>0:!1},parsingFlags:function(){return g({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(a){var b=E(this,a||ca.defaultFormat);return this.lang().postformat(b)},add:function(a,b){var c;return c="string"==typeof a?ca.duration(+b,a):ca.duration(a,b),j(this,c,1),this},subtract:function(a,b){var c;return c="string"==typeof a?ca.duration(+b,a):ca.duration(a,b),j(this,c,-1),this},diff:function(a,b,c){var d,e,f=y(a,this),g=6e4*(this.zone()-f.zone());return b=n(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+f.daysInMonth()),e=12*(this.year()-f.year())+(this.month()-f.month()),e+=(this-ca(this).startOf("month")-(f-ca(f).startOf("month")))/d,e-=6e4*(this.zone()-ca(this).startOf("month").zone()-(f.zone()-ca(f).startOf("month").zone()))/d,"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:h(e)},from:function(a,b){return ca.duration(this.diff(a)).lang(this.lang()._abbr).humanize(!b)},fromNow:function(a){return this.from(ca(),a)},calendar:function(){var a=y(ca(),this).startOf("day"),b=this.diff(a,"days",!0),c=-6>b?"sameElse":-1>b?"lastWeek":0>b?"lastDay":1>b?"sameDay":2>b?"nextDay":7>b?"nextWeek":"sameElse";return this.format(this.lang().calendar(c,this))},isLeapYear:function(){return t(this.year())},isDST:function(){return this.zone()<this.clone().month(0).zone()||this.zone()<this.clone().month(5).zone()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=U(a,this.lang()),this.add({d:a-b})):b},month:function(a){var b,c=this._isUTC?"UTC":"";return null!=a?"string"==typeof a&&(a=this.lang().monthsParse(a),"number"!=typeof a)?this:(b=this.date(),this.date(1),this._d["set"+c+"Month"](a),this.date(Math.min(b,this.daysInMonth())),ca.updateOffset(this),this):this._d["get"+c+"Month"]()},startOf:function(a){switch(a=n(a)){case"year":this.month(0);case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a?this.weekday(0):"isoWeek"===a&&this.isoWeekday(1),this},endOf:function(a){return a=n(a),this.startOf(a).add("isoWeek"===a?"week":a,1).subtract("ms",1)},isAfter:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)>+ca(a).startOf(b)},isBefore:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)<+ca(a).startOf(b)},isSame:function(a,b){return b=b||"ms",+this.clone().startOf(b)===+y(a,this).startOf(b)},min:function(a){return a=ca.apply(null,arguments),this>a?this:a},max:function(a){return a=ca.apply(null,arguments),a>this?this:a},zone:function(a){var b=this._offset||0;return null==a?this._isUTC?b:this._d.getTimezoneOffset():("string"==typeof a&&(a=H(a)),Math.abs(a)<16&&(a=60*a),this._offset=a,this._isUTC=!0,b!==a&&j(this,ca.duration(b-a,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?ca(a).zone():0,(this.zone()-a)%60===0},daysInMonth:function(){return r(this.year(),this.month())},dayOfYear:function(a){var b=ga((ca(this).startOf("day")-ca(this).startOf("year"))/864e5)+1;return null==a?b:this.add("d",a-b)},quarter:function(){return Math.ceil((this.month()+1)/3)},weekYear:function(a){var b=X(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==a?b:this.add("y",a-b)},isoWeekYear:function(a){var b=X(this,1,4).year;return null==a?b:this.add("y",a-b)},week:function(a){var b=this.lang().week(this);return null==a?b:this.add("d",7*(a-b))},isoWeek:function(a){var b=X(this,1,4).week;return null==a?b:this.add("d",7*(a-b))},weekday:function(a){var b=(this.day()+7-this.lang()._week.dow)%7;return null==a?b:this.add("d",a-b)},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},get:function(a){return a=n(a),this[a]()},set:function(a,b){return a=n(a),"function"==typeof this[a]&&this[a](b),this},lang:function(b){return b===a?this._lang:(this._lang=B(b),this)}}),da=0;da<Oa.length;da++)$(Oa[da].toLowerCase().replace(/s$/,""),Oa[da]);$("year","FullYear"),ca.fn.days=ca.fn.day,ca.fn.months=ca.fn.month,ca.fn.weeks=ca.fn.week,ca.fn.isoWeeks=ca.fn.isoWeek,ca.fn.toJSON=ca.fn.toISOString,g(ca.duration.fn=f.prototype,{_bubble:function(){var a,b,c,d,e=this._milliseconds,f=this._days,g=this._months,i=this._data;i.milliseconds=e%1e3,a=h(e/1e3),i.seconds=a%60,b=h(a/60),i.minutes=b%60,c=h(b/60),i.hours=c%24,f+=h(c/24),i.days=f%30,g+=h(f/30),i.months=g%12,d=h(g/12),i.years=d},weeks:function(){return h(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*q(this._months/12)},humanize:function(a){var b=+this,c=W(b,!a,this.lang());return a&&(c=this.lang().pastFuture(b,c)),this.lang().postformat(c)},add:function(a,b){var c=ca.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=ca.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=n(a),this[a.toLowerCase()+"s"]()},as:function(a){return a=n(a),this["as"+a.charAt(0).toUpperCase()+a.slice(1)+"s"]()},lang:ca.fn.lang,toIsoString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),d=Math.abs(this.hours()),e=Math.abs(this.minutes()),f=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"}});for(da in Pa)Pa.hasOwnProperty(da)&&(aa(da,Pa[da]),_(da.toLowerCase()));aa("Weeks",6048e5),ca.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},ca.lang("en",{ordinal:function(a){var b=a%10,c=1===q(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),pa?(module.exports=ca,ba(!0)):"function"==typeof define&&define.amd?define("moment",function(b,c,d){return d.config&&d.config()&&d.config().noGlobal!==!0&&ba(d.config().noGlobal===a),ca}):ba()}.call(this),function(a,b,c){"use strict";function d(a){var b,c=[];if(void 0===a)return void 0;for(Array.isArray(a)||(a=[a]),b=0;b<a.length;b+=1)"object"==typeof a[b]?c[b]=a[b].content:c[b]=a[b];return c}function e(a,b){var c;if("descending"===b)c=1;else{if("ascending"!==b)throw new TypeError("Query.sortFunction(): Argument 2 must be 'ascending' or 'descending'");c=-1}return function(b,e){var f,g;for(b=d(b[a])||[],e=d(e[a])||[],g=b.length>e.length?b.length:e.length,f=0;g>f;f+=1){if(void 0===b[f])return c;if(void 0===e[f])return-c;if(b[f]>e[f])return-c;if(b[f]<e[f])return c}return 0}}function f(a,b){var c;if(!Array.isArray(a))throw new TypeError("jioquery.sortOn(): Argument 1 is not of type 'array'");for(c=a.length-1;c>=0;c-=1)b.sort(e(a[c][0],a[c][1]));return b}function g(a,b){if(!Array.isArray(a))throw new TypeError("jioquery.limit(): Argument 1 is not of type 'array'");if(!Array.isArray(b))throw new TypeError("jioquery.limit(): Argument 2 is not of type 'array'");return b.splice(0,a[0]),a[1]&&b.splice(a[1]),b}function h(a,b){var c,d,e;if(!Array.isArray(a))throw new TypeError("jioquery.select(): Argument 1 is not of type Array");if(!Array.isArray(b))throw new TypeError("jioquery.select(): Argument 2 is not of type Array");for(c=0;c<b.length;c+=1){for(e={},d=0;d<a.length;d+=1)b[c].hasOwnProperty([a[d]])&&(e[a[d]]=b[c][a[d]]);for(d in e)if(e.hasOwnProperty(d)){b[c]=e;break}}return b}function i(){}function j(){}function k(a){return a.replace(t,"\\$&")}function l(a,b){a.super_=b,a.prototype=Object.create(b.prototype,{constructor:{configurable:!0,enumerable:!1,writable:!0,value:a}})}function m(a,b){if("string"!=typeof a)throw new TypeError("jioquery.searchTextToRegExp(): Argument 1 is not of type 'string'");return b===!1?new RegExp("^"+k(a)+"$"):new RegExp("^"+k(a).replace(u,".*").replace(v,".")+"$")}function n(a,b){i.call(this),this.operator=a.operator,this.query_list=a.query_list||[],this.query_list=this.query_list.map(function(a){return j.create(a,b)})}function o(a){var b=[];if("complex"===a.type)return b.push("("),(a.query_list||[]).forEach(function(c){b.push(o(c)),b.push(a.operator)}),b.length-=1,b.push(")"),b.join(" ");if("simple"===a.type)return(a.key?a.key+": ":"")+(a.operator||"")+' "'+a.value+'"';throw new TypeError("This object is not a query")}function p(a){var b;if(void 0!==a){if("object"!=typeof a)throw new TypeError("SimpleQuery().create(): key_schema is not of type 'object'");if(void 0===a.key_set)throw new TypeError("SimpleQuery().create(): key_schema has no 'key_set' property");for(b in a)if(a.hasOwnProperty(b))switch(b){case"key_set":case"cast_lookup":case"match_lookup":break;default:throw new TypeError("SimpleQuery().create(): key_schema has unknown property '"+b+"'")}}}function q(a,b){i.call(this),p(b),this._key_schema=b||{},this.operator=a.operator,this.key=a.key,this.value=a.value}function r(a){var b;if(void 0===a.read_from)throw new TypeError("Custom key is missing the read_from property");for(b in a)if(a.hasOwnProperty(b))switch(b){case"read_from":case"cast_to":case"equal_match":break;default:throw new TypeError("Custom key has unknown property '"+b+"'")}}var s={},t=/[\-\[\]{}()*+?.,\\\^$|#\s]/g,u=/%/g,v=/_/g,w=/^(?:AND|OR|NOT)$/i,x=/^(?:!?=|<=?|>=?)$/i;i.prototype.exec=function(b,c){if(!Array.isArray(b))throw new TypeError("Query().exec(): Argument 1 is not of type 'array'");if(void 0===c&&(c={}),"object"!=typeof c)throw new TypeError("Query().exec(): Optional argument 2 is not of type 'object'");var d,e=this;for(d=b.length-1;d>=0;d-=1)e.match(b[d])||b.splice(d,1);return c.sort_on&&f(c.sort_on,b),c.limit&&g(c.limit,b),h(c.select_list||[],b),(new a.Queue).push(function(){return b})},i.prototype.match=function(){return!0},i.prototype.parse=function(b){function c(b,d){function f(a){i.push(function(){return b.parsed=h.query_list[a],c(b,d)}).push(function(){h.query_list[a]=b.parsed})}var g,h=b.parsed,i=new a.Queue;if("complex"===h.type){for(g=0;g<h.query_list.length;g+=1)f(g);return i.push(function(){return b.parsed=h,e.onParseComplexQuery(b,d)})}return"simple"===h.type?e.onParseSimpleQuery(b,d):void 0}var d,e=this;return d={parsed:JSON.parse(JSON.stringify(e.serialized()))},(new a.Queue).push(function(){return e.onParseStart(d,b)}).push(function(){return c(d,b)}).push(function(){return e.onParseEnd(d,b)}).push(function(){return d.parsed})},i.prototype.toString=function(){return""},i.prototype.serialized=function(){return void 0},l(n,i),n.prototype.operator="AND",n.prototype.type="complex",n.prototype.match=function(a){var b=this.operator;return w.test(b)||(b="AND"),this[b.toUpperCase()](a)},n.prototype.toString=function(){var a=[],b=this.operator;return"NOT"===this.operator?(a.push("NOT ("),a.push(this.query_list[0].toString()),a.push(")"),a.join(" ")):(this.query_list.forEach(function(c){a.push("("),a.push(c.toString()),a.push(")"),a.push(b)}),a.length-=1,a.join(" "))},n.prototype.serialized=function(){var a={type:"complex",operator:this.operator,query_list:[]};return this.query_list.forEach(function(b){a.query_list.push("function"==typeof b.toJSON?b.toJSON():b)}),a},n.prototype.toJSON=n.prototype.serialized,n.prototype.AND=function(a){for(var b=!0,c=0;b&&c!==this.query_list.length;)b=this.query_list[c].match(a),c+=1;return b},n.prototype.OR=function(a){for(var b=!1,c=0;!b&&c!==this.query_list.length;)b=this.query_list[c].match(a),c+=1;return b},n.prototype.NOT=function(a){return!this.query_list[0].match(a)},j.create=function(a,b){if(""===a)return new i;if("string"==typeof a&&(a=c(a)),"string"==typeof(a||{}).type&&s[a.type])return new s[a.type](a,b);throw new TypeError("QueryFactory.create(): Argument 1 is not a search text or a parsable object")},l(q,i),q.prototype.type="simple",q.prototype.match=function(a){var b=null,c=null,d=null,e=null,f=this.operator,g=null,h=this.key;if(x.test(f)||(f=u.test(this.value)?"like":"="),e=this[f],this._key_schema.key_set&&void 0!==this._key_schema.key_set[h]&&(h=this._key_schema.key_set[h]),"object"==typeof h){if(r(h),b=a[h.read_from],c=h.equal_match,"string"==typeof c&&(c=this._key_schema.match_lookup[c]),void 0!==c&&(e="="===f||"like"===f?c:e),g=this.value,d=h.cast_to){"string"==typeof d&&(d=this._key_schema.cast_lookup[d]);try{g=d(g)}catch(i){g=void 0}try{b=d(b)}catch(i){b=void 0}}}else b=a[h],g=this.value;return void 0===b||void 0===g?!1:e(b,g)},q.prototype.toString=function(){return(this.key?this.key+":":"")+(this.operator?" "+this.operator:"")+' "'+this.value+'"'},q.prototype.serialized=function(){var a={type:"simple",key:this.key,value:this.value};return void 0!==this.operator&&(a.operator=this.operator),a},q.prototype.toJSON=q.prototype.serialized,q.prototype["="]=function(a,b){var c,d;for(Array.isArray(a)||(a=[a]),d=0;d<a.length;d+=1){if(c=a[d],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp)return 0===c.cmp(b);if(b.toString()===c.toString())return!0}return!1},q.prototype.like=function(a,b){var c,d;for(Array.isArray(a)||(a=[a]),d=0;d<a.length;d+=1){if(c=a[d],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),
-"function"==typeof c.cmp)return 0===c.cmp(b);if(m(b.toString()).test(c.toString()))return!0}return!1},q.prototype["!="]=function(a,b){var c,d;for(Array.isArray(a)||(a=[a]),d=0;d<a.length;d+=1){if(c=a[d],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp)return 0!==c.cmp(b);if(b.toString()===c.toString())return!1}return!0},q.prototype["<"]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)<0:b>c},q.prototype["<="]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)<=0:b>=c},q.prototype[">"]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)>0:c>b},q.prototype[">="]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)>=0:c>=b},s.simple=q,s.complex=n,i.parseStringToObject=c,i.objectToSearchText=o,b.Query=i,b.SimpleQuery=q,b.ComplexQuery=n,b.QueryFactory=j}(RSVP,window,parseStringToObject),function(a,b){"use strict";var c,d="year",e="month",f="day",g="hour",h="minute",i="second",j="millisecond",k={year:0,month:1,day:2,hour:3,minute:4,second:5,millisecond:6},l=function(a,b){return k[a]<k[b]?a:b};c=function(a){if(!(this instanceof c))return new c(a);if(a instanceof c)return this.mom=a.mom.clone(),void(this._precision=a._precision);if(void 0===a)return this.mom=b(),void this.setPrecision(j);if(this.mom=null,this._str=a,a.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+\-][0-2]\d:[0-5]\d|Z)/)||a.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d/)?(this.mom=b(a),this.setPrecision(j)):a.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+\-][0-2]\d:[0-5]\d|Z)/)||a.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/)?(this.mom=b(a),this.setPrecision(i)):a.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+\-][0-2]\d:[0-5]\d|Z)/)||a.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d/)?(this.mom=b(a),this.setPrecision(h)):a.match(/\d\d\d\d-\d\d-\d\d \d\d/)?(this.mom=b(a),this.setPrecision(g)):a.match(/\d\d\d\d-\d\d-\d\d/)?(this.mom=b(a),this.setPrecision(f)):a.match(/\d\d\d\d-\d\d/)?(this.mom=b(a),this.setPrecision(e)):a.match(/\d\d\d\d/)&&(this.mom=b(a),this.setPrecision(d)),!this.mom)throw new Error("Cannot parse: "+a)},c.prototype.setPrecision=function(a){this._precision=a},c.prototype.getPrecision=function(){return this._precision},c.prototype.cmp=function(a){var b=this.mom,c=a.mom,d=l(this._precision,a._precision);return b.isBefore(c,d)?-1:b.isSame(c,d)?0:1},c.prototype.toPrecisionString=function(a){var b;if(a=a||this._precision,b={millisecond:"YYYY-MM-DD HH:mm:ss.SSS",second:"YYYY-MM-DD HH:mm:ss",minute:"YYYY-MM-DD HH:mm",hour:"YYYY-MM-DD HH",day:"YYYY-MM-DD",month:"YYYY-MM",year:"YYYY"}[a],!b)throw new TypeError("Unsupported precision value '"+a+"'");return this.mom.format(b)},c.prototype.toString=function(){return this._str},a.jiodate={JIODate:c,YEAR:d,MONTH:e,DAY:f,HOUR:g,MIN:h,SEC:i,MSEC:j}}(window,moment),function(a,b,c,d,e,f,g,h,i){"use strict";function j(a,b){if(void 0!==a&&"string"!=typeof a)throw new TypeError("You must pass a string.");this.message=a||"Default Message",this.status_code=b||500}function k(a){var c=new XMLHttpRequest;return new b.Promise(function(b,d,e){var f;if(c.open(a.type||"GET",a.url,!0),c.responseType=a.dataType||"","object"==typeof a.headers&&null!==a.headers)for(f in a.headers)a.headers.hasOwnProperty(f)&&c.setRequestHeader(f,a.headers[f]);if(c.addEventListener("load",function(a){return a.target.status>=400?d(a):void b(a)}),c.addEventListener("error",d),c.addEventListener("progress",e),"object"==typeof a.xhrFields&&null!==a.xhrFields)for(f in a.xhrFields)a.xhrFields.hasOwnProperty(f)&&(c[f]=a.xhrFields[f]);"function"==typeof a.beforeSend&&a.beforeSend(c),c.send(a.data)},function(){c.abort()})}function l(a,c){var d=new g;return new b.Promise(function(b,e,f){d.addEventListener("load",b),d.addEventListener("error",e),d.addEventListener("progress",f),d.readAsText(a,c)},function(){d.abort()})}function m(a){var c=new g;return new b.Promise(function(b,d,e){c.addEventListener("load",b),c.addEventListener("error",d),c.addEventListener("progress",e),c.readAsArrayBuffer(a)},function(){c.abort()})}function n(a){var c=new g;return new b.Promise(function(b,d,e){c.addEventListener("load",b),c.addEventListener("error",d),c.addEventListener("progress",e),c.readAsDataURL(a)},function(){c.abort()})}function o(a){var b,d=f(a.split(",")[1]),e=a.split(",")[0].split(":")[1],g=new h(d.length),j=new i(g);for(e=e.slice(0,e.length-";base64".length),b=0;b<d.length;b+=1)j[b]=d.charCodeAt(b);return new c([g],{type:e})}function p(a,b,c){if("string"!=typeof a[0]||""===a[0])throw new u.util.jIOError("Document id must be a non empty string on '"+b.__type+"."+c+"'.",400)}function q(a,b,c){if("string"!=typeof a[1]||""===a[1])throw new u.util.jIOError("Attachment id must be a non empty string on '"+b.__type+"."+c+"'.",400)}function r(a,c,d,e){return a.prototype[c]=function(){var a,f=arguments,g=this;return(new b.Queue).push(function(){return void 0!==d?d.apply(g.__storage,[f,g,c]):void 0}).push(function(b){var d=g.__storage[c];if(a=b,void 0===d)throw new u.util.jIOError("Capacity '"+c+"' is not implemented on '"+g.__type+"'",501);return d.apply(g.__storage,f)}).push(function(b){return void 0!==e?e.call(g,f,b,a):b})},this}function s(a,b){return this instanceof s?(this.__type=a,void(this.__storage=b)):new s}function t(){return this instanceof t?void(this.__storage_types={}):new t}var u,v={};j.prototype=new Error,j.prototype.constructor=j,v.jIOError=j,v.ajax=k,v.readBlobAsText=l,v.readBlobAsArrayBuffer=m,v.readBlobAsDataURL=n,v.dataURItoBlob=o,r(s,"put",p,function(a){return a[0]}),r(s,"get",p),r(s,"bulk"),r(s,"remove",p,function(a){return a[0]}),s.prototype.post=function(){var a=this,c=arguments;return(new b.Queue).push(function(){var b=a.__storage.post;if(void 0===b)throw new u.util.jIOError("Capacity 'post' is not implemented on '"+a.__type+"'",501);return a.__storage.post.apply(a.__storage,c)})},r(s,"putAttachment",function(a,b,d){p(a,b,d),q(a,b,d);var e=a[3]||{};if("string"==typeof a[2])a[2]=new c([a[2]],{type:e._content_type||e._mimetype||"text/plain;charset=utf-8"});else if(!(a[2]instanceof c))throw new u.util.jIOError("Attachment content is not a blob",400)}),r(s,"removeAttachment",function(a,b,c){p(a,b,c),q(a,b,c)}),r(s,"getAttachment",function(a,b,c){var d="blob";return p(a,b,c),q(a,b,c),void 0!==a[2]&&(d=a[2].format||d,delete a[2].format),d},function(a,d,e){var f;if(!(d instanceof c))throw new u.util.jIOError("'getAttachment' ("+a[0]+" , "+a[1]+") on '"+this.__type+"' does not return a Blob.",501);if("blob"===e)f=d;else if("data_url"===e)f=(new b.Queue).push(function(){return u.util.readBlobAsDataURL(d)}).push(function(a){return a.target.result});else if("array_buffer"===e)f=(new b.Queue).push(function(){return u.util.readBlobAsArrayBuffer(d)}).push(function(a){return a.target.result});else if("text"===e)f=(new b.Queue).push(function(){return u.util.readBlobAsText(d)}).push(function(a){return a.target.result});else{if("json"!==e)throw new u.util.jIOError(this.__type+".getAttachment format: '"+e+"' is not supported",400);f=(new b.Queue).push(function(){return u.util.readBlobAsText(d)}).push(function(a){return JSON.parse(a.target.result)})}return f}),s.prototype.buildQuery=function(){var a=this.__storage.buildQuery,c=this,d=arguments;if(void 0===a)throw new u.util.jIOError("Capacity 'buildQuery' is not implemented on '"+this.__type+"'",501);return(new b.Queue).push(function(){return a.apply(c.__storage,d)})},s.prototype.hasCapacity=function(a){var b=this.__storage.hasCapacity,c=this.__storage[a];if(void 0!==c)return!0;if(void 0===b||!b.apply(this.__storage,arguments))throw new u.util.jIOError("Capacity '"+a+"' is not implemented on '"+this.__type+"'",501);return!0},s.prototype.allDocs=function(a){var c=this;return void 0===a&&(a={}),(new b.Queue).push(function(){return!c.hasCapacity("list")||void 0!==a.query&&!c.hasCapacity("query")||void 0!==a.sort_on&&!c.hasCapacity("sort")||void 0!==a.select_list&&!c.hasCapacity("select")||void 0!==a.include_docs&&!c.hasCapacity("include")||void 0!==a.limit&&!c.hasCapacity("limit")?void 0:c.buildQuery(a)}).push(function(a){return{data:{rows:a,total_rows:a.length}}})},r(s,"allAttachments",p),r(s,"repair"),s.prototype.repair=function(){var a=this,c=arguments;return(new b.Queue).push(function(){var b=a.__storage.repair;return void 0!==b?a.__storage.repair.apply(a.__storage,c):void 0})},t.prototype.createJIO=function(a,b){if("string"!=typeof a.type)throw new TypeError("Invalid storage description");if(!this.__storage_types[a.type])throw new TypeError("Unknown storage '"+a.type+"'");return new s(a.type,new this.__storage_types[a.type](a,b))},t.prototype.addStorage=function(a,b){if("string"!=typeof a)throw new TypeError("jIO.addStorage(): Argument 1 is not of type 'string'");if("function"!=typeof b)throw new TypeError("jIO.addStorage(): Argument 2 is not of type 'function'");if(void 0!==this.__storage_types[a])throw new TypeError("jIO.addStorage(): Storage type already exists");this.__storage_types[a]=b},t.prototype.util=v,t.prototype.QueryFactory=d,t.prototype.Query=e,u=new t,a.jIO=u}(window,RSVP,Blob,QueryFactory,Query,atob,FileReader,ArrayBuffer,Uint8Array),function(){function a(a){"use strict";var d={fill:0},f=function(a){for(a+=9;a%64>0;a+=1);return a},g=function(a,b){for(var c=b>>2;c<a.length;c++)a[c]=0},h=function(a,b,c){a[b>>2]|=128<<24-(b%4<<3),a[((b>>2)+2&-16)+14]=c>>29,a[((b>>2)+2&-16)+15]=c<<3},i=function(a,b,c,d,e){var f,g=this,h=e%4,i=d%4,j=d-i;if(j>0)switch(h){case 0:a[e+3|0]=g.charCodeAt(c);case 1:a[e+2|0]=g.charCodeAt(c+1);case 2:a[e+1|0]=g.charCodeAt(c+2);case 3:a[0|e]=g.charCodeAt(c+3)}for(f=h;j>f;f=f+4|0)b[e+f>>2]=g.charCodeAt(c+f)<<24|g.charCodeAt(c+f+1)<<16|g.charCodeAt(c+f+2)<<8|g.charCodeAt(c+f+3);switch(i){case 3:a[e+j+1|0]=g.charCodeAt(c+j+2);case 2:a[e+j+2|0]=g.charCodeAt(c+j+1);case 1:a[e+j+3|0]=g.charCodeAt(c+j)}},j=function(a,b,c,d,e){var f,g=this,h=e%4,i=d%4,j=d-i;if(j>0)switch(h){case 0:a[e+3|0]=g[c];case 1:a[e+2|0]=g[c+1];case 2:a[e+1|0]=g[c+2];case 3:a[0|e]=g[c+3]}for(f=4-h;j>f;f=f+=4)b[e+f>>2]=g[c+f]<<24|g[c+f+1]<<16|g[c+f+2]<<8|g[c+f+3];switch(i){case 3:a[e+j+1|0]=g[c+j+2];case 2:a[e+j+2|0]=g[c+j+1];case 1:a[e+j+3|0]=g[c+j]}},k=function(a,b,d,e,f){var g,h=this,i=f%4,j=e%4,k=e-j,l=new Uint8Array(c.readAsArrayBuffer(h.slice(d,d+e)));if(k>0)switch(i){case 0:a[f+3|0]=l[0];case 1:a[f+2|0]=l[1];case 2:a[f+1|0]=l[2];case 3:a[0|f]=l[3]}for(g=4-i;k>g;g=g+=4)b[f+g>>2]=l[g]<<24|l[g+1]<<16|l[g+2]<<8|l[g+3];switch(j){case 3:a[f+k+1|0]=l[k+2];case 2:a[f+k+2|0]=l[k+1];case 1:a[f+k+3|0]=l[k]}},l=function(a){switch(e.getDataType(a)){case"string":return i.bind(a);case"array":return j.bind(a);case"buffer":return j.bind(a);case"arraybuffer":return j.bind(new Uint8Array(a));case"view":return j.bind(new Uint8Array(a.buffer,a.byteOffset,a.byteLength));case"blob":return k.bind(a)}},m=function(a){var b,c,d="0123456789abcdef",e=[],f=new Uint8Array(a);for(b=0;b<f.length;b++)c=f[b],e[b]=d.charAt(c>>4&15)+d.charAt(c>>0&15);return e.join("")},n=function(a){var b;if(65536>=a)return 65536;if(16777216>a)for(b=1;a>b;b<<=1);else for(b=16777216;a>b;b+=16777216);return b},o=function(a){if(a%64>0)throw new Error("Chunk size must be a multiple of 128 bit");d.maxChunkLen=a,d.padMaxChunkLen=f(a),d.heap=new ArrayBuffer(n(d.padMaxChunkLen+320+20)),d.h32=new Int32Array(d.heap),d.h8=new Int8Array(d.heap),d.core=b({Int32Array:Int32Array,DataView:DataView},{},d.heap),d.buffer=null};o(a||65536);var p=function(a,b){var c=new Int32Array(a,b+320,5);c[0]=1732584193,c[1]=-271733879,c[2]=-1732584194,c[3]=271733878,c[4]=-1009589776},q=function(a,b){var c=f(a),e=new Int32Array(d.heap,0,c>>2);return g(e,a),h(e,a,b),c},r=function(a,b,c){l(a)(d.h8,d.h32,b,c,0)},s=function(a,b,c,e,f){var g=c;f&&(g=q(c,e)),r(a,b,c),d.core.hash(g,d.padMaxChunkLen)},t=function(a,b){var c=new Int32Array(a,b+320,5),d=new Int32Array(5),e=new DataView(d.buffer);return e.setInt32(0,c[0],!1),e.setInt32(4,c[1],!1),e.setInt32(8,c[2],!1),e.setInt32(12,c[3],!1),e.setInt32(16,c[4],!1),d},u=this.rawDigest=function(a){var b=a.byteLength||a.length||a.size||0;p(d.heap,d.padMaxChunkLen);var c=0,e=d.maxChunkLen;for(c=0;b>c+e;c+=e)s(a,c,e,b,!1);return s(a,c,b-c,b,!0),t(d.heap,d.padMaxChunkLen)};this.digest=this.digestFromString=this.digestFromBuffer=this.digestFromArrayBuffer=function(a){return m(u(a).buffer)}}function b(a,b,c){"use asm";function d(a,b){a|=0,b|=0;var c=0,d=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;for(f=e[b+320>>2]|0,h=e[b+324>>2]|0,j=e[b+328>>2]|0,l=e[b+332>>2]|0,n=e[b+336>>2]|0,c=0;(c|0)<(a|0);c=c+64|0){for(g=f,i=h,k=j,m=l,o=n,d=0;(d|0)<64;d=d+4|0)q=e[c+d>>2]|0,p=((f<<5|f>>>27)+(h&j|~h&l)|0)+((q+n|0)+1518500249|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[a+d>>2]=q;for(d=a+64|0;(d|0)<(a+80|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h&j|~h&l)|0)+((q+n|0)+1518500249|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+80|0;(d|0)<(a+160|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h^j^l)|0)+((q+n|0)+1859775393|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+160|0;(d|0)<(a+240|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h&j|h&l|j&l)|0)+((q+n|0)-1894007588|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+240|0;(d|0)<(a+320|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h^j^l)|0)+((q+n|0)-899497514|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;f=f+g|0,h=h+i|0,j=j+k|0,l=l+m|0,n=n+o|0}e[b+320>>2]=f,e[b+324>>2]=h,e[b+328>>2]=j,e[b+332>>2]=l,e[b+336>>2]=n}var e=new a.Int32Array(c);return{hash:d}}if("undefined"!=typeof module?module.exports=a:"undefined"!=typeof window&&(window.Rusha=a),"undefined"!=typeof FileReaderSync){var c=new FileReaderSync,d=new a(4194304);self.onmessage=function(a){var b,c=a.data.data;try{b=d.digest(c),self.postMessage({id:a.data.id,hash:b})}catch(e){self.postMessage({id:a.data.id,error:e.name})}}}var e={getDataType:function(a){if("string"==typeof a)return"string";if(a instanceof Array)return"array";if("undefined"!=typeof global&&global.Buffer&&global.Buffer.isBuffer(a))return"buffer";if(a instanceof ArrayBuffer)return"arraybuffer";if(a.buffer instanceof ArrayBuffer)return"view";if(a instanceof Blob)return"blob";throw new Error("Unsupported data type.")}}}(),function(a,b,c){"use strict";function d(a){return f.digestFromString(a)}function e(b){if(this._query_options=b.query||{},this._local_sub_storage=a.createJIO(b.local_sub_storage),this._remote_sub_storage=a.createJIO(b.remote_sub_storage),this._signature_hash="_replicate_"+d(JSON.stringify(b.local_sub_storage)+JSON.stringify(b.remote_sub_storage)+JSON.stringify(this._query_options)),this._signature_sub_storage=a.createJIO({type:"document",document_id:this._signature_hash,sub_storage:b.local_sub_storage}),this._use_remote_post=b.use_remote_post||!1,this._conflict_handling=b.conflict_handling||0,this._conflict_handling!==g&&this._conflict_handling!==h&&this._conflict_handling!==i&&this._conflict_handling!==j)throw new a.util.jIOError("Unsupported conflict handling: "+this._conflict_handling,400);this._check_local_modification=b.check_local_modification,void 0===this._check_local_modification&&(this._check_local_modification=!0),this._check_local_creation=b.check_local_creation,void 0===this._check_local_creation&&(this._check_local_creation=!0),this._check_local_deletion=b.check_local_deletion,void 0===this._check_local_deletion&&(this._check_local_deletion=!0),this._check_remote_modification=b.check_remote_modification,void 0===this._check_remote_modification&&(this._check_remote_modification=!0),this._check_remote_creation=b.check_remote_creation,void 0===this._check_remote_creation&&(this._check_remote_creation=!0),this._check_remote_deletion=b.check_remote_deletion,void 0===this._check_remote_deletion&&(this._check_remote_deletion=!0)}var f=new c,g=0,h=1,i=2,j=3;e.prototype.remove=function(b){if(b===this._signature_hash)throw new a.util.jIOError(this._signature_hash+" is frozen",403);return this._local_sub_storage.remove.apply(this._local_sub_storage,arguments)},e.prototype.post=function(){return this._local_sub_storage.post.apply(this._local_sub_storage,arguments)},e.prototype.put=function(b){if(b===this._signature_hash)throw new a.util.jIOError(this._signature_hash+" is frozen",403);return this._local_sub_storage.put.apply(this._local_sub_storage,arguments)},e.prototype.get=function(){return this._local_sub_storage.get.apply(this._local_sub_storage,arguments)},e.prototype.hasCapacity=function(){return this._local_sub_storage.hasCapacity.apply(this._local_sub_storage,arguments)},e.prototype.buildQuery=function(){return this._local_sub_storage.buildQuery.apply(this._local_sub_storage,arguments)},e.prototype.repair=function(){function c(a,b,c,d,e,f){var g,h,i=!0;return void 0===f&&(f={}),g=f.use_post?b.post(c).push(function(b){return i=!1,h=b,a.put(h,c)}).push(function(){return a.remove(e)}).push(function(){return n._signature_sub_storage.remove(e)}).push(function(){return i=!0,n._signature_sub_storage.put(h,{hash:d})}).push(function(){p[h]=null}):b.put(e,c).push(function(){return n._signature_sub_storage.put(e,{hash:d})}),g.push(function(){i&&(p[e]=null)})}function e(b,e,f,g,h,i){var j;b.push(function(){return f.get(g)}).push(function(a){j=a},function(b){if(!(b instanceof a.util.jIOError&&404===b.status_code))throw b}).push(function(){return i(g)}).push(function(b){var i,k=d(JSON.stringify(b));if(void 0===j)return c(e,f,b,k,g,h);if(i=d(JSON.stringify(j)),k===i)return n._signature_sub_storage.put(g,{hash:k}).push(function(){p[g]=null});if(h.conflict_ignore!==!0){if(h.conflict_force===!0)return c(e,f,b,k,g,h);throw new a.util.jIOError("Conflict on '"+g+"'",409)}})}function f(a,c,d,f,g){a.push(function(){return c.bulk(f)}).push(function(a){function h(b){return function(c){if(c!==f[b].parameter_list[0])throw new Error("Does not access expected ID "+c);return a[b]}}var i,j=new b.Queue;for(i=0;i<a.length;i+=1)e(j,c,d,f[i].parameter_list[0],g,h(i));return j})}function g(b,e,f,g){var h;b.push(function(){return n._signature_sub_storage.get(f)}).push(function(b){return h=b.hash,e.get(f).push(function(a){var b=d(JSON.stringify(a));return b===h?e.remove(f).push(function(){return n._signature_sub_storage.remove(f)}).push(function(){p[f]=null}):c(e,g,a,b,f)},function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return n._signature_sub_storage.remove(f).push(function(){p[f]=null});throw b})})}function k(e,f,g,h,i,j,k){e.push(function(){return b.all([k(h),n._signature_sub_storage.get(h)])}).push(function(b){var e=b[0],k=d(JSON.stringify(e)),l=b[1].hash;return k!==l?g.get(h).push(function(b){var m=d(JSON.stringify(b));if(m!==l){if(k===m)return n._signature_sub_storage.put(h,{hash:k}).push(function(){p[h]=null});if(j===!0)return;if(i!==!0)throw new a.util.jIOError("Conflict on '"+h+"'",409)}return c(f,g,e,k,h)},function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return c(f,g,e,k,h);throw b}):void 0})}function l(a,c,d,e,f,g){a.push(function(){return c.bulk(e)}).push(function(a){function h(b){return function(c){if(c!==e[b].parameter_list[0])throw new Error("Does not access expected ID "+c);return a[b]}}var i,j=new b.Queue;for(i=0;i<a.length;i+=1)k(j,c,d,e[i].parameter_list[0],f,g,h(i));return j})}function m(a,c,d){var h=new b.Queue;return d.hasOwnProperty("use_post")||(d.use_post=!1),h.push(function(){return b.all([a.allDocs(n._query_options),n._signature_sub_storage.allDocs()])}).push(function(b){var i,j,m={},n=[],o=[],q={};for(i=0;i<b[0].data.total_rows;i+=1)p.hasOwnProperty(b[0].data.rows[i].id)||(m[b[0].data.rows[i].id]=i);for(i=0;i<b[1].data.total_rows;i+=1)p.hasOwnProperty(b[1].data.rows[i].id)||(q[b[1].data.rows[i].id]=i);if(d.check_creation===!0){for(j in m)m.hasOwnProperty(j)&&(q.hasOwnProperty(j)||(d.use_bulk_get===!0?n.push({method:"get",parameter_list:[j]}):e(h,a,c,j,d,a.get.bind(a))));d.use_bulk_get===!0&&0!==n.length&&f(h,a,c,n,d)}for(j in q)q.hasOwnProperty(j)&&(m.hasOwnProperty(j)?d.check_modification===!0&&(d.use_bulk_get===!0?o.push({method:"get",parameter_list:[j]}):k(h,a,c,j,d.conflict_force,d.conflict_ignore,a.get.bind(a))):d.check_deletion===!0&&g(h,c,j,a));d.use_bulk_get===!0&&0!==o.length&&l(h,a,c,o,d.conflict_force,d.conflict_ignore)})}var n=this,o=arguments,p={};return p[n._signature_hash]=null,(new b.Queue).push(function(){return n._signature_sub_storage.__storage._sub_storage.get(n._signature_hash)}).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return n._signature_sub_storage.__storage._sub_storage.put(n._signature_hash,{});throw b}).push(function(){return b.all([n._local_sub_storage.repair.apply(n._local_sub_storage,o),n._remote_sub_storage.repair.apply(n._remote_sub_storage,o)])}).push(function(){return n._check_local_modification||n._check_local_creation||n._check_local_deletion?m(n._local_sub_storage,n._remote_sub_storage,{use_post:n._use_remote_post,conflict_force:n._conflict_handling===h,conflict_ignore:n._conflict_handling===j||n._conflict_handling===i,check_modification:n._check_local_modification,check_creation:n._check_local_creation,check_deletion:n._check_local_deletion}):void 0}).push(function(){var b=!1;try{b=n._remote_sub_storage.hasCapacity("bulk")}catch(c){if(!(c instanceof a.util.jIOError&&501===c.status_code))throw c}return n._check_remote_modification||n._check_remote_creation||n._check_remote_deletion?m(n._remote_sub_storage,n._local_sub_storage,{use_bulk_get:b,conflict_force:n._conflict_handling===i,conflict_ignore:n._conflict_handling===j,check_modification:n._check_remote_modification,check_creation:n._check_remote_creation,check_deletion:n._check_remote_deletion}):void 0})},a.addStorage("replicate",e)}(jIO,RSVP,Rusha),function(a){"use strict";function b(a){this._sub_storage=jIO.createJIO(a.sub_storage)}var c=new a;b.prototype.post=function(a){return this._sub_storage.put(c.digestFromString(JSON.stringify(a)),a)},b.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},b.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},b.prototype.hasCapacity=function(){return this._sub_storage.hasCapacity.apply(this._sub_storage,arguments)},b.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},b.prototype.getAttachment=function(){return this._sub_storage.getAttachment.apply(this._sub_storage,arguments)},b.prototype.putAttachment=function(){return this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},b.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},b.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},b.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},jIO.addStorage("sha",b)}(Rusha),function(a){"use strict";function b(b){this._sub_storage=a.createJIO(b.sub_storage)}b.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},b.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},b.prototype.post=function(a){function b(){return("0000"+Math.floor(65536*Math.random()).toString(16)).slice(-4)}var c=b()+b()+"-"+b()+"-"+b()+"-"+b()+"-"+b()+b()+b();return this.put(c,a)},b.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},b.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},b.prototype.getAttachment=function(){return this._sub_storage.getAttachment.apply(this._sub_storage,arguments)},b.prototype.putAttachment=function(){return this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},b.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},b.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},b.prototype.hasCapacity=function(a){return this._sub_storage.hasCapacity(a)},b.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},a.addStorage("uuid",b)}(jIO),function(a){"use strict";function b(){this._database={}}b.prototype.put=function(a,b){return this._database.hasOwnProperty(a)||(this._database[a]={attachments:{}}),this._database[a].doc=b,a},b.prototype.get=function(b){try{return this._database[b].doc}catch(c){if(c instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+b,404);throw c}},b.prototype.allAttachments=function(b){var c,d={};try{for(c in this._database[b].attachments)this._database[b].attachments.hasOwnProperty(c)&&(d[c]={})}catch(e){if(e instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+b,404);throw e}return d},b.prototype.remove=function(a){return delete this._database[a],a},b.prototype.getAttachment=function(b,c){try{var d=this._database[b].attachments[c];if(void 0===d)throw new a.util.jIOError("Cannot find attachment: "+b+" , "+c,404);return d}catch(e){if(e instanceof TypeError)throw new a.util.jIOError("Cannot find attachment: "+b+" , "+c,404);throw e}},b.prototype.putAttachment=function(b,c,d){var e;try{e=this._database[b].attachments}catch(f){if(f instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+b,404);throw f}e[c]=d},b.prototype.removeAttachment=function(b,c){try{delete this._database[b].attachments[c]}catch(d){if(d instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+b,404);throw d}},b.prototype.hasCapacity=function(a){return"list"===a||"include"===a},b.prototype.buildQuery=function(a){var b,c=[];for(b in this._database)this._database.hasOwnProperty(b)&&(a.include_docs===!0?c.push({id:b,value:{},doc:this._database[b]}):c.push({id:b,value:{}}));return c},a.addStorage("memory",b)}(jIO),function(a,b,c,d){"use strict";function e(a){this._sub_storage=jIO.createJIO(a.sub_storage)}function f(a,b){return a.indexOf(b)===a.length-b.length}var g="application/x-jio-utf16_lz_string";e.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},e.prototype.post=function(){return this._sub_storage.post.apply(this._sub_storage,arguments)},e.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},e.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},e.prototype.hasCapacity=function(){return this._sub_storage.hasCapacity.apply(this._sub_storage,arguments)},e.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},e.prototype.getAttachment=function(b,e){var f=this;return f._sub_storage.getAttachment(b,e).push(function(b){return b.type!==g?b:(new a.Queue).push(function(){return jIO.util.readBlobAsText(b,"utf16")}).push(function(a){var e=c.decompressFromUTF16(a.target.result);if(""===e)return b;try{return jIO.util.dataURItoBlob(e)}catch(f){if(f instanceof d)return b;throw f}})})},e.prototype.putAttachment=function(d,e,h){var i=this;return 0===h.type.indexOf("text/")||f(h.type,"xml")||f(h.type,"json")?(new a.Queue).push(function(){return jIO.util.readBlobAsDataURL(h)}).push(function(a){var f=c.compressToUTF16(a.target.result);return h=new b([f],{type:g}),i._sub_storage.putAttachment(d,e,h)}):this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},e.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},e.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},jIO.addStorage("zip",e)}(RSVP,Blob,LZString,DOMException),function(a,b,c,d){"use strict";function e(b){if(0!==b.indexOf("/"))throw new a.util.jIOError("id "+b+" is forbidden (no begin /)",400);if(b.lastIndexOf("/")!==b.length-1)throw new a.util.jIOError("id "+b+" is forbidden (no end /)",400);return b}function f(b){if(-1!==b.indexOf("/"))throw new a.util.jIOError("attachment "+b+" is forbidden",400)}function g(a){if("string"!=typeof a.access_token||!a.access_token)throw new TypeError("Access Token' must be a string which contains more than one character.");if("string"!=typeof a.root||!a.root||"dropbox"!==a.root&&"sandbox"!==a.root)throw new TypeError("root must be 'dropbox' or 'sandbox'");this._access_token=a.access_token,this._root=a.root}var h="https://content.dropboxapi.com/1/files_put/{+root}{+id}{+name}{?access_token}",i=d.parse(h),j="https://api.dropboxapi.com/1/fileops/create_folder{?access_token,root,path}",k=d.parse(j),l="https://api.dropboxapi.com/1/fileops/delete/{?access_token,root,path}",m=d.parse(l),n="https://content.dropboxapi.com/1/files{/root,id}{+name}{?access_token}",o=d.parse(n),p="https://api.dropboxapi.com/1/metadata{/root}{+id}{?access_token}",q=d.parse(p);g.prototype.put=function(c,d){var f=this;if(c=e(c),Object.getOwnPropertyNames(d).length>0)throw new a.util.jIOError("Can not store properties: "+Object.getOwnPropertyNames(d),400);return(new b.Queue).push(function(){return a.util.ajax({type:"POST",url:k.expand({access_token:f._access_token,root:f._root,path:c})})}).push(void 0,function(a){if(void 0===a.target||405!==a.target.status)throw a})},g.prototype.remove=function(b){return b=e(b),a.util.ajax({type:"POST",url:m.expand({access_token:this._access_token,root:this._root,path:b})})},g.prototype.get=function(c){var d=this;return"/"===c?{}:(c=e(c),(new b.Queue).push(function(){return a.util.ajax({type:"GET",url:q.expand({access_token:d._access_token,root:d._root,id:c})})}).push(function(b){var d=JSON.parse(b.target.response||b.target.responseText);if(d.is_dir)return{};throw new a.util.jIOError("Not a directory: "+c,404)},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document: "+c,404);throw b}))},g.prototype.allAttachments=function(c){var d=this;return c=e(c),(new b.Queue).push(function(){return a.util.ajax({type:"GET",url:q.expand({access_token:d._access_token,root:d._root,id:c})})}).push(function(b){var d,e=JSON.parse(b.target.response||b.target.responseText),f={};if(!e.is_dir)throw new a.util.jIOError("Not a directory: "+c,404);for(d=0;d<e.contents.length;d+=1)e.contents[d].is_dir||(f[e.contents[d].path.split("/").pop()]={});return f},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document: "+c,404);throw b})},g.prototype.putAttachment=function(b,c,d){return b=e(b),f(c),a.util.ajax({type:"PUT",url:i.expand({root:this._root,id:b,name:c,access_token:this._access_token}),dataType:d.type,data:d})},g.prototype.getAttachment=function(d,g){var h=this;return d=e(d),f(g),(new b.Queue).push(function(){return a.util.ajax({type:"GET",dataType:"blob",url:o.expand({root:h._root,id:d,name:g,access_token:h._access_token})})}).push(function(a){return new c([a.target.response||a.target.responseText],{type:a.target.getResponseHeader("Content-Type")||"application/octet-stream"})},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+d+", "+g,404);throw b})},g.prototype.removeAttachment=function(c,d){var g=this;return c=e(c),f(d),(new b.Queue).push(function(){return a.util.ajax({type:"POST",url:m.expand({access_token:g._access_token,root:g._root,path:c+d})})}).push(void 0,function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+c+", "+d,404);
-throw b})},a.addStorage("dropbox",g)}(jIO,RSVP,Blob,UriTemplate),function(a,b,c,d){"use strict";function e(c,d){return void 0===d&&(d={}),void 0!==c._authorization&&(void 0===d.headers&&(d.headers={}),d.headers.Authorization=c._authorization),void 0!==c._with_credentials&&(void 0===d.xhrFields&&(d.xhrFields={}),d.xhrFields.withCredentials=c._with_credentials),(new b.Queue).push(function(){return a.util.ajax(d)})}function f(b){if(0!==b.indexOf("/"))throw new a.util.jIOError("id "+b+" is forbidden (no begin /)",400);if(b.lastIndexOf("/")!==b.length-1)throw new a.util.jIOError("id "+b+" is forbidden (no end /)",400);return b}function g(b){if(-1!==b.indexOf("/"))throw new a.util.jIOError("attachment "+b+" is forbidden",400)}function h(a){if("string"!=typeof a.url)throw new TypeError("DavStorage 'url' is not of type string");this._url=a.url,"string"==typeof a.basic_login&&(this._authorization="Basic "+a.basic_login),this._with_credentials=a.with_credentials}h.prototype.put=function(c,d){var g=this;if(c=f(c),Object.getOwnPropertyNames(d).length>0)throw new a.util.jIOError("Can not store properties: "+Object.getOwnPropertyNames(d),400);return(new b.Queue).push(function(){return e(g,{type:"MKCOL",url:g._url+c})}).push(void 0,function(a){if(void 0===a.target||405!==a.target.status)throw a})},h.prototype.remove=function(a){return a=f(a),e(this,{type:"DELETE",url:this._url+a})},h.prototype.get=function(c){var d=this;return c=f(c),(new b.Queue).push(function(){return e(d,{type:"PROPFIND",url:d._url+c,dataType:"text",headers:{Depth:"1"}})}).push(function(){return{}},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document",404);throw b})},h.prototype.allAttachments=function(d){var g=this;return d=f(d),(new b.Queue).push(function(){return e(g,{type:"PROPFIND",url:g._url+d,dataType:"text",headers:{Depth:"1"}})}).push(function(a){var b,d,e={},f=(new c).parseFromString(a.target.responseText,"text/xml").querySelectorAll("D\\:response, response");for(b=1;b<f.length;b+=1)d=f[b].querySelector("D\\:href, href").textContent.split("/").slice(-1)[0],void 0!==d&&""!==d&&(e[d]={});return e},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document",404);throw b})},h.prototype.putAttachment=function(c,d,h){var i=this;return c=f(c),g(d),(new b.Queue).push(function(){return e(i,{type:"PUT",url:i._url+c+d,data:h})}).push(void 0,function(b){if(403===b.target.status||424===b.target.status)throw new a.util.jIOError("Cannot access subdocument",404);throw b})},h.prototype.getAttachment=function(c,h){var i=this;return c=f(c),g(h),(new b.Queue).push(function(){return e(i,{type:"GET",url:i._url+c+h,dataType:"blob"})}).push(function(a){return new d([a.target.response||a.target.responseText],{type:a.target.getResponseHeader("Content-Type")||"application/octet-stream"})},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+c+" , "+h,404);throw b})},h.prototype.removeAttachment=function(c,d){var h=this;return c=f(c),g(d),(new b.Queue).push(function(){return e(h,{type:"DELETE",url:h._url+c+d})}).push(void 0,function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+c+" , "+d,404);throw b})},a.addStorage("dav",h)}(jIO,RSVP,DOMParser,Blob),function(a,b,c,d,e){"use strict";function f(b,c){if(404===b.target.status)throw new a.util.jIOError("Cannot find document: "+c,404);throw b}function g(b,d){var g,h;return(new c.Queue).push(function(){return a.util.ajax({type:"GET",url:s.expand({pageToken:b.nextPageToken||"",access_token:d})})}).push(function(a){for(h=e.parse(a.target.response||a.target.responseText),g=0;g<h.items.length;g+=1)h.items[g].value={},b.push(h.items[g]);return b.nextPageToken=h.nextPageToken,b},f)}function h(b){if("enclosure"!==b)throw new a.util.jIOError("Only support 'enclosure' attachment",400)}function i(a){if(void 0===a||void 0===a.access_token||"string"!=typeof a.access_token)throw new TypeError("Access Token must be a string which contains more than one character.");if(void 0!==a.trashing&&a.trashing!==!0&&a.trashing!==!1)throw new TypeError("trashing parameter must be a boolean (true or false)");this._trashing=a.trashing||!0,this._access_token=a.access_token}function j(a,b){return(new c.Queue).push(function(){return g(a,b)}).push(function(){return a.nextPageToken?j(a,b):a})}function k(b,d,g){var h="-------314159265358979323846";return(new c.Queue).push(function(){return a.util.ajax({type:b?"PUT":"POST",url:o.expand({access_token:g,id:b||[],upload:b?[]:"upload",uploadType:"multipart"}),headers:{"Content-Type":'multipart/related; boundary="'+h+'"'},data:"--"+h+"\nContent-Type: application/json; charset=UTF-8\n\n"+e.stringify(d)+"\n\n--"+h+"--"})}).push(function(a){var b=e.parse(a.target.responseText);return b.id},function(a){f(a,b)})}function l(b,d,g){return(new c.Queue).push(function(){return a.util.ajax({type:"PUT",url:o.expand({access_token:g,upload:"upload",id:b,uploadType:"media"}),data:d})}).push(function(b){if(b=e.parse(b.target.responseText),"application/vnd.google-apps.folder"===b.mimeType)throw new a.util.jIOError("cannot put attachments to folder",400);return b},function(a){f(a,b)})}function m(d,g,h){return(new c.Queue).push(function(){return a.util.ajax({type:"GET",dataType:g?"blob":"json",url:u.expand({id:d,alt:g?"media":[],access_token:h}),headers:{Authorization:"Bearer "+h}})}).push(function(a){return a.target.response||(g?new b([a.target.responseText],{type:a.target.responseHeaders["Content-Type"]}):e.parse(a.target.responseText))},function(a){f(a,d)})}var n="https://www.googleapis.com{/upload}/drive/v2/files{/id}{?uploadType,access_token}",o=d.parse(n),p="https://www.googleapis.com/drive/v2/files{/id,trash}{?access_token}",q=d.parse(p),r="https://www.googleapis.com/drive/v2/files?prettyPrint=false{&pageToken}&q=trashed=false&fields=nextPageToken,items(id){&access_token}",s=d.parse(r),t="https://www.googleapis.com/drive/v2/files{/id}{?alt}",u=d.parse(t);i.prototype.hasCapacity=function(a){return"list"===a},i.prototype.buildQuery=function(){return j([],this._access_token)},i.prototype.put=function(a,b){return k(a,b,this._access_token)},i.prototype.post=function(a){return k(void 0,a,this._access_token)},i.prototype.putAttachment=function(a,b,c){return h(b),l(a,c,this._access_token)},i.prototype.remove=function(b){var d=this;return(new c.Queue).push(function(){return a.util.ajax({type:d._trashing?"POST":"DELETE",url:q.expand({id:b,access_token:d._access_token,trash:d._trashing?"trash":[]})})}).push(void 0,function(a){f(a,b)})},i.prototype.get=function(a){return m(a,!1,this._access_token)},i.prototype.getAttachment=function(a,b){return h(b),m(a,!0,this._access_token)},i.prototype.allAttachments=function(a){var b=this._access_token;return(new c.Queue).push(function(){return m(a,!1,b)}).push(function(a){return"application/vnd.google-apps.folder"===a.mimeType?{}:{enclosure:{}}})},a.addStorage("gdrive",i)}(jIO,Blob,RSVP,UriTemplate,JSON),function(a,b){"use strict";function c(b){if(!Array.isArray(b.storage_list))throw new a.util.jIOError("storage_list is not an Array",400);var c;for(this._storage_list=[],c=0;c<b.storage_list.length;c+=1)this._storage_list.push(a.createJIO(b.storage_list[c]))}c.prototype._getWithStorageIndex=function(){function b(b){g.push(void 0,function(c){if(c instanceof a.util.jIOError&&404===c.status_code)return e._storage_list[b].get.apply(e._storage_list[b],f).push(function(a){return d=b,a});throw c})}var c,d=0,e=this,f=arguments,g=this._storage_list[0].get.apply(this._storage_list[0],f);for(c=1;c<this._storage_list.length;c+=1)b(c);return g.push(function(a){return[d,a]})},c.prototype.get=function(){return this._getWithStorageIndex.apply(this,arguments).push(function(a){return a[1]})},c.prototype.allAttachments=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.allAttachments.apply(d,a)})},c.prototype.post=function(){return this._storage_list[0].post.apply(this._storage_list[0],arguments)},c.prototype.put=function(){var b=arguments,c=this;return this._getWithStorageIndex(b[0]).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return[0];throw b}).push(function(a){var d=c._storage_list[a[0]];return d.put.apply(d,b)})},c.prototype.remove=function(){var a=arguments,b=this;return this._getWithStorageIndex(a[0]).push(function(c){var d=b._storage_list[c[0]];return d.remove.apply(d,a)})},c.prototype.buildQuery=function(){var a,c,d=[],e={},f=this._storage_list.length;for(a=0;f>a;a+=1)c=this._storage_list[a],d.push(c.buildQuery.apply(c,arguments));return(new b.Queue).push(function(){return b.all(d)}).push(function(b){var c,d,g,h=[];for(f=b.length,a=0;f>a;a+=1)for(c=b[a],d=c.length,g=0;d>g;g+=1)e.hasOwnProperty(c[g].id)||(e[c[g].id]=null,h.push(c[g]));return h})},c.prototype.hasCapacity=function(a){var b,c,d,e;if("list"===a||"query"===a||"select"===a){for(d=!0,c=this._storage_list.length,b=0;c>b;b+=1)e=this._storage_list[b],d=d&&e.hasCapacity(a);return d}return!1},c.prototype.repair=function(){var a,c=[];for(a=0;a<this._storage_list.length;a+=1)c.push(this._storage_list[a].repair.apply(this._storage_list[a],arguments));return b.all(c)},c.prototype.getAttachment=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.getAttachment.apply(d,a)})},c.prototype.putAttachment=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.putAttachment.apply(d,a)})},c.prototype.removeAttachment=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.removeAttachment.apply(d,a)})},a.addStorage("union",c)}(jIO,RSVP),function(a,b,c,d,e,f,g,h){"use strict";function i(b){return(new d.Queue).push(function(){return a.util.ajax({type:"GET",url:b._url,xhrFields:{withCredentials:!0}})}).push(function(a){return JSON.parse(a.target.responseText)})}function j(c,e,f){return void 0===f&&(f={}),i(c).push(function(c){return(new d.Queue).push(function(){return a.util.ajax({type:"GET",url:b.parse(c._links.traverse.href).expand({relative_url:e,view:f._view}),xhrFields:{withCredentials:!0}})}).push(void 0,function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document: "+e,404);throw b})})}function k(a){return(new d.Queue).push(function(){var b,c,d,e,f=a._embedded._view,g={portal_type:a.portal_type},h={};h.form_id={key:[f.form_id.key],"default":f.form_id["default"]};for(c in f)f.hasOwnProperty(c)&&(b=f[c],d=0,0===c.indexOf("my_")&&b.editable&&(d=3),0===c.indexOf("your_")&&(d=5),0!==d&&q.hasOwnProperty(b.type)&&(h[c.substring(d)]={"default":b["default"],key:b.key},g[c.substring(d)]=b["default"]));return e={data:g,form_data:h},f.hasOwnProperty("_actions")&&f._actions.hasOwnProperty("put")&&(e.action_href=f._actions.put.href),e})}function l(b,c){return b.getAttachment(c,"view").push(function(b){return a.util.readBlobAsText(b)}).push(function(a){return JSON.parse(a.target.result)}).push(function(a){return k(a)})}function m(a){if("string"!=typeof a.url||!a.url)throw new TypeError("ERP5 'url' must be a string which contains more than one character.");this._url=a.url,this._default_view_reference=a.default_view_reference}function n(a){var b,c=a.data;for(b in c)c.hasOwnProperty(b)&&(c[b]||delete c[b]);return c}function o(a){return a instanceof g&&"local_roles"===a.key?a.value:void 0}function p(a){var b,c,d=!0,e=[];if(a instanceof h&&"OR"===a.operator){for(b=0;b<a.query_list.length;b+=1)c=a.query_list[b],c instanceof g&&"local_roles"===c.key?e.push(c.value):d=!1;if(d)return e}}var q={StringField:null,EmailField:null,IntegerField:null,FloatField:null,TextAreaField:null};m.prototype.get=function(a){return l(this,a).push(function(a){return n(a)})},m.prototype.bulk=function(b){var e,f=this,g=[];for(e=0;e<b.length;e+=1){if("get"!==b[e].method)throw new Error("ERP5Storage: not supported "+b[e].method+" in bulk");g.push({relative_url:b[e].parameter_list[0],view:f._default_view_reference})}return i(f).push(function(b){var d=new c;return d.append("bulk_list",JSON.stringify(g)),a.util.ajax({type:"POST",url:b._actions.bulk.href,data:d,xhrFields:{withCredentials:!0}})}).push(function(a){function b(a){return a.portal_type=a._links.type.name,k(a).push(function(a){return n(a)})}var c=[],f=JSON.parse(a.target.responseText);for(e=0;e<f.result_list.length;e+=1)c.push(b(f.result_list[e]));return d.all(c)})},m.prototype.post=function(b){var d,f=this;return i(this).push(function(d){var e=new c;return e.append("portal_type",b.portal_type),e.append("parent_relative_url",b.parent_relative_url),a.util.ajax({type:"POST",url:d._actions.add.href,data:e,xhrFields:{withCredentials:!0}})}).push(function(a){var c=a.target.getResponseHeader("X-Location"),g=new e(c);return d=g.segment(2),f.put(d,b)}).push(function(){return d})},m.prototype.put=function(b,c){var d=this;return l(d,b).push(function(e){var g,h=e.form_data,i={};i[h.form_id.key]=h.form_id["default"];for(g in c)if(c.hasOwnProperty(g)){if("form_id"===g)throw new a.util.jIOError("ERP5: forbidden property: "+g,400);if("portal_type"!==g&&"parent_relative_url"!==g){if(!h.hasOwnProperty(g))throw new a.util.jIOError("ERP5: can not store property: "+g,400);i[h[g].key]=c[g]}}if(!e.hasOwnProperty("action_href"))throw new a.util.jIOError("ERP5: can not modify document: "+b,403);return d.putAttachment(b,e.action_href,new f([JSON.stringify(i)],{type:"application/json"}))})},m.prototype.allAttachments=function(a){var b=this;return j(this,a).push(function(){return void 0===b._default_view_reference?{links:{}}:{view:{},links:{}}})},m.prototype.getAttachment=function(b,c,e){if(void 0===e&&(e={}),"view"===c){if(void 0===this._default_view_reference)throw new a.util.jIOError("Cannot find attachment view for: "+b,404);return j(this,b,{_view:this._default_view_reference}).push(function(a){var b=JSON.parse(a.target.responseText);return b.portal_type=b._links.type.name,new f([JSON.stringify(b)],{type:"application/hal+json"})})}if("links"===c)return j(this,b).push(function(a){return new f([JSON.stringify(JSON.parse(a.target.responseText))],{type:"application/hal+json"})});if(0===c.indexOf(this._url))return(new d.Queue).push(function(){var b,d,f,g={type:"GET",dataType:"blob",url:c,xhrFields:{withCredentials:!0}};if(void 0!==e.start||void 0!==e.end){if(b=e.start||0,d=e.end,void 0!==d&&0>d)throw new a.util.jIOError("end must be positive",400);if(0>b)f="bytes="+b;else if(void 0===d)f="bytes="+b+"-";else{if(b>d)throw new a.util.jIOError("start is greater than end",400);f="bytes="+b+"-"+d}g.headers={Range:f}}return a.util.ajax(g)}).push(function(a){return void 0===a.target.response?new f([a.target.responseText],{type:a.target.getResponseHeader("Content-Type")}):a.target.response});throw new a.util.jIOError("ERP5: not support get attachment: "+c,400)},m.prototype.putAttachment=function(b,e,f){if(0!==e.indexOf(this._url))throw new a.util.jIOError("Can not store outside ERP5: "+e,400);return(new d.Queue).push(function(){return a.util.readBlobAsText(f)}).push(function(b){var d,f,g,h,i=JSON.parse(b.target.result),j=new c;for(g in i)if(i.hasOwnProperty(g))for(d=Array.isArray(i[g])?i[g]:[i[g]],f=0;f<d.length;f+=1)h=d[f],"object"==typeof h?j.append(g,a.util.dataURItoBlob(h.url),h.file_name):j.append(g,h);return a.util.ajax({type:"POST",url:e,data:j,xhrFields:{withCredentials:!0}})})},m.prototype.hasCapacity=function(a){return"list"===a||"query"===a||"select"===a||"limit"===a||"sort"===a},m.prototype.buildQuery=function(c){return i(this).push(function(d){var e,f,g,i,j,k=c.query,l=[];if(c.query)if(f=a.QueryFactory.create(c.query),i=o(f))k=void 0,j=i;else if(i=p(f))k=void 0,j=i;else if(f instanceof h&&"AND"===f.operator)for(e=0;e<f.query_list.length;e+=1)g=f.query_list[e],i=o(g),i?(j=i,f.query_list.splice(e,1),k=a.Query.objectToSearchText(f),e=f.query_list.length):(i=p(g),i&&(j=i,f.query_list.splice(e,1),k=a.Query.objectToSearchText(f),e=f.query_list.length));if(c.sort_on){for(e=0;e<c.sort_on.length;e+=1)l.push(JSON.stringify(c.sort_on[e]));c.sort_on=l}return a.util.ajax({type:"GET",url:b.parse(d._links.raw_search.href).expand({query:k,select_list:c.select_list||["title","reference"],limit:c.limit,sort_on:c.sort_on,local_roles:j}),xhrFields:{withCredentials:!0}})}).push(function(a){return JSON.parse(a.target.responseText)}).push(function(a){var b,c,d,f=a._embedded.contents,g=f.length,h=[];for(b=0;g>b;b+=1)d=f[b],c=new e(d._links.self.href),delete d._links,h.push({id:c.segment(2),value:d});return h})},a.addStorage("erp5",m)}(jIO,UriTemplate,FormData,RSVP,URI,Blob,SimpleQuery,ComplexQuery),function(a,b){"use strict";function c(b){this._sub_storage=a.createJIO(b.sub_storage),this._key_schema=b.key_schema}c.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},c.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},c.prototype.post=function(){return this._sub_storage.post.apply(this._sub_storage,arguments)},c.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},c.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},c.prototype.getAttachment=function(){return this._sub_storage.getAttachment.apply(this._sub_storage,arguments)},c.prototype.putAttachment=function(){return this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},c.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},c.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},c.prototype.hasCapacity=function(a){return"list"===a?this._sub_storage.hasCapacity(a):!0},c.prototype.buildQuery=function(c){var d=this._sub_storage,e=this,f={},g=!1,h=!1;if(d.hasCapacity("list")){try{void 0!==c.query&&!d.hasCapacity("query")||void 0!==c.sort_on&&!d.hasCapacity("sort")||void 0!==c.select_list&&!d.hasCapacity("select")||void 0!==c.limit&&!d.hasCapacity("limit")||(f.query=c.query,f.sort_on=c.sort_on,f.select_list=c.select_list,f.limit=c.limit)}catch(i){if(!(i instanceof a.util.jIOError&&501===i.status_code))throw i;g=!0}try{(g||c.include_docs===!0)&&d.hasCapacity("include")&&(f.include_docs=!0)}catch(i){if(!(i instanceof a.util.jIOError&&501===i.status_code))throw i;h=!0}return d.buildQuery(f).push(function(c){function e(b){var e=c[b].id;return d.get(e).push(function(a){return a._id=e,a},function(b){if(!(b instanceof a.util.jIOError&&404===b.status_code))throw b})}var f,g,i=[c];if(h){for(f=c.length,g=0;f>g;g+=1)i.push(e(g));c=b.all(i)}return c}).push(function(a){var b,c,d;if(h){for(b=a[0],c=b.length,d=0;c>d;d+=1)b[d].doc=a[d+1];a=b}return a}).push(function(b){var d,f,h=[];if(g){for(d=b.length,f=0;d>f;f+=1)b[f].doc.__id=b[f].id,h.push(b[f].doc);c.select_list&&c.select_list.push("__id"),b=a.QueryFactory.create(c.query||"",e._key_schema).exec(h,c)}return b}).push(function(a){var b,d,e,f=[];if(g){for(d=a.length,e=0;d>e;e+=1){if(b={id:a[e].__id,value:c.select_list?a[e]:{},doc:{}},c.select_list&&delete b.value.__id,c.include_docs)throw new Error("QueryStorage does not support include docs");f.push(b)}a=f}return a})}},a.addStorage("query",c)}(jIO,RSVP),function(a,b,c){"use strict";function d(b){this._sub_storage=a.createJIO(b.sub_storage)}function e(a,b){return-1!==a.indexOf(b,a.length-b.length)}var f=".json",g="/.jio_documents/",h="/";d.prototype.get=function(c){var d=this;return(new b.Queue).push(function(){return d._sub_storage.getAttachment(g,c+f,{format:"json"})}).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return d._sub_storage.allAttachments(h).push(function(b){if(b.hasOwnProperty(c))return{};throw new a.util.jIOError("Cannot find document "+c,404)});throw b})},d.prototype.allAttachments=function(b){var c=this;return c._sub_storage.allAttachments(h).push(function(d){return d.hasOwnProperty(b)?{enclosure:{}}:c._sub_storage.getAttachment(g,b+f).push(function(){return{}},function(c){if(c instanceof a.util.jIOError&&404===c.status_code)throw new a.util.jIOError("Cannot find document "+b,404);throw c})})},d.prototype.put=function(b,d){var e=this;return e._sub_storage.putAttachment(g,b+f,new c([JSON.stringify(d)],{type:"application/json"})).push(void 0,function(h){if(h instanceof a.util.jIOError&&404===h.status_code)return e._sub_storage.put(g,{}).push(function(){return e._sub_storage.putAttachment(g,b+f,new c([JSON.stringify(d)],{type:"application/json"}))});throw h}).push(function(){return b})},d.prototype.remove=function(c){var d=this,e=!1;return(new b.Queue).push(function(){return d._sub_storage.removeAttachment(h,c)}).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return void(e=!0);throw b}).push(function(){return d._sub_storage.removeAttachment(g,c+f)}).push(void 0,function(b){if(!e&&b instanceof a.util.jIOError&&404===b.status_code)return c;throw b})},d.prototype.hasCapacity=function(a){return"list"===a},d.prototype.buildQuery=function(){var c={},d=this;return(new b.Queue).push(function(){return d._sub_storage.allAttachments(g)}).push(function(a){var b;for(b in a)a.hasOwnProperty(b)&&e(b,f)&&(c[b.substring(0,b.length-f.length)]=null)},function(b){if(!(b instanceof a.util.jIOError&&404===b.status_code))throw b}).push(function(){return d._sub_storage.allAttachments(h)}).push(function(a){var b;for(b in a)a.hasOwnProperty(b)&&(c[b]=null)}).push(function(){var a,b=[];for(a in c)c.hasOwnProperty(a)&&b.push({id:a,value:{}});return b})},d.prototype.getAttachment=function(b,c){if("enclosure"!==c)throw new a.util.jIOError("Only support 'enclosure' attachment",400);return this._sub_storage.getAttachment(h,b)},d.prototype.putAttachment=function(b,c,d){if("enclosure"!==c)throw new a.util.jIOError("Only support 'enclosure' attachment",400);return this._sub_storage.putAttachment(h,b,d)},d.prototype.removeAttachment=function(b,c){if("enclosure"!==c)throw new a.util.jIOError("Only support 'enclosure' attachment",400);return this._sub_storage.removeAttachment(h,b)},d.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},a.addStorage("drivetojiomapping",d)}(jIO,RSVP,Blob),function(a,b,c,d,e){"use strict";function f(b){this._sub_storage=a.createJIO(b.sub_storage),this._document_id=b.document_id,this._repair_attachment=b.repair_attachment||!1}function g(a,b){return void 0===b?"jio_document/"+d(a)+h:"jio_attachment/"+d(a)+"/"+d(b)}var h=".json",i=new RegExp("^jio_document/([\\w=]+)"+h+"$"),j=new RegExp("^jio_attachment/([\\w=]+)/([\\w=]+)$");f.prototype.get=function(a){return this._sub_storage.getAttachment(this._document_id,g(a),{format:"json"})},f.prototype.allAttachments=function(a){return this._sub_storage.allAttachments(this._document_id).push(function(b){var d,e,f={};for(e in b)if(b.hasOwnProperty(e)&&j.test(e)){d=j.exec(e);try{c(d[1])===a&&(f[c(d[2])]={})}catch(g){if(!g instanceof ReferenceError)throw g}}return f})},f.prototype.put=function(a,c){return this._sub_storage.putAttachment(this._document_id,g(a),new b([JSON.stringify(c)],{type:"application/json"})).push(function(){return a})},f.prototype.remove=function(a){var b=this;return this.allAttachments(a).push(function(c){var d,f=[];for(d in c)c.hasOwnProperty(d)&&f.push(b.removeAttachment(a,d));return e.all(f)}).push(function(){return b._sub_storage.removeAttachment(b._document_id,g(a))}).push(function(){return a})},f.prototype.repair=function(){var a=this;return this._sub_storage.repair.apply(this._sub_storage,arguments).push(function(b){return a._repair_attachment?a._sub_storage.allAttachments(a._document_id).push(function(b){var d,f,g,h,k=[],l={},m={};for(h in b)if(b.hasOwnProperty(h))if(d=void 0,f=void 0,i.test(h)){try{d=c(i.exec(h)[1])}catch(n){if(!n instanceof ReferenceError)throw n}void 0!==d&&(l[d]=null)}else if(j.test(h)){g=j.exec(h);try{d=c(g[1]),f=c(g[2])}catch(n){if(!n instanceof ReferenceError)throw n}void 0!==f&&(l.hasOwnProperty(d)||(m.hasOwnProperty(d)||(m[d]={}),m[d][f]=null))}for(d in m)if(m.hasOwnProperty(d)&&!l.hasOwnProperty(d))for(f in m[d])m[d].hasOwnProperty(f)&&k.push(a.removeAttachment(d,f));return e.all(k)}):b})},f.prototype.hasCapacity=function(a){return"list"===a},f.prototype.buildQuery=function(){return this._sub_storage.allAttachments(this._document_id).push(function(a){var b,d=[];for(b in a)if(a.hasOwnProperty(b)&&i.test(b))try{d.push({id:c(i.exec(b)[1]),value:{}})}catch(e){if(!e instanceof ReferenceError)throw e}return d})},f.prototype.getAttachment=function(a,b){return this._sub_storage.getAttachment(this._document_id,g(a,b))},f.prototype.putAttachment=function(a,b,c){return this._sub_storage.putAttachment(this._document_id,g(a,b),c)},f.prototype.removeAttachment=function(a,b){return this._sub_storage.removeAttachment(this._document_id,g(a,b))},a.addStorage("document",f)}(jIO,Blob,atob,btoa,RSVP),function(a,b,c,d){"use strict";function e(a){a.sessiononly===!0?this._storage=b:this._storage=c}function f(b){if("/"!==b)throw new a.util.jIOError("id "+b+" is forbidden (!== /)",400)}e.prototype.get=function(a){return f(a),{}},e.prototype.allAttachments=function(a){f(a);var b,c={};for(b in this._storage)this._storage.hasOwnProperty(b)&&(c[b]={});return c},e.prototype.getAttachment=function(b,c){f(b);var d=this._storage.getItem(c);if(null===d)throw new a.util.jIOError("Cannot find attachment "+c,404);return a.util.dataURItoBlob(d)},e.prototype.putAttachment=function(b,c,e){var g=this;return f(b),(new d.Queue).push(function(){return a.util.readBlobAsDataURL(e)}).push(function(a){g._storage.setItem(c,a.target.result)})},e.prototype.removeAttachment=function(a,b){return f(a),this._storage.removeItem(b)},e.prototype.hasCapacity=function(a){return"list"===a},e.prototype.buildQuery=function(){return[{id:"/",value:{}}]},a.addStorage("local",e)}(jIO,sessionStorage,localStorage,RSVP),function(a,b,c,d,e,f){"use strict";function g(a){if("string"!=typeof a.database||""===a.database)throw new TypeError("IndexedDBStorage 'database' description property must be a non-empty string");this._database_name="jio:"+a.database}function h(a){return a.join("_")}function i(a){var b,c=a.target.result;b=c.createObjectStore("metadata",{keyPath:"_id",autoIncrement:!1}),b.createIndex("_id","_id",{unique:!0}),b=c.createObjectStore("attachment",{keyPath:"_key_path",autoIncrement:!1}),b.createIndex("_id","_id",{unique:!1}),b=c.createObjectStore("blob",{keyPath:"_key_path",autoIncrement:!1}),b.createIndex("_id_attachment",["_id","_attachment"],{unique:!1}),b.createIndex("_id","_id",{unique:!1})}function j(b){function d(b,c){var d=a.open(e);d.onerror=function(a){d.result&&d.result.close(),c(a)},d.onabort=function(){d.result.close(),c("Aborting connection to: "+e)},d.ontimeout=function(){d.result.close(),c("Connection to: "+e+" timeout")},d.onblocked=function(){d.result.close(),c("Connection to: "+e+" was blocked")},d.onupgradeneeded=i,d.onversionchange=function(){d.result.close(),c(e+" was upgraded")},d.onsuccess=function(){b(d.result)}}var e=b._database_name;return(new c.Queue).push(function(){return new c.Promise(d)})}function k(a,b,c,d){var e=a.transaction(b,c);return d!==!1&&(e.oncomplete=function(){a.close()}),e.onabort=function(){a.close()},e}function l(a,b){function d(c,d){a.onerror=function(b){a.transaction&&a.transaction.abort(),d(b)},a.onsuccess=function(a){var e=a.target.result;if(e){try{b(e)}catch(f){d(f)}e["continue"]()}else c()}}return new c.Promise(d)}function m(a){function d(c,d){a.onerror=d,a.onsuccess=function(){a.result&&c(a.result),d(new b.util.jIOError("Cannot find document",404))}}return new c.Promise(d)}function n(a){function b(b,c){a.onerror=c,a.onsuccess=function(){b(a.result)}}return new c.Promise(b)}function o(a){a["delete"]()}function p(a,b,d){return c.all([n(a.objectStore("attachment")["delete"](h([b,d]))),l(a.objectStore("blob").index("_id_attachment").openCursor(f.only([b,d])),o)])}var q=2e6;g.prototype.hasCapacity=function(a){return"list"===a||"include"===a},g.prototype.buildQuery=function(a){function b(a){d.push({id:a.key,value:{},doc:a.value.doc})}function c(a){d.push({id:a.key,value:{}})}var d=[];return j(this).push(function(d){var e=k(d,["metadata"],"readonly");return a.include_docs===!0?l(e.objectStore("metadata").index("_id").openCursor(),b):l(e.objectStore("metadata").index("_id").openKeyCursor(),c)}).push(function(){return d})},g.prototype.get=function(a){return j(this).push(function(b){var c=k(b,["metadata"],"readonly");return m(c.objectStore("metadata").get(a))}).push(function(a){return a.doc})},g.prototype.allAttachments=function(a){function b(a){d[a.value._attachment]={}}var d={};return j(this).push(function(d){var e=k(d,["metadata","attachment"],"readonly");return c.all([m(e.objectStore("metadata").get(a)),l(e.objectStore("attachment").index("_id").openCursor(f.only(a)),b)])}).push(function(){return d})},g.prototype.put=function(a,b){return j(this).push(function(c){var d=k(c,["metadata"],"readwrite");return n(d.objectStore("metadata").put({_id:a,doc:b}))})},g.prototype.remove=function(a){return j(this).push(function(b){var d=k(b,["metadata","attachment","blob"],"readwrite");return c.all([n(d.objectStore("metadata")["delete"](a)),l(d.objectStore("attachment").index("_id").openCursor(f.only(a)),o),l(d.objectStore("blob").index("_id").openCursor(f.only(a)),o)])})},g.prototype.getAttachment=function(a,f,g){var i,l,n,o;return void 0===g&&(g={}),j(this).push(function(b){return i=k(b,["attachment","blob"],"readonly"),m(i.objectStore("attachment").get(h([a,f])))}).push(function(d){var j,k,p,r=d.info.length,s=[],t=i.objectStore("blob");if(l=d.info.content_type,n=g.start||0,o=g.end||r,o>r&&(o=r),0>n||0>o)throw new b.util.jIOError("_start and _end must be positive",400);if(n>o)throw new b.util.jIOError("_start is greater than _end",400);for(k=e.floor(n/q),p=e.floor(o/q),o%q===0&&(p-=1),j=k;p>=j;j+=1)s.push(m(t.get(h([a,f,j]))));return c.all(s)}).push(function(a){var b,c,f,h=[],i=a.length;for(c=0;i>c;c+=1)h.push(a[c].blob);return void 0===g.start&&void 0===g.end?new d(h,{type:l}):(f=e.floor(n/q)*q,b=new d(h,{type:"application/octet-stream"}),b.slice(n-f,o-f,"application/octet-stream"))})},g.prototype.putAttachment=function(a,d,e){var f,g,i=[];return j(this).push(function(a){return g=a,b.util.readBlobAsArrayBuffer(e)}).push(function(b){for(var c=b.target.result,h=e.size,j=0;h>j;)i.push(c.slice(j,j+q)),j+=q;return f=k(g,["attachment","blob"],"readwrite"),p(f,a,d)}).push(function(){var b,g=[n(f.objectStore("attachment").put({_key_path:h([a,d]),_id:a,_attachment:d,info:{content_type:e.type,length:e.size}}))],j=i.length,k=f.objectStore("blob");for(b=0;j>b;b+=1)g.push(n(k.put({_key_path:h([a,d,b]),_id:a,_attachment:d,_part:b,blob:i[b]})));return c.all(g)})},g.prototype.removeAttachment=function(a,b){return j(this).push(function(c){var d=k(c,["attachment","blob"],"readwrite");return p(d,a,b)})},b.addStorage("indexeddb",g)}(indexedDB,jIO,RSVP,Blob,Math,IDBKeyRange),function(a,b,c,d,e,f,g){"use strict";function h(b){this._key=b.key,this._jsonKey=!0,this._sub_storage=a.createJIO(b.sub_storage)}function i(a){return(new b.Queue).push(function(){return e.subtle.importKey("jwk",a._key,"AES-GCM",!1,["encrypt","decrypt"])}).push(function(b){a._key=b,a._jsonKey=!1})}var j="application/x-jio-aes-gcm-encryption";h.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},h.prototype.post=function(){return this._sub_storage.post.apply(this._sub_storage,arguments)},h.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},h.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},h.prototype.hasCapacity=function(){return this._sub_storage.hasCapacity.apply(this._sub_storage,arguments);
-},h.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},h.prototype.putAttachment=function(c,h,k){var l=e.getRandomValues(new f(12)),m=this;return(new b.Queue).push(function(){return m._jsonKey===!0?i(m):void 0}).push(function(){return a.util.readBlobAsDataURL(k)}).push(function(a){var b,c=a.currentTarget.result.length,d=new g(c),h=new f(d);for(a=a.currentTarget.result,b=0;c>b;b+=1)h[b]=a.charCodeAt(b);return e.subtle.encrypt({name:"AES-GCM",iv:l},m._key,d)}).push(function(a){var b=new d([l,a],{type:j});return m._sub_storage.putAttachment(c,h,b)})},h.prototype.getAttachment=function(d,g){var h=this;return h._sub_storage.getAttachment(d,g).push(function(d){return d.type!==j?d:(new b.Queue).push(function(){return h._jsonKey===!0?i(h):void 0}).push(function(){return a.util.readBlobAsArrayBuffer(d)}).push(function(g){var i;return g=g.currentTarget.result,i=new f(g.slice(0,12)),(new b.Queue).push(function(){return e.subtle.decrypt({name:"AES-GCM",iv:i},h._key,g.slice(12))}).push(function(b){return b=String.fromCharCode.apply(null,new f(b)),a.util.dataURItoBlob(b)}).push(void 0,function(a){if(a instanceof c)return d;throw a})})})},h.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},h.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},a.addStorage("crypt",h)}(jIO,RSVP,DOMException,Blob,crypto,Uint8Array,ArrayBuffer),function(a,b,c,d){"use strict";function e(a,c,d){return new b.Promise(function(b,e){a.transaction(function(a){function f(a,c){j.push(c),j.length===i&&b(j)}function g(a,b){return e(b),!0}var h,i=c.length,j=[];for(h=0;i>h;h+=1)a.executeSql(c[h],d[h],f,g)},function(a,b){e(b)})})}function f(a){var c=["CREATE TABLE IF NOT EXISTS document(id VARCHAR PRIMARY KEY NOT NULL, data TEXT)","CREATE TABLE IF NOT EXISTS attachment(id VARCHAR, attachment VARCHAR, part INT, blob TEXT)","CREATE TRIGGER IF NOT EXISTS removeAttachment BEFORE DELETE ON document FOR EACH ROW BEGIN DELETE from attachment WHERE id = OLD.id;END;","CREATE INDEX IF NOT EXISTS index_document ON document (id);","CREATE INDEX IF NOT EXISTS index_attachment ON attachment (id, attachment);"];return(new b.Queue).push(function(){return e(a,c,[])})}function g(a){if("string"!=typeof a.database||!a.database)throw new TypeError("database must be a string which contains more than one character.");if(this._database=d("jio:"+a.database,"1.0","",2097152),a.blob_length&&("number"!=typeof a.blob_length||a.blob_length<20))throw new TypeError("blob_len parameter must be a number >= 20");this._blob_length=a.blob_length||2e6,this._init_db_promise=f(this._database)}function h(b,c,d,e){e.push(function(){return a.util.readBlobAsDataURL(b)}).push(function(a){c[d+2].push(a.currentTarget.result)})}g.prototype.put=function(a,c){var d=this._database,f=this,g=JSON.stringify(c);return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["INSERT OR REPLACE INTO document(id, data) VALUES(?,?)"],[[a,g]])}).push(function(){return a})},g.prototype.remove=function(c){var d=this._database,f=this;return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["DELETE FROM document WHERE id = ?"],[[c]])}).push(function(b){if(0===b[0].rowsAffected)throw new a.util.jIOError("Cannot find document",404);return c})},g.prototype.get=function(c){var d=this._database,f=this;return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["SELECT data FROM document WHERE id = ?"],[[c]])}).push(function(b){if(0===b[0].rows.length)throw new a.util.jIOError("Cannot find document",404);return JSON.parse(b[0].rows[0].data)})},g.prototype.allAttachments=function(c){var d=this._database,f=this;return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["SELECT id FROM document WHERE id = ?","SELECT DISTINCT attachment FROM attachment WHERE id = ?"],[[c],[c]])}).push(function(b){if(0===b[0].rows.length)throw new a.util.jIOError("Cannot find document",404);var c,d=b[1].rows.length,e={};for(c=0;d>c;c+=1)e[b[1].rows[c].attachment]={};return e})},g.prototype.putAttachment=function(c,d,f){var g=this._database,i=this,j=this._blob_length;return(new b.Queue).push(function(){return i._init_db_promise}).push(function(){return e(g,["SELECT id FROM document WHERE id = ?"],[[c]])}).push(function(i){var k,l,m=[],n=[],o=f.size,p=new b.Queue;if(0===i[0].rows.length)throw new a.util.jIOError("Cannot access subdocument",404);for(m.push("DELETE FROM attachment WHERE id = ? AND attachment = ?"),n.push([c,d]),m.push("INSERT INTO attachment(id, attachment, part, blob)VALUES(?, ?, ?, ?)"),n.push([c,d,-1,f.type||"application/octet-stream"]),k=0,l=0;o>k;k+=j,l+=1)m.push("INSERT INTO attachment(id, attachment, part, blob)VALUES(?, ?, ?, ?)"),n.push([c,d,l]),h(f.slice(k,k+j),n,l,p);return p.push(function(){return e(g,m,n)}),p})},g.prototype.getAttachment=function(d,f,g){var h,i,j,k,l=this._database,m=this,n=this._blob_length;if(void 0===g&&(g={}),h=g.start||0,i=g.end||-1,0>h||void 0!==g.end&&g.end<0)throw new a.util.jIOError("_start and _end must be positive",400);if(h>i&&-1!==i)throw new a.util.jIOError("_start is greater than _end",400);return j=Math.floor(h/n),0===h&&(j-=1),k=Math.floor(i/n),i%n===0&&(k-=1),(new b.Queue).push(function(){return m._init_db_promise}).push(function(){var a="SELECT part, blob FROM attachment WHERE id = ? AND attachment = ? AND part >= ?",b=[d,f,j];return-1!==i&&(a+=" AND part <= ?",b.push(k)),e(l,[a],[b])}).push(function(b){var d,e,f,k,l=[];if(e=b[0].rows,0===e.length)throw new a.util.jIOError("Cannot find document",404);for(d=0;d<e.length;d+=1)-1===e[d].part?(k=e[d].blob,j+=1):l.push(a.util.dataURItoBlob(e[d].blob));return 0===h&&void 0===g.end?new c(l,{type:k}):(f=new c(l,{}),f.slice(h-j*n,-1===i?f.size:i-j*n,"application/octet-stream"))})},g.prototype.removeAttachment=function(c,d){var f=this._database,g=this;return(new b.Queue).push(function(){return g._init_db_promise}).push(function(){return e(f,["DELETE FROM attachment WHERE id = ? AND attachment = ?"],[[c,d]])}).push(function(b){if(0===b[0].rowsAffected)throw new a.util.jIOError("Cannot find document",404);return d})},g.prototype.hasCapacity=function(a){return"list"===a||"include"===a},g.prototype.buildQuery=function(a){var c=this._database,d=this,f="SELECT id";return(new b.Queue).push(function(){return d._init_db_promise}).push(function(){return void 0===a&&(a={}),a.include_docs===!0&&(f+=", data AS doc"),f+=" FROM document",e(c,[f],[[]])}).push(function(a){var b,c=[],d=a[0].rows.length;for(b=0;d>b;b+=1)c.push(a[0].rows[b]),c[b].value={},void 0!==c[b].doc&&(c[b].doc=JSON.parse(c[b].doc));return c})},a.addStorage("websql",g)}(jIO,RSVP,Blob,openDatabase);
\ No newline at end of file
+if(a.toASCII(b).match(e.invalid_hostname_characters))throw new TypeError("Hostname '"+b+"' contains characters other than [A-Z0-9.-]")}},e.noConflict=function(a){return a?(a={URI:this.noConflict()},URITemplate&&"function"==typeof URITemplate.noConflict&&(a.URITemplate=URITemplate.noConflict()),b&&"function"==typeof b.noConflict&&(a.IPv6=b.noConflict()),SecondLevelDomains&&"function"==typeof SecondLevelDomains.noConflict&&(a.SecondLevelDomains=SecondLevelDomains.noConflict()),a):(d.URI===this&&(d.URI=m),this)},n.build=function(a){return!0===a?this._deferred_build=!0:(void 0===a||this._deferred_build)&&(this._string=e.build(this._parts),this._deferred_build=!1),this},n.clone=function(){return new e(this)},n.valueOf=n.toString=function(){return this.build(!1)._string},q={protocol:"protocol",username:"username",password:"password",hostname:"hostname",port:"port"},r=function(a){return function(b,c){return void 0===b?this._parts[a]||"":(this._parts[a]=b||null,this.build(!c),this)}};for(p in q)n[p]=r(q[p]);q={query:"?",fragment:"#"},r=function(a,b){return function(c,d){return void 0===c?this._parts[a]||"":(null!==c&&(c+="",c.charAt(0)===b&&(c=c.substring(1))),this._parts[a]=c,this.build(!d),this)}};for(p in q)n[p]=r(p,q[p]);q={search:["?","query"],hash:["#","fragment"]},r=function(a,b){return function(c,d){var e=this[a](c,d);return"string"==typeof e&&e.length?b+e:e}};for(p in q)n[p]=r(q[p][1],q[p][0]);n.pathname=function(a,b){if(void 0===a||!0===a){var c=this._parts.path||(this._parts.hostname?"/":"");return a?e.decodePath(c):c}return this._parts.path=a?e.recodePath(a):"/",this.build(!b),this},n.path=n.pathname,n.href=function(a,b){var c;if(void 0===a)return this.toString();this._string="",this._parts=e._parts();var d=a instanceof e,f="object"==typeof a&&(a.hostname||a.path||a.pathname);if(a.nodeName&&(f=e.getDomAttribute(a),a=a[f]||"",f=!1),!d&&f&&void 0!==a.pathname&&(a=a.toString()),"string"==typeof a)this._parts=e.parse(a,this._parts);else{if(!d&&!f)throw new TypeError("invalid input");for(c in d=d?a._parts:a)o.call(this._parts,c)&&(this._parts[c]=d[c])}return this.build(!b),this},n.is=function(a){var b=!1,d=!1,f=!1,g=!1,h=!1,i=!1,j=!1,k=!this._parts.urn;switch(this._parts.hostname&&(k=!1,d=e.ip4_expression.test(this._parts.hostname),f=e.ip6_expression.test(this._parts.hostname),b=d||f,h=(g=!b)&&c&&c.has(this._parts.hostname),i=g&&e.idn_expression.test(this._parts.hostname),j=g&&e.punycode_expression.test(this._parts.hostname)),a.toLowerCase()){case"relative":return k;case"absolute":return!k;case"domain":case"name":return g;case"sld":return h;case"ip":return b;case"ip4":case"ipv4":case"inet4":return d;case"ip6":case"ipv6":case"inet6":return f;case"idn":return i;case"url":return!this._parts.urn;case"urn":return!!this._parts.urn;case"punycode":return j}return null};var s=n.protocol,t=n.port,u=n.hostname;n.protocol=function(a,b){if(void 0!==a&&a&&(a=a.replace(/:(\/\/)?$/,""),!a.match(e.protocol_expression)))throw new TypeError("Protocol '"+a+"' contains characters other than [A-Z0-9.+-] or doesn't start with [A-Z]");return s.call(this,a,b)},n.scheme=n.protocol,n.port=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a&&(0===a&&(a=null),a&&(a+="",":"===a.charAt(0)&&(a=a.substring(1)),a.match(/[^0-9]/))))throw new TypeError("Port '"+a+"' contains characters other than [0-9]");return t.call(this,a,b)},n.hostname=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a){var c={};e.parseHost(a,c),a=c.hostname}return u.call(this,a,b)},n.host=function(a,b){return this._parts.urn?void 0===a?"":this:void 0===a?this._parts.hostname?e.buildHost(this._parts):"":(e.parseHost(a,this._parts),this.build(!b),this)},n.authority=function(a,b){return this._parts.urn?void 0===a?"":this:void 0===a?this._parts.hostname?e.buildAuthority(this._parts):"":(e.parseAuthority(a,this._parts),this.build(!b),this)},n.userinfo=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.username)return"";var c=e.buildUserinfo(this._parts);return c.substring(0,c.length-1)}return"@"!==a[a.length-1]&&(a+="@"),e.parseUserinfo(a,this._parts),this.build(!b),this},n.resource=function(a,b){var c;return void 0===a?this.path()+this.search()+this.hash():(c=e.parse(a),this._parts.path=c.path,this._parts.query=c.query,this._parts.fragment=c.fragment,this.build(!b),this)},n.subdomain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.length-this.domain().length-1;return this._parts.hostname.substring(0,c)||""}return c=this._parts.hostname.length-this.domain().length,c=this._parts.hostname.substring(0,c),c=RegExp("^"+f(c)),a&&"."!==a.charAt(a.length-1)&&(a+="."),a&&e.ensureValidHostname(a),this._parts.hostname=this._parts.hostname.replace(c,a),this.build(!b),this},n.domain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if("boolean"==typeof a&&(b=a,a=void 0),void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.match(/\./g);return c&&2>c.length?this._parts.hostname:(c=this._parts.hostname.length-this.tld(b).length-1,c=this._parts.hostname.lastIndexOf(".",c-1)+1,this._parts.hostname.substring(c)||"")}if(!a)throw new TypeError("cannot set domain empty");return e.ensureValidHostname(a),!this._parts.hostname||this.is("IP")?this._parts.hostname=a:(c=RegExp(f(this.domain())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a)),this.build(!b),this},n.tld=function(a,b){if(this._parts.urn)return void 0===a?"":this;if("boolean"==typeof a&&(b=a,a=void 0),void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var d=this._parts.hostname.lastIndexOf("."),d=this._parts.hostname.substring(d+1);return!0!==b&&c&&c.list[d.toLowerCase()]?c.get(this._parts.hostname)||d:d}if(!a)throw new TypeError("cannot set TLD empty");if(a.match(/[^a-zA-Z0-9-]/)){if(!c||!c.is(a))throw new TypeError("TLD '"+a+"' contains characters other than [A-Z0-9]");d=RegExp(f(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(d,a)}else{if(!this._parts.hostname||this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");d=RegExp(f(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(d,a)}return this.build(!b),this},n.directory=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var c=this._parts.path.length-this.filename().length-1,c=this._parts.path.substring(0,c)||(this._parts.hostname?"/":"");return a?e.decodePath(c):c}return c=this._parts.path.length-this.filename().length,c=this._parts.path.substring(0,c),c=RegExp("^"+f(c)),this.is("relative")||(a||(a="/"),"/"!==a.charAt(0)&&(a="/"+a)),a&&"/"!==a.charAt(a.length-1)&&(a+="/"),a=e.recodePath(a),this._parts.path=this._parts.path.replace(c,a),this.build(!b),this},n.filename=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var c=this._parts.path.lastIndexOf("/"),c=this._parts.path.substring(c+1);return a?e.decodePathSegment(c):c}c=!1,"/"===a.charAt(0)&&(a=a.substring(1)),a.match(/\.?\//)&&(c=!0);var d=RegExp(f(this.filename())+"$");return a=e.recodePath(a),this._parts.path=this._parts.path.replace(d,a),c?this.normalizePath(b):this.build(!b),this},n.suffix=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var c=this.filename(),d=c.lastIndexOf(".");return-1===d?"":(c=c.substring(d+1),c=/^[a-z0-9%]+$/i.test(c)?c:"",a?e.decodePathSegment(c):c)}if("."===a.charAt(0)&&(a=a.substring(1)),c=this.suffix())d=a?RegExp(f(c)+"$"):RegExp(f("."+c)+"$");else{if(!a)return this;this._parts.path+="."+e.recodePath(a)}return d&&(a=e.recodePath(a),this._parts.path=this._parts.path.replace(d,a)),this.build(!b),this},n.segment=function(a,b,c){var d=this._parts.urn?":":"/",e=this.path(),f="/"===e.substring(0,1),e=e.split(d);if(void 0!==a&&"number"!=typeof a&&(c=b,b=a,a=void 0),void 0!==a&&"number"!=typeof a)throw Error("Bad segment '"+a+"', must be 0-based integer");if(f&&e.shift(),0>a&&(a=Math.max(e.length+a,0)),void 0===b)return void 0===a?e:e[a];if(null===a||void 0===e[a])if(h(b)){e=[],a=0;for(var g=b.length;g>a;a++)(b[a].length||e.length&&e[e.length-1].length)&&(e.length&&!e[e.length-1].length&&e.pop(),e.push(b[a]))}else(b||"string"==typeof b)&&(""===e[e.length-1]?e[e.length-1]=b:e.push(b));else b||"string"==typeof b&&b.length?e[a]=b:e.splice(a,1);return f&&e.unshift(""),this.path(e.join(d),c)},n.segmentCoded=function(a,b,c){var d,f;if("number"!=typeof a&&(c=b,b=a,a=void 0),void 0===b){if(a=this.segment(a,b,c),h(a))for(d=0,f=a.length;f>d;d++)a[d]=e.decode(a[d]);else a=void 0!==a?e.decode(a):void 0;return a}if(h(b))for(d=0,f=b.length;f>d;d++)b[d]=e.decode(b[d]);else b="string"==typeof b?e.encode(b):b;return this.segment(a,b,c)};var v=n.query;return n.query=function(a,b){if(!0===a)return e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("function"==typeof a){var c=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace),d=a.call(this,c);return this._parts.query=e.buildQuery(d||c,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!b),this}return void 0!==a&&"string"!=typeof a?(this._parts.query=e.buildQuery(a,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!b),this):v.call(this,a,b)},n.setQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("object"==typeof a)for(var f in a)o.call(a,f)&&(d[f]=a[f]);else{if("string"!=typeof a)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");d[a]=void 0!==b?b:null}return this._parts.query=e.buildQuery(d,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof a&&(c=b),this.build(!c),this},n.addQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return e.addQuery(d,a,void 0===b?null:b),this._parts.query=e.buildQuery(d,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof a&&(c=b),this.build(!c),this},n.removeQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return e.removeQuery(d,a,b),this._parts.query=e.buildQuery(d,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof a&&(c=b),this.build(!c),this},n.hasQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return e.hasQuery(d,a,b,c)},n.setSearch=n.setQuery,n.addSearch=n.addQuery,n.removeSearch=n.removeQuery,n.hasSearch=n.hasQuery,n.normalize=function(){return this._parts.urn?this.normalizeProtocol(!1).normalizeQuery(!1).normalizeFragment(!1).build():this.normalizeProtocol(!1).normalizeHostname(!1).normalizePort(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build()},n.normalizeProtocol=function(a){return"string"==typeof this._parts.protocol&&(this._parts.protocol=this._parts.protocol.toLowerCase(),this.build(!a)),this},n.normalizeHostname=function(c){return this._parts.hostname&&(this.is("IDN")&&a?this._parts.hostname=a.toASCII(this._parts.hostname):this.is("IPv6")&&b&&(this._parts.hostname=b.best(this._parts.hostname)),this._parts.hostname=this._parts.hostname.toLowerCase(),this.build(!c)),this},n.normalizePort=function(a){return"string"==typeof this._parts.protocol&&this._parts.port===e.defaultPorts[this._parts.protocol]&&(this._parts.port=null,this.build(!a)),this},n.normalizePath=function(a){if(this._parts.urn||!this._parts.path||"/"===this._parts.path)return this;var b,c,d,f=this._parts.path,g="";for("/"!==f.charAt(0)&&(b=!0,f="/"+f),f=f.replace(/(\/(\.\/)+)|(\/\.$)/g,"/").replace(/\/{2,}/g,"/"),b&&(g=f.substring(1).match(/^(\.\.\/)+/)||"")&&(g=g[0]);c=f.indexOf("/.."),-1!==c;)0!==c?(d=f.substring(0,c).lastIndexOf("/"),-1===d&&(d=c),f=f.substring(0,d)+f.substring(c+3)):f=f.substring(3);return b&&this.is("relative")&&(f=g+f.substring(1)),f=e.recodePath(f),this._parts.path=f,this.build(!a),this},n.normalizePathname=n.normalizePath,n.normalizeQuery=function(a){return"string"==typeof this._parts.query&&(this._parts.query.length?this.query(e.parseQuery(this._parts.query,this._parts.escapeQuerySpace)):this._parts.query=null,this.build(!a)),this},n.normalizeFragment=function(a){return this._parts.fragment||(this._parts.fragment=null,this.build(!a)),this},n.normalizeSearch=n.normalizeQuery,n.normalizeHash=n.normalizeFragment,n.iso8859=function(){var a=e.encode,b=e.decode;return e.encode=escape,e.decode=decodeURIComponent,this.normalize(),e.encode=a,e.decode=b,this},n.unicode=function(){var a=e.encode,b=e.decode;return e.encode=l,e.decode=unescape,this.normalize(),e.encode=a,e.decode=b,this},n.readable=function(){var b=this.clone();b.username("").password("").normalize();var c="";if(b._parts.protocol&&(c+=b._parts.protocol+"://"),b._parts.hostname&&(b.is("punycode")&&a?(c+=a.toUnicode(b._parts.hostname),b._parts.port&&(c+=":"+b._parts.port)):c+=b.host()),b._parts.hostname&&b._parts.path&&"/"!==b._parts.path.charAt(0)&&(c+="/"),c+=b.path(!0),b._parts.query){for(var d="",f=0,g=b._parts.query.split("&"),h=g.length;h>f;f++){var i=(g[f]||"").split("="),d=d+("&"+e.decodeQuery(i[0],this._parts.escapeQuerySpace).replace(/&/g,"%26"));void 0!==i[1]&&(d+="="+e.decodeQuery(i[1],this._parts.escapeQuerySpace).replace(/&/g,"%26"))}c+="?"+d.substring(1)}return c+=e.decodeQuery(b.hash(),!0)},n.absoluteTo=function(a){var b,c,d=this.clone(),f=["protocol","username","password","hostname","port"];if(this._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");if(a instanceof e||(a=new e(a)),d._parts.protocol||(d._parts.protocol=a._parts.protocol),this._parts.hostname)return d;for(b=0;c=f[b];b++)d._parts[c]=a._parts[c];return d._parts.path?".."===d._parts.path.substring(-2)&&(d._parts.path+="/"):(d._parts.path=a._parts.path,d._parts.query||(d._parts.query=a._parts.query)),"/"!==d.path().charAt(0)&&(a=a.directory(),d._parts.path=(a?a+"/":"")+d._parts.path,d.normalizePath()),d.build(),d},n.relativeTo=function(a){var b,c,d,f,g=this.clone().normalize();if(g._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");if(a=new e(a).normalize(),b=g._parts,c=a._parts,d=g.path(),f=a.path(),"/"!==d.charAt(0))throw Error("URI is already relative");if("/"!==f.charAt(0))throw Error("Cannot calculate a URI relative to another relative URI");return b.protocol===c.protocol&&(b.protocol=null),b.username!==c.username||b.password!==c.password||null!==b.protocol||null!==b.username||null!==b.password||b.hostname!==c.hostname||b.port!==c.port?g.build():(b.hostname=null,b.port=null,d===f?(b.path="",g.build()):(a=e.commonPath(g.path(),a.path()))?(c=c.path.substring(a.length).replace(/[^\/]*$/,"").replace(/.*?\//g,"../"),b.path=c+b.path.substring(a.length),g.build()):g.build())},n.equals=function(a){var b=this.clone();a=new e(a);var c,d={},f={},g={};if(b.normalize(),a.normalize(),b.toString()===a.toString())return!0;if(d=b.query(),f=a.query(),b.query(""),a.query(""),b.toString()!==a.toString()||d.length!==f.length)return!1;d=e.parseQuery(d,this._parts.escapeQuerySpace),f=e.parseQuery(f,this._parts.escapeQuerySpace);for(c in d)if(o.call(d,c)){if(h(d[c])){if(!j(d[c],f[c]))return!1}else if(d[c]!==f[c])return!1;g[c]=!0}for(c in f)if(o.call(f,c)&&!g[c])return!1;return!0},n.duplicateQueryParameters=function(a){return this._parts.duplicateQueryParameters=!!a,this},n.escapeQuerySpace=function(a){return this._parts.escapeQuerySpace=!!a,this},e}),function(a,b){"object"==typeof exports?module.exports=b(require("./URI")):"function"==typeof define&&define.amd?define(["./URI"],b):b(a.URI)}(this,function(a){var b=a.prototype,c=b.fragment;a.fragmentPrefix="?";var d=a._parts;return a._parts=function(){var b=d();return b.fragmentPrefix=a.fragmentPrefix,b},b.fragmentPrefix=function(a){return this._parts.fragmentPrefix=a,this},b.fragment=function(b,d){var e=this._parts.fragmentPrefix,f=this._parts.fragment||"";return!0===b?f.substring(0,e.length)!==e?{}:a.parseQuery(f.substring(e.length)):void 0!==b&&"string"!=typeof b?(this._parts.fragment=e+a.buildQuery(b),this.build(!d),this):c.call(this,b,d)},b.addFragment=function(b,c,d){var e=this._parts.fragmentPrefix,f=a.parseQuery((this._parts.fragment||"").substring(e.length));return a.addQuery(f,b,c),this._parts.fragment=e+a.buildQuery(f),"string"!=typeof b&&(d=c),this.build(!d),this},b.removeFragment=function(b,c,d){var e=this._parts.fragmentPrefix,f=a.parseQuery((this._parts.fragment||"").substring(e.length));return a.removeQuery(f,b,c),this._parts.fragment=e+a.buildQuery(f),"string"!=typeof b&&(d=c),this.build(!d),this},b.addHash=b.addFragment,b.removeHash=b.removeFragment,{}}),function(a){"use strict";function b(a){var c;if(null===a||void 0===a)return!1;if(d.isArray(a))return a.length>0;if("string"==typeof a||"number"==typeof a||"boolean"==typeof a)return!0;for(c in a)if(a.hasOwnProperty(c)&&b(a[c]))return!0;return!1}var c=function(){function a(a){this.options=a}return a.prototype.toString=function(){return JSON&&JSON.stringify?JSON.stringify(this.options):this.options},a}(),d=function(){function a(a){return"[object Array]"===Object.prototype.toString.apply(a)}function b(a){return"[object String]"===Object.prototype.toString.apply(a)}function c(a){return"[object Number]"===Object.prototype.toString.apply(a)}function d(a){return"[object Boolean]"===Object.prototype.toString.apply(a)}function e(a,b){var c,d="",e=!0;for(c=0;c<a.length;c+=1)e?e=!1:d+=b,d+=a[c];return d}function f(a,b){for(var c=[],d=0;d<a.length;d+=1)c.push(b(a[d]));return c}function g(a,b){for(var c=[],d=0;d<a.length;d+=1)b(a[d])&&c.push(a[d]);return c}function h(a){if("object"!=typeof a||null===a)return a;Object.freeze(a);var b,c;for(c in a)a.hasOwnProperty(c)&&(b=a[c],"object"!=typeof b||b instanceof RegExp||i(b));return a}function i(a){return"function"==typeof Object.freeze?h(a):a}return{isArray:a,isString:b,isNumber:c,isBoolean:d,join:e,map:f,filter:g,deepFreeze:i}}(),e=function(){function a(a){return a>="a"&&"z">=a||a>="A"&&"Z">=a}function b(a){return a>="0"&&"9">=a}function c(a){return b(a)||a>="a"&&"f">=a||a>="A"&&"F">=a}return{isAlpha:a,isDigit:b,isHexDigit:c}}(),f=function(){function a(a){var b,c,d="",e=g.encode(a);for(c=0;c<e.length;c+=1)b=e.charCodeAt(c),d+="%"+(16>b?"0":"")+b.toString(16).toUpperCase();return d}function b(a,b){return"%"===a.charAt(b)&&e.isHexDigit(a.charAt(b+1))&&e.isHexDigit(a.charAt(b+2))}function c(a,b){return parseInt(a.substr(b,2),16)}function d(a){if(!b(a,0))return!1;var d=c(a,1),e=g.numBytes(d);if(0===e)return!1;for(var f=1;e>f;f+=1)if(!b(a,3*f)||!g.isValidFollowingCharCode(c(a,3*f+1)))return!1;return!0}function f(a,d){var e=a.charAt(d);if(!b(a,d))return e;var f=c(a,d+1),h=g.numBytes(f);if(0===h)return e;for(var i=1;h>i;i+=1)if(!b(a,d+3*i)||!g.isValidFollowingCharCode(c(a,d+3*i+1)))return e;return a.substr(d,3*h)}var g={encode:function(a){return unescape(encodeURIComponent(a))},numBytes:function(a){return 127>=a?1:a>=194&&223>=a?2:a>=224&&239>=a?3:a>=240&&244>=a?4:0},isValidFollowingCharCode:function(a){return a>=128&&191>=a}};return{encodeCharacter:a,isPctEncoded:d,pctCharAt:f}}(),g=function(){function a(a){return e.isAlpha(a)||e.isDigit(a)||"_"===a||f.isPctEncoded(a)}function b(a){return e.isAlpha(a)||e.isDigit(a)||"-"===a||"."===a||"_"===a||"~"===a}function c(a){return":"===a||"/"===a||"?"===a||"#"===a||"["===a||"]"===a||"@"===a||"!"===a||"$"===a||"&"===a||"("===a||")"===a||"*"===a||"+"===a||","===a||";"===a||"="===a||"'"===a}return{isVarchar:a,isUnreserved:b,isReserved:c}}(),h=function(){function a(a,b){var c,d="",e="";for(("number"==typeof a||"boolean"==typeof a)&&(a=a.toString()),c=0;c<a.length;c+=e.length)e=a.charAt(c),d+=g.isUnreserved(e)||b&&g.isReserved(e)?e:f.encodeCharacter(e);return d}function b(b){return a(b,!0)}function c(a,b){var c=f.pctCharAt(a,b);return c.length>1?c:g.isReserved(c)||g.isUnreserved(c)?c:f.encodeCharacter(c)}function d(a){var b,c="",d="";for(b=0;b<a.length;b+=d.length)d=f.pctCharAt(a,b),c+=d.length>1?d:g.isReserved(d)||g.isUnreserved(d)?d:f.encodeCharacter(d);return c}return{encode:a,encodePassReserved:b,encodeLiteral:d,encodeLiteralCharacter:c}}(),i=function(){function a(a){b[a]={symbol:a,separator:"?"===a?"&":""===a||"+"===a||"#"===a?",":a,named:";"===a||"&"===a||"?"===a,ifEmpty:"&"===a||"?"===a?"=":"",first:"+"===a?"":a,encode:"+"===a||"#"===a?h.encodePassReserved:h.encode,toString:function(){return this.symbol}}}var b={};return a(""),a("+"),a("#"),a("."),a("/"),a(";"),a("?"),a("&"),{valueOf:function(a){return b[a]?b[a]:"=,!@|".indexOf(a)>=0?null:b[""]}}}(),j=function(){function a(a){this.literal=h.encodeLiteral(a)}return a.prototype.expand=function(){return this.literal},a.prototype.toString=a.prototype.expand,a}(),k=function(){function a(a){function b(){var b=a.substring(n,j);if(0===b.length)throw new c({expressionText:a,message:"a varname must be specified",position:j});m={varname:b,exploded:!1,maxLength:null},n=null}function d(){if(o===j)throw new c({expressionText:a,message:"after a ':' you have to specify the length",position:j});m.maxLength=parseInt(a.substring(o,j),10),o=null}var h,j,k=[],m=null,n=null,o=null,p="";for(h=function(b){var d=i.valueOf(b);if(null===d)throw new c({expressionText:a,message:"illegal use of reserved operator",position:j,operator:b});return d}(a.charAt(0)),j=h.symbol.length,n=j;j<a.length;j+=p.length){if(p=f.pctCharAt(a,j),null!==n){if("."===p){if(n===j)throw new c({expressionText:a,message:"a varname MUST NOT start with a dot",position:j});continue}if(g.isVarchar(p))continue;b()}if(null!==o){if(j===o&&"0"===p)throw new c({expressionText:a,message:"A :prefix must not start with digit 0",position:j});if(e.isDigit(p)){if(j-o>=4)throw new c({expressionText:a,message:"A :prefix must have max 4 digits",position:j});continue}d()}if(":"!==p)if("*"!==p){if(","!==p)throw new c({expressionText:a,message:"illegal character",character:p,position:j});k.push(m),m=null,n=j+1}else{if(null===m)throw new c({expressionText:a,message:"exploded without varspec",position:j});if(m.exploded)throw new c({expressionText:a,message:"exploded twice",position:j});if(m.maxLength)throw new c({expressionText:a,message:"an explode (*) MUST NOT follow to a prefix",position:j});m.exploded=!0}else{if(null!==m.maxLength)throw new c({expressionText:a,message:"only one :maxLength is allowed per varspec",position:j});if(m.exploded)throw new c({expressionText:a,message:"an exploeded varspec MUST NOT be varspeced",position:j});o=j+1}}return null!==n&&b(),null!==o&&d(),k.push(m),new l(a,h,k)}function b(a){return a.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function d(d){var e,f,g,h=[],i=null,k="",l=!0,n=0;for(e=0;e<d.length;e+=1)if(f=d.charAt(e),null===n){if(null===i)throw new Error("reached unreachable code");if("{"===f)throw new c({templateText:d,message:"brace already opened",position:e});if("}"===f){if(i+1===e)throw new c({templateText:d,message:"empty braces",position:i});try{g=a(d.substring(i+1,e))}catch(o){if(o.prototype===c.prototype)throw new c({templateText:d,message:o.options.message,position:i+o.options.position,details:o.options});throw o}h.push(g),0===g.operator.symbol.length?k+="([^/]+)":l=!1,i=null,n=e+1}}else{if("}"===f)throw new c({templateText:d,message:"unopened brace closed",position:e});"{"===f&&(e>n&&(g=new j(d.substring(n,e)),h.push(g),k+=b(g.literal)),n=null,i=e)}if(null!==i)throw new c({templateText:d,message:"unclosed brace",position:i});return n<d.length&&(g=new j(d.substring(n)),h.push(g),k+=b(g.literal)),l===!1&&(k=void 0),new m(d,h,k)}return d}(),l=function(){function a(a){return JSON&&JSON.stringify?JSON.stringify(a):a}function c(a){if(!b(a))return!0;if(d.isString(a))return""===a;if(d.isNumber(a)||d.isBoolean(a))return!1;if(d.isArray(a))return 0===a.length;for(var c in a)if(a.hasOwnProperty(c))return!1;return!0}function e(a){var b,c=[];for(b in a)a.hasOwnProperty(b)&&c.push({name:b,value:a[b]});return c}function f(a,b,c){this.templateText=a,this.operator=b,this.varspecs=c}function g(a,b,c){var d="";if(c=c.toString(),b.named){if(d+=h.encodeLiteral(a.varname),""===c)return d+=b.ifEmpty;d+="="}return null!==a.maxLength&&(c=c.substr(0,a.maxLength)),d+=b.encode(c)}function i(a){return b(a.value)}function j(a,f,g){var j=[],k="";if(f.named){if(k+=h.encodeLiteral(a.varname),c(g))return k+=f.ifEmpty;k+="="}return d.isArray(g)?(j=g,j=d.filter(j,b),j=d.map(j,f.encode),k+=d.join(j,",")):(j=e(g),j=d.filter(j,i),j=d.map(j,function(a){return f.encode(a.name)+","+f.encode(a.value)}),k+=d.join(j,",")),k}function k(a,f,g){var j=d.isArray(g),k=[];return j?(k=g,k=d.filter(k,b),k=d.map(k,function(b){var d=h.encodeLiteral(a.varname);return d+=c(b)?f.ifEmpty:"="+f.encode(b)})):(k=e(g),k=d.filter(k,i),k=d.map(k,function(a){var b=h.encodeLiteral(a.name);return b+=c(a.value)?f.ifEmpty:"="+f.encode(a.value)})),d.join(k,f.separator)}function l(a,c){var f=[],g="";return d.isArray(c)?(f=c,f=d.filter(f,b),f=d.map(f,a.encode),g+=d.join(f,a.separator)):(f=e(c),f=d.filter(f,function(a){return b(a.value)}),f=d.map(f,function(b){return a.encode(b.name)+"="+a.encode(b.value)}),g+=d.join(f,a.separator)),g}return f.prototype.toString=function(){return this.templateText},f.prototype.expand=function(e){var f,h,i,m,n=[],o=!1,p=this.operator;for(f=0;f<this.varspecs.length;f+=1)if(h=this.varspecs[f],i=e[h.varname],null!==i&&void 0!==i)if(h.exploded&&(o=!0),m=d.isArray(i),"string"==typeof i||"number"==typeof i||"boolean"==typeof i)n.push(g(h,p,i));else{if(h.maxLength&&b(i))throw new Error("Prefix modifiers are not applicable to variables that have composite values. You tried to expand "+this+" with "+a(i));h.exploded?b(i)&&(p.named?n.push(k(h,p,i)):n.push(l(p,i))):(p.named||!c(i))&&n.push(j(h,p,i))}return 0===n.length?"":p.first+d.join(n,p.separator)},f}(),m=function(){function a(a,b,c){this.templateText=a,this.expressions=b,void 0!==c&&(this.regexp=new RegExp("^"+c+"$")),d.deepFreeze(this)}return a.prototype.toString=function(){return this.templateText},a.prototype.expand=function(a){var b,c="";for(b=0;b<this.expressions.length;b+=1)c+=this.expressions[b].expand(a);return c},a.prototype.extract=function(a){var b,c,d,e,f=1,g=!0,h={};if(void 0!==this.regexp&&this.regexp.test(a)){for(e=this.regexp.exec(a),b=0;b<this.expressions.length;b+=1)c=this.expressions[b],void 0===c.literal&&(void 0!==c.operator&&0===c.operator.symbol.length&&1===c.varspecs.length?(d=c.varspecs[0],d.exploded===!1&&null===d.maxLength&&-1===e[f].indexOf(",")?(h[d.varname]=decodeURIComponent(e[f]),f+=1):g=!1):g=!1);if(g)return h}return!1},a.parse=k,a.UriTemplateError=c,a}();a(m)}(function(a){"use strict";"undefined"!=typeof module?module.exports=a:"function"==typeof define?define([],function(){return a}):"undefined"!=typeof window?window.UriTemplate=a:global.UriTemplate=a});var LZString=function(){function a(a,b){if(!e[a]){e[a]={};for(var c=0;c<a.length;c++)e[a][a.charAt(c)]=c}return e[a][b]}var b=String.fromCharCode,c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",e={},f={compressToBase64:function(a){if(null==a)return"";var b=f._compress(a,6,function(a){return c.charAt(a)});switch(b.length%4){default:case 0:return b;case 1:return b+"===";case 2:return b+"==";case 3:return b+"="}},decompressFromBase64:function(b){return null==b?"":""==b?null:f._decompress(b.length,32,function(d){return a(c,b.charAt(d))})},compressToUTF16:function(a){return null==a?"":f._compress(a,15,function(a){return b(a+32)})+" "},decompressFromUTF16:function(a){return null==a?"":""==a?null:f._decompress(a.length,16384,function(b){return a.charCodeAt(b)-32})},compressToUint8Array:function(a){for(var b=f.compress(a),c=new Uint8Array(2*b.length),d=0,e=b.length;e>d;d++){var g=b.charCodeAt(d);c[2*d]=g>>>8,c[2*d+1]=g%256}return c},decompressFromUint8Array:function(a){if(null===a||void 0===a)return f.decompress(a);for(var c=new Array(a.length/2),d=0,e=c.length;e>d;d++)c[d]=256*a[2*d]+a[2*d+1];var g=[];return c.forEach(function(a){g.push(b(a))}),f.decompress(g.join(""))},compressToEncodedURIComponent:function(a){return null==a?"":f._compress(a,6,function(a){return d.charAt(a)})},decompressFromEncodedURIComponent:function(b){return null==b?"":""==b?null:(b=b.replace(/ /g,"+"),f._decompress(b.length,32,function(c){return a(d,b.charAt(c))}))},compress:function(a){return f._compress(a,16,function(a){return b(a)})},_compress:function(a,b,c){if(null==a)return"";var d,e,f,g={},h={},i="",j="",k="",l=2,m=3,n=2,o=[],p=0,q=0;for(f=0;f<a.length;f+=1)if(i=a.charAt(f),Object.prototype.hasOwnProperty.call(g,i)||(g[i]=m++,h[i]=!0),j=k+i,Object.prototype.hasOwnProperty.call(g,j))k=j;else{if(Object.prototype.hasOwnProperty.call(h,k)){if(k.charCodeAt(0)<256){for(d=0;n>d;d++)p<<=1,q==b-1?(q=0,o.push(c(p)),p=0):q++;for(e=k.charCodeAt(0),d=0;8>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}else{for(e=1,d=0;n>d;d++)p=p<<1|e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e=0;for(e=k.charCodeAt(0),d=0;16>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}l--,0==l&&(l=Math.pow(2,n),n++),delete h[k]}else for(e=g[k],d=0;n>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1;l--,0==l&&(l=Math.pow(2,n),n++),g[j]=m++,k=String(i)}if(""!==k){if(Object.prototype.hasOwnProperty.call(h,k)){if(k.charCodeAt(0)<256){for(d=0;n>d;d++)p<<=1,q==b-1?(q=0,o.push(c(p)),p=0):q++;for(e=k.charCodeAt(0),d=0;8>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}else{for(e=1,d=0;n>d;d++)p=p<<1|e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e=0;for(e=k.charCodeAt(0),d=0;16>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}l--,0==l&&(l=Math.pow(2,n),n++),delete h[k]}else for(e=g[k],d=0;n>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1;l--,0==l&&(l=Math.pow(2,n),n++)}for(e=2,d=0;n>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1;for(;;){if(p<<=1,q==b-1){o.push(c(p));break}q++}return o.join("")},decompress:function(a){return null==a?"":""==a?null:f._decompress(a.length,32768,function(b){return a.charCodeAt(b)})},_decompress:function(a,c,d){var e,f,g,h,i,j,k,l,m=[],n=4,o=4,p=3,q="",r=[],s={val:d(0),position:c,index:1};for(f=0;3>f;f+=1)m[f]=f;for(h=0,j=Math.pow(2,2),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;switch(e=h){case 0:for(h=0,j=Math.pow(2,8),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;l=b(h);break;case 1:for(h=0,j=Math.pow(2,16),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;l=b(h);break;case 2:return""}for(m[3]=l,g=l,r.push(l);;){if(s.index>a)return"";for(h=0,j=Math.pow(2,p),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;switch(l=h){case 0:for(h=0,j=Math.pow(2,8),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;m[o++]=b(h),l=o-1,n--;break;case 1:for(h=0,j=Math.pow(2,16),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;m[o++]=b(h),l=o-1,n--;break;case 2:return r.join("")}if(0==n&&(n=Math.pow(2,p),p++),m[l])q=m[l];else{if(l!==o)return null;q=g+g.charAt(0)}r.push(q),m[o++]=g+q.charAt(0),n--,g=q,0==n&&(n=Math.pow(2,p),p++)}}};return f}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module&&(module.exports=LZString),function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return fd.apply(null,arguments)}function b(a){fd=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a);
+}function e(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function f(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function g(a,b){for(var c in b)f(b,c)&&(a[c]=b[c]);return f(b,"toString")&&(a.toString=b.toString),f(b,"valueOf")&&(a.valueOf=b.valueOf),a}function h(a,b,c,d){return Ja(a,b,c,d,!0).utc()}function i(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function j(a){return null==a._pf&&(a._pf=i()),a._pf}function k(a){if(null==a._isValid){var b=j(a),c=gd.call(b.parsedDateParts,function(a){return null!=a});a._isValid=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c),a._strict&&(a._isValid=a._isValid&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour)}return a._isValid}function l(a){var b=h(NaN);return null!=a?g(j(b),a):j(b).userInvalidated=!0,b}function m(a){return void 0===a}function n(a,b){var c,d,e;if(m(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),m(b._i)||(a._i=b._i),m(b._f)||(a._f=b._f),m(b._l)||(a._l=b._l),m(b._strict)||(a._strict=b._strict),m(b._tzm)||(a._tzm=b._tzm),m(b._isUTC)||(a._isUTC=b._isUTC),m(b._offset)||(a._offset=b._offset),m(b._pf)||(a._pf=j(b)),m(b._locale)||(a._locale=b._locale),hd.length>0)for(c in hd)d=hd[c],e=b[d],m(e)||(a[d]=e);return a}function o(b){n(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),id===!1&&(id=!0,a.updateOffset(this),id=!1)}function p(a){return a instanceof o||null!=a&&null!=a._isAMomentObject}function q(a){return 0>a?Math.ceil(a):Math.floor(a)}function r(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=q(b)),c}function s(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&r(a[d])!==r(b[d]))&&g++;return g+f}function t(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function u(b,c){var d=!0;return g(function(){return null!=a.deprecationHandler&&a.deprecationHandler(null,b),d&&(t(b+"\nArguments: "+Array.prototype.slice.call(arguments).join(", ")+"\n"+(new Error).stack),d=!1),c.apply(this,arguments)},c)}function v(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),jd[b]||(t(c),jd[b]=!0)}function w(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function x(a){return"[object Object]"===Object.prototype.toString.call(a)}function y(a){var b,c;for(c in a)b=a[c],w(b)?this[c]=b:this["_"+c]=b;this._config=a,this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function z(a,b){var c,d=g({},a);for(c in b)f(b,c)&&(x(a[c])&&x(b[c])?(d[c]={},g(d[c],a[c]),g(d[c],b[c])):null!=b[c]?d[c]=b[c]:delete d[c]);return d}function A(a){null!=a&&this.set(a)}function B(a){return a?a.toLowerCase().replace("_","-"):a}function C(a){for(var b,c,d,e,f=0;f<a.length;){for(e=B(a[f]).split("-"),b=e.length,c=B(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=D(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&s(e,c,!0)>=b-1)break;b--}f++}return null}function D(a){var b=null;if(!nd[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=ld._abbr,require("./locale/"+a),E(b)}catch(c){}return nd[a]}function E(a,b){var c;return a&&(c=m(b)?H(a):F(a,b),c&&(ld=c)),ld._abbr}function F(a,b){return null!==b?(b.abbr=a,null!=nd[a]?(v("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale"),b=z(nd[a]._config,b)):null!=b.parentLocale&&(null!=nd[b.parentLocale]?b=z(nd[b.parentLocale]._config,b):v("parentLocaleUndefined","specified parentLocale is not defined yet")),nd[a]=new A(b),E(a),nd[a]):(delete nd[a],null)}function G(a,b){if(null!=b){var c;null!=nd[a]&&(b=z(nd[a]._config,b)),c=new A(b),c.parentLocale=nd[a],nd[a]=c,E(a)}else null!=nd[a]&&(null!=nd[a].parentLocale?nd[a]=nd[a].parentLocale:null!=nd[a]&&delete nd[a]);return nd[a]}function H(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return ld;if(!c(a)){if(b=D(a))return b;a=[a]}return C(a)}function I(){return kd(nd)}function J(a,b){var c=a.toLowerCase();od[c]=od[c+"s"]=od[b]=a}function K(a){return"string"==typeof a?od[a]||od[a.toLowerCase()]:void 0}function L(a){var b,c,d={};for(c in a)f(a,c)&&(b=K(c),b&&(d[b]=a[c]));return d}function M(b,c){return function(d){return null!=d?(O(this,b,d),a.updateOffset(this,c),this):N(this,b)}}function N(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function O(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)}function P(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=K(a),w(this[a]))return this[a](b);return this}function Q(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function R(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(sd[a]=e),b&&(sd[b[0]]=function(){return Q(e.apply(this,arguments),b[1],b[2])}),c&&(sd[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function S(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function T(a){var b,c,d=a.match(pd);for(b=0,c=d.length;c>b;b++)sd[d[b]]?d[b]=sd[d[b]]:d[b]=S(d[b]);return function(b){var e,f="";for(e=0;c>e;e++)f+=d[e]instanceof Function?d[e].call(b,a):d[e];return f}}function U(a,b){return a.isValid()?(b=V(b,a.localeData()),rd[b]=rd[b]||T(b),rd[b](a)):a.localeData().invalidDate()}function V(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(qd.lastIndex=0;d>=0&&qd.test(a);)a=a.replace(qd,c),qd.lastIndex=0,d-=1;return a}function W(a,b,c){Kd[a]=w(b)?b:function(a,d){return a&&c?c:b}}function X(a,b){return f(Kd,a)?Kd[a](b._strict,b._locale):new RegExp(Y(a))}function Y(a){return Z(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function Z(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function $(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=r(a)}),c=0;c<a.length;c++)Ld[a[c]]=d}function _(a,b){$(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function aa(a,b,c){null!=b&&f(Ld,a)&&Ld[a](b,c._a,c,a)}function ba(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function ca(a,b){return c(this._months)?this._months[a.month()]:this._months[Vd.test(b)?"format":"standalone"][a.month()]}function da(a,b){return c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[Vd.test(b)?"format":"standalone"][a.month()]}function ea(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],d=0;12>d;++d)f=h([2e3,d]),this._shortMonthsParse[d]=this.monthsShort(f,"").toLocaleLowerCase(),this._longMonthsParse[d]=this.months(f,"").toLocaleLowerCase();return c?"MMM"===b?(e=md.call(this._shortMonthsParse,g),-1!==e?e:null):(e=md.call(this._longMonthsParse,g),-1!==e?e:null):"MMM"===b?(e=md.call(this._shortMonthsParse,g),-1!==e?e:(e=md.call(this._longMonthsParse,g),-1!==e?e:null)):(e=md.call(this._longMonthsParse,g),-1!==e?e:(e=md.call(this._shortMonthsParse,g),-1!==e?e:null))}function fa(a,b,c){var d,e,f;if(this._monthsParseExact)return ea.call(this,a,b,c);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function ga(a,b){var c;if(!a.isValid())return a;if("string"==typeof b)if(/^\d+$/.test(b))b=r(b);else if(b=a.localeData().monthsParse(b),"number"!=typeof b)return a;return c=Math.min(a.date(),ba(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ha(b){return null!=b?(ga(this,b),a.updateOffset(this,!0),this):N(this,"Month")}function ia(){return ba(this.year(),this.month())}function ja(a){return this._monthsParseExact?(f(this,"_monthsRegex")||la.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex}function ka(a){return this._monthsParseExact?(f(this,"_monthsRegex")||la.call(this),a?this._monthsStrictRegex:this._monthsRegex):this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex}function la(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;12>b;b++)c=h([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for(d.sort(a),e.sort(a),f.sort(a),b=0;12>b;b++)d[b]=Z(d[b]),e[b]=Z(e[b]),f[b]=Z(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")","i")}function ma(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[Nd]<0||c[Nd]>11?Nd:c[Od]<1||c[Od]>ba(c[Md],c[Nd])?Od:c[Pd]<0||c[Pd]>24||24===c[Pd]&&(0!==c[Qd]||0!==c[Rd]||0!==c[Sd])?Pd:c[Qd]<0||c[Qd]>59?Qd:c[Rd]<0||c[Rd]>59?Rd:c[Sd]<0||c[Sd]>999?Sd:-1,j(a)._overflowDayOfYear&&(Md>b||b>Od)&&(b=Od),j(a)._overflowWeeks&&-1===b&&(b=Td),j(a)._overflowWeekday&&-1===b&&(b=Ud),j(a).overflow=b),a}function na(a){var b,c,d,e,f,g,h=a._i,i=$d.exec(h)||_d.exec(h);if(i){for(j(a).iso=!0,b=0,c=be.length;c>b;b++)if(be[b][1].exec(i[1])){e=be[b][0],d=be[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=ce.length;c>b;b++)if(ce[b][1].exec(i[3])){f=(i[2]||" ")+ce[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!ae.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),Ca(a)}else a._isValid=!1}function oa(b){var c=de.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(na(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function pa(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 100>a&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function qa(a){var b=new Date(Date.UTC.apply(null,arguments));return 100>a&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b}function ra(a){return sa(a)?366:365}function sa(a){return a%4===0&&a%100!==0||a%400===0}function ta(){return sa(this.year())}function ua(a,b,c){var d=7+b-c,e=(7+qa(a,0,d).getUTCDay()-b)%7;return-e+d-1}function va(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ua(a,d,e),j=1+7*(b-1)+h+i;return 0>=j?(f=a-1,g=ra(f)+j):j>ra(a)?(f=a+1,g=j-ra(a)):(f=a,g=j),{year:f,dayOfYear:g}}function wa(a,b,c){var d,e,f=ua(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return 1>g?(e=a.year()-1,d=g+xa(e,b,c)):g>xa(a.year(),b,c)?(d=g-xa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function xa(a,b,c){var d=ua(a,b,c),e=ua(a+1,b,c);return(ra(a)-d+e)/7}function ya(a,b,c){return null!=a?a:null!=b?b:c}function za(b){var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]}function Aa(a){var b,c,d,e,f=[];if(!a._d){for(d=za(a),a._w&&null==a._a[Od]&&null==a._a[Nd]&&Ba(a),a._dayOfYear&&(e=ya(a._a[Md],d[Md]),a._dayOfYear>ra(e)&&(j(a)._overflowDayOfYear=!0),c=qa(e,0,a._dayOfYear),a._a[Nd]=c.getUTCMonth(),a._a[Od]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[Pd]&&0===a._a[Qd]&&0===a._a[Rd]&&0===a._a[Sd]&&(a._nextDay=!0,a._a[Pd]=0),a._d=(a._useUTC?qa:pa).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[Pd]=24)}}function Ba(a){var b,c,d,e,f,g,h,i;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=ya(b.GG,a._a[Md],wa(Ka(),1,4).year),d=ya(b.W,1),e=ya(b.E,1),(1>e||e>7)&&(i=!0)):(f=a._locale._week.dow,g=a._locale._week.doy,c=ya(b.gg,a._a[Md],wa(Ka(),f,g).year),d=ya(b.w,1),null!=b.d?(e=b.d,(0>e||e>6)&&(i=!0)):null!=b.e?(e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):e=f),1>d||d>xa(c,f,g)?j(a)._overflowWeeks=!0:null!=i?j(a)._overflowWeekday=!0:(h=va(c,d,e,f,g),a._a[Md]=h.year,a._dayOfYear=h.dayOfYear)}function Ca(b){if(b._f===a.ISO_8601)return void na(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=V(b._f,b._locale).match(pd)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(X(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),sd[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),aa(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[Pd]<=12&&b._a[Pd]>0&&(j(b).bigHour=void 0),j(b).parsedDateParts=b._a.slice(0),j(b).meridiem=b._meridiem,b._a[Pd]=Da(b._locale,b._a[Pd],b._meridiem),Aa(b),ma(b)}function Da(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function Ea(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=n({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],Ca(b),k(b)&&(f+=j(b).charsLeftOver,f+=10*j(b).unusedTokens.length,j(b).score=f,(null==d||d>f)&&(d=f,c=b));g(a,c||b)}function Fa(a){if(!a._d){var b=L(a._i);a._a=e([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),Aa(a)}}function Ga(a){var b=new o(ma(Ha(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function Ha(a){var b=a._i,e=a._f;return a._locale=a._locale||H(a._l),null===b||void 0===e&&""===b?l({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),p(b)?new o(ma(b)):(c(e)?Ea(a):e?Ca(a):d(b)?a._d=b:Ia(a),k(a)||(a._d=null),a))}function Ia(b){var f=b._i;void 0===f?b._d=new Date(a.now()):d(f)?b._d=new Date(f.valueOf()):"string"==typeof f?oa(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),Aa(b)):"object"==typeof f?Fa(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function Ja(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,Ga(f)}function Ka(a,b,c,d){return Ja(a,b,c,d,!1)}function La(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Ka();for(d=b[0],e=1;e<b.length;++e)(!b[e].isValid()||b[e][a](d))&&(d=b[e]);return d}function Ma(){var a=[].slice.call(arguments,0);return La("isBefore",a)}function Na(){var a=[].slice.call(arguments,0);return La("isAfter",a)}function Oa(a){var b=L(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+1e3*h*60*60,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=H(),this._bubble()}function Pa(a){return a instanceof Oa}function Qa(a,b){R(a,0,0,function(){var a=this.utcOffset(),c="+";return 0>a&&(a=-a,c="-"),c+Q(~~(a/60),2)+b+Q(~~a%60,2)})}function Ra(a,b){var c=(b||"").match(a)||[],d=c[c.length-1]||[],e=(d+"").match(ie)||["-",0,0],f=+(60*e[1])+r(e[2]);return"+"===e[0]?f:-f}function Sa(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(p(b)||d(b)?b.valueOf():Ka(b).valueOf())-e.valueOf(),e._d.setTime(e._d.valueOf()+f),a.updateOffset(e,!1),e):Ka(b).local()}function Ta(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Ua(b,c){var d,e=this._offset||0;return this.isValid()?null!=b?("string"==typeof b?b=Ra(Hd,b):Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ta(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?jb(this,db(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ta(this):null!=b?this:NaN}function Va(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Wa(a){return this.utcOffset(0,a)}function Xa(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ta(this),"m")),this}function Ya(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ra(Gd,this._i)),this}function Za(a){return this.isValid()?(a=a?Ka(a).utcOffset():0,(this.utcOffset()-a)%60===0):!1}function $a(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function _a(){if(!m(this._isDSTShifted))return this._isDSTShifted;var a={};if(n(a,this),a=Ha(a),a._a){var b=a._isUTC?h(a._a):Ka(a._a);this._isDSTShifted=this.isValid()&&s(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function ab(){return this.isValid()?!this._isUTC:!1}function bb(){return this.isValid()?this._isUTC:!1}function cb(){return this.isValid()?this._isUTC&&0===this._offset:!1}function db(a,b){var c,d,e,g=a,h=null;return Pa(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=je.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:r(h[Od])*c,h:r(h[Pd])*c,m:r(h[Qd])*c,s:r(h[Rd])*c,ms:r(h[Sd])*c}):(h=ke.exec(a))?(c="-"===h[1]?-1:1,g={y:eb(h[2],c),M:eb(h[3],c),w:eb(h[4],c),d:eb(h[5],c),h:eb(h[6],c),m:eb(h[7],c),s:eb(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=gb(Ka(g.from),Ka(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Oa(g),Pa(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function eb(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function fb(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function gb(a,b){var c;return a.isValid()&&b.isValid()?(b=Sa(b,a),a.isBefore(b)?c=fb(a,b):(c=fb(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}function hb(a){return 0>a?-1*Math.round(-1*a):Math.round(a)}function ib(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(v(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=db(c,d),jb(this,e,a),this}}function jb(b,c,d,e){var f=c._milliseconds,g=hb(c._days),h=hb(c._months);b.isValid()&&(e=null==e?!0:e,f&&b._d.setTime(b._d.valueOf()+f*d),g&&O(b,"Date",N(b,"Date")+g*d),h&&ga(b,N(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function kb(a,b){var c=a||Ka(),d=Sa(c,this).startOf("day"),e=this.diff(d,"days",!0),f=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse",g=b&&(w(b[f])?b[f]():b[f]);return this.format(g||this.localeData().calendar(f,this,Ka(c)))}function lb(){return new o(this)}function mb(a,b){var c=p(a)?a:Ka(a);return this.isValid()&&c.isValid()?(b=K(m(b)?"millisecond":b),"millisecond"===b?this.valueOf()>c.valueOf():c.valueOf()<this.clone().startOf(b).valueOf()):!1}function nb(a,b){var c=p(a)?a:Ka(a);return this.isValid()&&c.isValid()?(b=K(m(b)?"millisecond":b),"millisecond"===b?this.valueOf()<c.valueOf():this.clone().endOf(b).valueOf()<c.valueOf()):!1}function ob(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!this.isBefore(a,c))&&(")"===d[1]?this.isBefore(b,c):!this.isAfter(b,c))}function pb(a,b){var c,d=p(a)?a:Ka(a);return this.isValid()&&d.isValid()?(b=K(b||"millisecond"),"millisecond"===b?this.valueOf()===d.valueOf():(c=d.valueOf(),this.clone().startOf(b).valueOf()<=c&&c<=this.clone().endOf(b).valueOf())):!1}function qb(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function rb(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function sb(a,b,c){var d,e,f,g;return this.isValid()?(d=Sa(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=K(b),"year"===b||"month"===b||"quarter"===b?(g=tb(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:q(g)):NaN):NaN}function tb(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)||0}function ub(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function vb(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?w(Date.prototype.toISOString)?this.toDate().toISOString():U(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):U(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function wb(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var c=U(this,b);return this.localeData().postformat(c)}function xb(a,b){return this.isValid()&&(p(a)&&a.isValid()||Ka(a).isValid())?db({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function yb(a){return this.from(Ka(),a)}function zb(a,b){return this.isValid()&&(p(a)&&a.isValid()||Ka(a).isValid())?db({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function Ab(a){return this.to(Ka(),a)}function Bb(a){var b;return void 0===a?this._locale._abbr:(b=H(a),null!=b&&(this._locale=b),this)}function Cb(){return this._locale}function Db(a){switch(a=K(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function Eb(a){return a=K(a),void 0===a||"millisecond"===a?this:("date"===a&&(a="day"),this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms"))}function Fb(){return this._d.valueOf()-6e4*(this._offset||0)}function Gb(){return Math.floor(this.valueOf()/1e3)}function Hb(){return this._offset?new Date(this.valueOf()):this._d}function Ib(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function Jb(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function Kb(){return this.isValid()?this.toISOString():null}function Lb(){return k(this)}function Mb(){return g({},j(this))}function Nb(){return j(this).overflow}function Ob(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Pb(a,b){R(0,[a,a.length],0,b)}function Qb(a){return Ub.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function Rb(a){return Ub.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Sb(){return xa(this.year(),1,4)}function Tb(){var a=this.localeData()._week;return xa(this.year(),a.dow,a.doy)}function Ub(a,b,c,d,e){var f;return null==a?wa(this,d,e).year:(f=xa(a,d,e),b>f&&(b=f),Vb.call(this,a,b,c,d,e))}function Vb(a,b,c,d,e){var f=va(a,b,c,d,e),g=qa(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this}function Wb(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}function Xb(a){return wa(a,this._week.dow,this._week.doy).week}function Yb(){return this._week.dow}function Zb(){return this._week.doy}function $b(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function _b(a){var b=wa(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function ac(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function bc(a,b){return c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]}function cc(a){return this._weekdaysShort[a.day()]}function dc(a){return this._weekdaysMin[a.day()]}function ec(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],d=0;7>d;++d)f=h([2e3,1]).day(d),this._minWeekdaysParse[d]=this.weekdaysMin(f,"").toLocaleLowerCase(),this._shortWeekdaysParse[d]=this.weekdaysShort(f,"").toLocaleLowerCase(),this._weekdaysParse[d]=this.weekdays(f,"").toLocaleLowerCase();return c?"dddd"===b?(e=md.call(this._weekdaysParse,g),-1!==e?e:null):"ddd"===b?(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:null):(e=md.call(this._minWeekdaysParse,g),-1!==e?e:null):"dddd"===b?(e=md.call(this._weekdaysParse,g),-1!==e?e:(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:(e=md.call(this._minWeekdaysParse,g),-1!==e?e:null))):"ddd"===b?(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:(e=md.call(this._weekdaysParse,g),-1!==e?e:(e=md.call(this._minWeekdaysParse,g),-1!==e?e:null))):(e=md.call(this._minWeekdaysParse,g),-1!==e?e:(e=md.call(this._weekdaysParse,g),-1!==e?e:(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:null)))}function fc(a,b,c){var d,e,f;if(this._weekdaysParseExact)return ec.call(this,a,b,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;7>d;d++){if(e=h([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}}function gc(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=ac(a,this.localeData()),this.add(a-b,"d")):b}function hc(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function ic(a){return this.isValid()?null==a?this.day()||7:this.day(this.day()%7?a:a-7):null!=a?this:NaN}function jc(a){return this._weekdaysParseExact?(f(this,"_weekdaysRegex")||mc.call(this),a?this._weekdaysStrictRegex:this._weekdaysRegex):this._weekdaysStrictRegex&&a?this._weekdaysStrictRegex:this._weekdaysRegex}function kc(a){return this._weekdaysParseExact?(f(this,"_weekdaysRegex")||mc.call(this),a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):this._weekdaysShortStrictRegex&&a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex}function lc(a){return this._weekdaysParseExact?(f(this,"_weekdaysRegex")||mc.call(this),a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):this._weekdaysMinStrictRegex&&a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex}function mc(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[],i=[],j=[],k=[];for(b=0;7>b;b++)c=h([2e3,1]).day(b),d=this.weekdaysMin(c,""),e=this.weekdaysShort(c,""),f=this.weekdays(c,""),g.push(d),i.push(e),j.push(f),k.push(d),k.push(e),k.push(f);for(g.sort(a),i.sort(a),j.sort(a),k.sort(a),b=0;7>b;b++)i[b]=Z(i[b]),j[b]=Z(j[b]),k[b]=Z(k[b]);this._weekdaysRegex=new RegExp("^("+k.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+j.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+g.join("|")+")","i")}function nc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function oc(){return this.hours()%12||12}function pc(){return this.hours()||24}function qc(a,b){R(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function rc(a,b){return b._meridiemParse}function sc(a){return"p"===(a+"").toLowerCase().charAt(0)}function tc(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function uc(a,b){b[Sd]=r(1e3*("0."+a))}function vc(){return this._isUTC?"UTC":""}function wc(){return this._isUTC?"Coordinated Universal Time":""}function xc(a){return Ka(1e3*a)}function yc(){return Ka.apply(null,arguments).parseZone()}function zc(a,b,c){var d=this._calendar[a];return w(d)?d.call(b,c):d}function Ac(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function Bc(){return this._invalidDate}function Cc(a){return this._ordinal.replace("%d",a)}function Dc(a){return a}function Ec(a,b,c,d){var e=this._relativeTime[c];return w(e)?e(a,b,c,d):e.replace(/%d/i,a)}function Fc(a,b){var c=this._relativeTime[a>0?"future":"past"];return w(c)?c(b):c.replace(/%s/i,b)}function Gc(a,b,c,d){var e=H(),f=h().set(d,b);return e[c](f,a)}function Hc(a,b,c){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return Gc(a,b,c,"month");var d,e=[];for(d=0;12>d;d++)e[d]=Gc(a,d,c,"month");return e}function Ic(a,b,c,d){"boolean"==typeof a?("number"==typeof b&&(c=b,b=void 0),b=b||""):(b=a,c=b,a=!1,"number"==typeof b&&(c=b,b=void 0),b=b||"");var e=H(),f=a?e._week.dow:0;if(null!=c)return Gc(b,(c+f)%7,d,"day");var g,h=[];for(g=0;7>g;g++)h[g]=Gc(b,(g+f)%7,d,"day");return h}function Jc(a,b){return Hc(a,b,"months")}function Kc(a,b){return Hc(a,b,"monthsShort")}function Lc(a,b,c){return Ic(a,b,c,"weekdays")}function Mc(a,b,c){return Ic(a,b,c,"weekdaysShort")}function Nc(a,b,c){return Ic(a,b,c,"weekdaysMin")}function Oc(){var a=this._data;return this._milliseconds=Le(this._milliseconds),this._days=Le(this._days),this._months=Le(this._months),a.milliseconds=Le(a.milliseconds),a.seconds=Le(a.seconds),a.minutes=Le(a.minutes),a.hours=Le(a.hours),a.months=Le(a.months),a.years=Le(a.years),this}function Pc(a,b,c,d){var e=db(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function Qc(a,b){return Pc(this,a,b,1)}function Rc(a,b){return Pc(this,a,b,-1)}function Sc(a){return 0>a?Math.floor(a):Math.ceil(a)}function Tc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*Sc(Vc(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=q(f/1e3),i.seconds=a%60,b=q(a/60),i.minutes=b%60,c=q(b/60),i.hours=c%24,g+=q(c/24),e=q(Uc(g)),h+=e,g-=Sc(Vc(e)),d=q(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function Uc(a){return 4800*a/146097}function Vc(a){return 146097*a/4800}function Wc(a){var b,c,d=this._milliseconds;if(a=K(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+Uc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(Vc(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function Xc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*r(this._months/12)}function Yc(a){return function(){return this.as(a)}}function Zc(a){return a=K(a),this[a+"s"]()}function $c(a){return function(){return this._data[a]}}function _c(){return q(this.days()/7)}function ad(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function bd(a,b,c){var d=db(a).abs(),e=_e(d.as("s")),f=_e(d.as("m")),g=_e(d.as("h")),h=_e(d.as("d")),i=_e(d.as("M")),j=_e(d.as("y")),k=e<af.s&&["s",e]||1>=f&&["m"]||f<af.m&&["mm",f]||1>=g&&["h"]||g<af.h&&["hh",g]||1>=h&&["d"]||h<af.d&&["dd",h]||1>=i&&["M"]||i<af.M&&["MM",i]||1>=j&&["y"]||["yy",j];
+return k[2]=b,k[3]=+a>0,k[4]=c,ad.apply(null,k)}function cd(a,b){return void 0===af[a]?!1:void 0===b?af[a]:(af[a]=b,!0)}function dd(a){var b=this.localeData(),c=bd(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function ed(){var a,b,c,d=bf(this._milliseconds)/1e3,e=bf(this._days),f=bf(this._months);a=q(d/60),b=q(a/60),d%=60,a%=60,c=q(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var fd,gd;gd=Array.prototype.some?Array.prototype.some:function(a){for(var b=Object(this),c=b.length>>>0,d=0;c>d;d++)if(d in b&&a.call(this,b[d],d,b))return!0;return!1};var hd=a.momentProperties=[],id=!1,jd={};a.suppressDeprecationWarnings=!1,a.deprecationHandler=null;var kd;kd=Object.keys?Object.keys:function(a){var b,c=[];for(b in a)f(a,b)&&c.push(b);return c};var ld,md,nd={},od={},pd=/(\[[^\[]*\])|(\\)?([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,qd=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,rd={},sd={},td=/\d/,ud=/\d\d/,vd=/\d{3}/,wd=/\d{4}/,xd=/[+-]?\d{6}/,yd=/\d\d?/,zd=/\d\d\d\d?/,Ad=/\d\d\d\d\d\d?/,Bd=/\d{1,3}/,Cd=/\d{1,4}/,Dd=/[+-]?\d{1,6}/,Ed=/\d+/,Fd=/[+-]?\d+/,Gd=/Z|[+-]\d\d:?\d\d/gi,Hd=/Z|[+-]\d\d(?::?\d\d)?/gi,Id=/[+-]?\d+(\.\d{1,3})?/,Jd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Kd={},Ld={},Md=0,Nd=1,Od=2,Pd=3,Qd=4,Rd=5,Sd=6,Td=7,Ud=8;md=Array.prototype.indexOf?Array.prototype.indexOf:function(a){var b;for(b=0;b<this.length;++b)if(this[b]===a)return b;return-1},R("M",["MM",2],"Mo",function(){return this.month()+1}),R("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),R("MMMM",0,0,function(a){return this.localeData().months(this,a)}),J("month","M"),W("M",yd),W("MM",yd,ud),W("MMM",function(a,b){return b.monthsShortRegex(a)}),W("MMMM",function(a,b){return b.monthsRegex(a)}),$(["M","MM"],function(a,b){b[Nd]=r(a)-1}),$(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[Nd]=e:j(c).invalidMonth=a});var Vd=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/,Wd="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Xd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),Yd=Jd,Zd=Jd,$d=/^\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)?)?/,_d=/^\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)?)?/,ae=/Z|[+-]\d\d(?::?\d\d)?/,be=[["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/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],ce=[["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/]],de=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=u("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),R("Y",0,0,function(){var a=this.year();return 9999>=a?""+a:"+"+a}),R(0,["YY",2],0,function(){return this.year()%100}),R(0,["YYYY",4],0,"year"),R(0,["YYYYY",5],0,"year"),R(0,["YYYYYY",6,!0],0,"year"),J("year","y"),W("Y",Fd),W("YY",yd,ud),W("YYYY",Cd,wd),W("YYYYY",Dd,xd),W("YYYYYY",Dd,xd),$(["YYYYY","YYYYYY"],Md),$("YYYY",function(b,c){c[Md]=2===b.length?a.parseTwoDigitYear(b):r(b)}),$("YY",function(b,c){c[Md]=a.parseTwoDigitYear(b)}),$("Y",function(a,b){b[Md]=parseInt(a,10)}),a.parseTwoDigitYear=function(a){return r(a)+(r(a)>68?1900:2e3)};var ee=M("FullYear",!0);a.ISO_8601=function(){};var fe=u("moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Ka.apply(null,arguments);return this.isValid()&&a.isValid()?this>a?this:a:l()}),ge=u("moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Ka.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:l()}),he=function(){return Date.now?Date.now():+new Date};Qa("Z",":"),Qa("ZZ",""),W("Z",Hd),W("ZZ",Hd),$(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ra(Hd,a)});var ie=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var je=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/,ke=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;db.fn=Oa.prototype;var le=ib(1,"add"),me=ib(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var ne=u("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});R(0,["gg",2],0,function(){return this.weekYear()%100}),R(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Pb("gggg","weekYear"),Pb("ggggg","weekYear"),Pb("GGGG","isoWeekYear"),Pb("GGGGG","isoWeekYear"),J("weekYear","gg"),J("isoWeekYear","GG"),W("G",Fd),W("g",Fd),W("GG",yd,ud),W("gg",yd,ud),W("GGGG",Cd,wd),W("gggg",Cd,wd),W("GGGGG",Dd,xd),W("ggggg",Dd,xd),_(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=r(a)}),_(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),R("Q",0,"Qo","quarter"),J("quarter","Q"),W("Q",td),$("Q",function(a,b){b[Nd]=3*(r(a)-1)}),R("w",["ww",2],"wo","week"),R("W",["WW",2],"Wo","isoWeek"),J("week","w"),J("isoWeek","W"),W("w",yd),W("ww",yd,ud),W("W",yd),W("WW",yd,ud),_(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=r(a)});var oe={dow:0,doy:6};R("D",["DD",2],"Do","date"),J("date","D"),W("D",yd),W("DD",yd,ud),W("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),$(["D","DD"],Od),$("Do",function(a,b){b[Od]=r(a.match(yd)[0],10)});var pe=M("Date",!0);R("d",0,"do","day"),R("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),R("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),R("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),R("e",0,0,"weekday"),R("E",0,0,"isoWeekday"),J("day","d"),J("weekday","e"),J("isoWeekday","E"),W("d",yd),W("e",yd),W("E",yd),W("dd",function(a,b){return b.weekdaysMinRegex(a)}),W("ddd",function(a,b){return b.weekdaysShortRegex(a)}),W("dddd",function(a,b){return b.weekdaysRegex(a)}),_(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict);null!=e?b.d=e:j(c).invalidWeekday=a}),_(["d","e","E"],function(a,b,c,d){b[d]=r(a)});var qe="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),re="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),se="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),te=Jd,ue=Jd,ve=Jd;R("DDD",["DDDD",3],"DDDo","dayOfYear"),J("dayOfYear","DDD"),W("DDD",Bd),W("DDDD",vd),$(["DDD","DDDD"],function(a,b,c){c._dayOfYear=r(a)}),R("H",["HH",2],0,"hour"),R("h",["hh",2],0,oc),R("k",["kk",2],0,pc),R("hmm",0,0,function(){return""+oc.apply(this)+Q(this.minutes(),2)}),R("hmmss",0,0,function(){return""+oc.apply(this)+Q(this.minutes(),2)+Q(this.seconds(),2)}),R("Hmm",0,0,function(){return""+this.hours()+Q(this.minutes(),2)}),R("Hmmss",0,0,function(){return""+this.hours()+Q(this.minutes(),2)+Q(this.seconds(),2)}),qc("a",!0),qc("A",!1),J("hour","h"),W("a",rc),W("A",rc),W("H",yd),W("h",yd),W("HH",yd,ud),W("hh",yd,ud),W("hmm",zd),W("hmmss",Ad),W("Hmm",zd),W("Hmmss",Ad),$(["H","HH"],Pd),$(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),$(["h","hh"],function(a,b,c){b[Pd]=r(a),j(c).bigHour=!0}),$("hmm",function(a,b,c){var d=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d)),j(c).bigHour=!0}),$("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d,2)),b[Rd]=r(a.substr(e)),j(c).bigHour=!0}),$("Hmm",function(a,b,c){var d=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d))}),$("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d,2)),b[Rd]=r(a.substr(e))});var we=/[ap]\.?m?\.?/i,xe=M("Hours",!0);R("m",["mm",2],0,"minute"),J("minute","m"),W("m",yd),W("mm",yd,ud),$(["m","mm"],Qd);var ye=M("Minutes",!1);R("s",["ss",2],0,"second"),J("second","s"),W("s",yd),W("ss",yd,ud),$(["s","ss"],Rd);var ze=M("Seconds",!1);R("S",0,0,function(){return~~(this.millisecond()/100)}),R(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),R(0,["SSS",3],0,"millisecond"),R(0,["SSSS",4],0,function(){return 10*this.millisecond()}),R(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),R(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),R(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),R(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),R(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),J("millisecond","ms"),W("S",Bd,td),W("SS",Bd,ud),W("SSS",Bd,vd);var Ae;for(Ae="SSSS";Ae.length<=9;Ae+="S")W(Ae,Ed);for(Ae="S";Ae.length<=9;Ae+="S")$(Ae,uc);var Be=M("Milliseconds",!1);R("z",0,0,"zoneAbbr"),R("zz",0,0,"zoneName");var Ce=o.prototype;Ce.add=le,Ce.calendar=kb,Ce.clone=lb,Ce.diff=sb,Ce.endOf=Eb,Ce.format=wb,Ce.from=xb,Ce.fromNow=yb,Ce.to=zb,Ce.toNow=Ab,Ce.get=P,Ce.invalidAt=Nb,Ce.isAfter=mb,Ce.isBefore=nb,Ce.isBetween=ob,Ce.isSame=pb,Ce.isSameOrAfter=qb,Ce.isSameOrBefore=rb,Ce.isValid=Lb,Ce.lang=ne,Ce.locale=Bb,Ce.localeData=Cb,Ce.max=ge,Ce.min=fe,Ce.parsingFlags=Mb,Ce.set=P,Ce.startOf=Db,Ce.subtract=me,Ce.toArray=Ib,Ce.toObject=Jb,Ce.toDate=Hb,Ce.toISOString=vb,Ce.toJSON=Kb,Ce.toString=ub,Ce.unix=Gb,Ce.valueOf=Fb,Ce.creationData=Ob,Ce.year=ee,Ce.isLeapYear=ta,Ce.weekYear=Qb,Ce.isoWeekYear=Rb,Ce.quarter=Ce.quarters=Wb,Ce.month=ha,Ce.daysInMonth=ia,Ce.week=Ce.weeks=$b,Ce.isoWeek=Ce.isoWeeks=_b,Ce.weeksInYear=Tb,Ce.isoWeeksInYear=Sb,Ce.date=pe,Ce.day=Ce.days=gc,Ce.weekday=hc,Ce.isoWeekday=ic,Ce.dayOfYear=nc,Ce.hour=Ce.hours=xe,Ce.minute=Ce.minutes=ye,Ce.second=Ce.seconds=ze,Ce.millisecond=Ce.milliseconds=Be,Ce.utcOffset=Ua,Ce.utc=Wa,Ce.local=Xa,Ce.parseZone=Ya,Ce.hasAlignedHourOffset=Za,Ce.isDST=$a,Ce.isDSTShifted=_a,Ce.isLocal=ab,Ce.isUtcOffset=bb,Ce.isUtc=cb,Ce.isUTC=cb,Ce.zoneAbbr=vc,Ce.zoneName=wc,Ce.dates=u("dates accessor is deprecated. Use date instead.",pe),Ce.months=u("months accessor is deprecated. Use month instead",ha),Ce.years=u("years accessor is deprecated. Use year instead",ee),Ce.zone=u("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Va);var De=Ce,Ee={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Fe={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"},Ge="Invalid date",He="%d",Ie=/\d{1,2}/,Je={future:"in %s",past:"%s ago",s:"a few 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"},Ke=A.prototype;Ke._calendar=Ee,Ke.calendar=zc,Ke._longDateFormat=Fe,Ke.longDateFormat=Ac,Ke._invalidDate=Ge,Ke.invalidDate=Bc,Ke._ordinal=He,Ke.ordinal=Cc,Ke._ordinalParse=Ie,Ke.preparse=Dc,Ke.postformat=Dc,Ke._relativeTime=Je,Ke.relativeTime=Ec,Ke.pastFuture=Fc,Ke.set=y,Ke.months=ca,Ke._months=Wd,Ke.monthsShort=da,Ke._monthsShort=Xd,Ke.monthsParse=fa,Ke._monthsRegex=Zd,Ke.monthsRegex=ka,Ke._monthsShortRegex=Yd,Ke.monthsShortRegex=ja,Ke.week=Xb,Ke._week=oe,Ke.firstDayOfYear=Zb,Ke.firstDayOfWeek=Yb,Ke.weekdays=bc,Ke._weekdays=qe,Ke.weekdaysMin=dc,Ke._weekdaysMin=se,Ke.weekdaysShort=cc,Ke._weekdaysShort=re,Ke.weekdaysParse=fc,Ke._weekdaysRegex=te,Ke.weekdaysRegex=jc,Ke._weekdaysShortRegex=ue,Ke.weekdaysShortRegex=kc,Ke._weekdaysMinRegex=ve,Ke.weekdaysMinRegex=lc,Ke.isPM=sc,Ke._meridiemParse=we,Ke.meridiem=tc,E("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===r(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=u("moment.lang is deprecated. Use moment.locale instead.",E),a.langData=u("moment.langData is deprecated. Use moment.localeData instead.",H);var Le=Math.abs,Me=Yc("ms"),Ne=Yc("s"),Oe=Yc("m"),Pe=Yc("h"),Qe=Yc("d"),Re=Yc("w"),Se=Yc("M"),Te=Yc("y"),Ue=$c("milliseconds"),Ve=$c("seconds"),We=$c("minutes"),Xe=$c("hours"),Ye=$c("days"),Ze=$c("months"),$e=$c("years"),_e=Math.round,af={s:45,m:45,h:22,d:26,M:11},bf=Math.abs,cf=Oa.prototype;cf.abs=Oc,cf.add=Qc,cf.subtract=Rc,cf.as=Wc,cf.asMilliseconds=Me,cf.asSeconds=Ne,cf.asMinutes=Oe,cf.asHours=Pe,cf.asDays=Qe,cf.asWeeks=Re,cf.asMonths=Se,cf.asYears=Te,cf.valueOf=Xc,cf._bubble=Tc,cf.get=Zc,cf.milliseconds=Ue,cf.seconds=Ve,cf.minutes=We,cf.hours=Xe,cf.days=Ye,cf.weeks=_c,cf.months=Ze,cf.years=$e,cf.humanize=dd,cf.toISOString=ed,cf.toString=ed,cf.toJSON=ed,cf.locale=Bb,cf.localeData=Cb,cf.toIsoString=u("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ed),cf.lang=ne,R("X",0,0,"unix"),R("x",0,0,"valueOf"),W("x",Fd),W("X",Id),$("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),$("x",function(a,b,c){c._d=new Date(r(a))}),a.version="2.13.0",b(Ka),a.fn=De,a.min=Ma,a.max=Na,a.now=he,a.utc=h,a.unix=xc,a.months=Jc,a.isDate=d,a.locale=E,a.invalid=l,a.duration=db,a.isMoment=p,a.weekdays=Lc,a.parseZone=yc,a.localeData=H,a.isDuration=Pa,a.monthsShort=Kc,a.weekdaysMin=Nc,a.defineLocale=F,a.updateLocale=G,a.locales=I,a.weekdaysShort=Mc,a.normalizeUnits=K,a.relativeTimeThreshold=cd,a.prototype=De;var df=a;return df}),function(a,b,c){"use strict";function d(a){var b,c=[];if(void 0===a)return void 0;for(Array.isArray(a)||(a=[a]),b=0;b<a.length;b+=1)"object"==typeof a[b]?c[b]=a[b].content:c[b]=a[b];return c}function e(a,b){var c;if("descending"===b)c=1;else{if("ascending"!==b)throw new TypeError("Query.sortFunction(): Argument 2 must be 'ascending' or 'descending'");c=-1}return function(b,e){var f,g;for(b=d(b[a])||[],e=d(e[a])||[],g=b.length>e.length?b.length:e.length,f=0;g>f;f+=1){if(void 0===b[f])return c;if(void 0===e[f])return-c;if(b[f]>e[f])return-c;if(b[f]<e[f])return c}return 0}}function f(a,b){var c;if(!Array.isArray(a))throw new TypeError("jioquery.sortOn(): Argument 1 is not of type 'array'");for(c=a.length-1;c>=0;c-=1)b.sort(e(a[c][0],a[c][1]));return b}function g(a,b){if(!Array.isArray(a))throw new TypeError("jioquery.limit(): Argument 1 is not of type 'array'");if(!Array.isArray(b))throw new TypeError("jioquery.limit(): Argument 2 is not of type 'array'");return b.splice(0,a[0]),a[1]&&b.splice(a[1]),b}function h(a,b){var c,d,e;if(!Array.isArray(a))throw new TypeError("jioquery.select(): Argument 1 is not of type Array");if(!Array.isArray(b))throw new TypeError("jioquery.select(): Argument 2 is not of type Array");for(c=0;c<b.length;c+=1){for(e={},d=0;d<a.length;d+=1)b[c].hasOwnProperty([a[d]])&&(e[a[d]]=b[c][a[d]]);for(d in e)if(e.hasOwnProperty(d)){b[c]=e;break}}return b}function i(){}function j(){}function k(a){return a.replace(t,"\\$&")}function l(a,b){a.super_=b,a.prototype=Object.create(b.prototype,{constructor:{configurable:!0,enumerable:!1,writable:!0,value:a}})}function m(a,b){if("string"!=typeof a)throw new TypeError("jioquery.searchTextToRegExp(): Argument 1 is not of type 'string'");return b===!1?new RegExp("^"+k(a)+"$"):new RegExp("^"+k(a).replace(u,".*").replace(v,".")+"$")}function n(a,b){i.call(this),this.operator=a.operator,this.query_list=a.query_list||[],this.query_list=this.query_list.map(function(a){return j.create(a,b)})}function o(a){var b=[];if("complex"===a.type)return b.push("("),(a.query_list||[]).forEach(function(c){b.push(o(c)),b.push(a.operator)}),b.length-=1,b.push(")"),b.join(" ");if("simple"===a.type)return(a.key?a.key+": ":"")+(a.operator||"")+' "'+a.value+'"';throw new TypeError("This object is not a query")}function p(a){var b;if(void 0!==a){if("object"!=typeof a)throw new TypeError("SimpleQuery().create(): key_schema is not of type 'object'");if(void 0===a.key_set)throw new TypeError("SimpleQuery().create(): key_schema has no 'key_set' property");for(b in a)if(a.hasOwnProperty(b))switch(b){case"key_set":case"cast_lookup":case"match_lookup":break;default:throw new TypeError("SimpleQuery().create(): key_schema has unknown property '"+b+"'")}}}function q(a,b){i.call(this),p(b),this._key_schema=b||{},this.operator=a.operator,this.key=a.key,this.value=a.value}function r(a){var b;if(void 0===a.read_from)throw new TypeError("Custom key is missing the read_from property");for(b in a)if(a.hasOwnProperty(b))switch(b){case"read_from":case"cast_to":case"equal_match":break;default:throw new TypeError("Custom key has unknown property '"+b+"'")}}var s={},t=/[\-\[\]{}()*+?.,\\\^$|#\s]/g,u=/%/g,v=/_/g,w=/^(?:AND|OR|NOT)$/i,x=/^(?:!?=|<=?|>=?)$/i;i.prototype.exec=function(b,c){if(!Array.isArray(b))throw new TypeError("Query().exec(): Argument 1 is not of type 'array'");if(void 0===c&&(c={}),"object"!=typeof c)throw new TypeError("Query().exec(): Optional argument 2 is not of type 'object'");var d,e=this;for(d=b.length-1;d>=0;d-=1)e.match(b[d])||b.splice(d,1);return c.sort_on&&f(c.sort_on,b),c.limit&&g(c.limit,b),h(c.select_list||[],b),(new a.Queue).push(function(){return b})},i.prototype.match=function(){return!0},i.prototype.parse=function(b){function c(b,d){function f(a){i.push(function(){return b.parsed=h.query_list[a],c(b,d)}).push(function(){h.query_list[a]=b.parsed})}var g,h=b.parsed,i=new a.Queue;if("complex"===h.type){for(g=0;g<h.query_list.length;g+=1)f(g);return i.push(function(){return b.parsed=h,e.onParseComplexQuery(b,d)})}return"simple"===h.type?e.onParseSimpleQuery(b,d):void 0}var d,e=this;return d={parsed:JSON.parse(JSON.stringify(e.serialized()))},(new a.Queue).push(function(){return e.onParseStart(d,b)}).push(function(){return c(d,b)}).push(function(){return e.onParseEnd(d,b)}).push(function(){return d.parsed})},i.prototype.toString=function(){return""},i.prototype.serialized=function(){return void 0},l(n,i),n.prototype.operator="AND",n.prototype.type="complex",n.prototype.match=function(a){var b=this.operator;return w.test(b)||(b="AND"),this[b.toUpperCase()](a)},n.prototype.toString=function(){var a=[],b=this.operator;return"NOT"===this.operator?(a.push("NOT ("),a.push(this.query_list[0].toString()),a.push(")"),a.join(" ")):(this.query_list.forEach(function(c){a.push("("),a.push(c.toString()),a.push(")"),a.push(b)}),a.length-=1,a.join(" "))},n.prototype.serialized=function(){var a={type:"complex",operator:this.operator,query_list:[]};return this.query_list.forEach(function(b){a.query_list.push("function"==typeof b.toJSON?b.toJSON():b)}),a},n.prototype.toJSON=n.prototype.serialized,n.prototype.AND=function(a){for(var b=!0,c=0;b&&c!==this.query_list.length;)b=this.query_list[c].match(a),c+=1;return b},n.prototype.OR=function(a){for(var b=!1,c=0;!b&&c!==this.query_list.length;)b=this.query_list[c].match(a),c+=1;return b},n.prototype.NOT=function(a){return!this.query_list[0].match(a)},j.create=function(a,b){if(""===a)return new i;if("string"==typeof a&&(a=c(a)),"string"==typeof(a||{}).type&&s[a.type])return new s[a.type](a,b);throw new TypeError("QueryFactory.create(): Argument 1 is not a search text or a parsable object")},l(q,i),q.prototype.type="simple",q.prototype.match=function(a){var b=null,c=null,d=null,e=null,f=this.operator,g=null,h=this.key;if(x.test(f)||(f=u.test(this.value)?"like":"="),e=this[f],this._key_schema.key_set&&void 0!==this._key_schema.key_set[h]&&(h=this._key_schema.key_set[h]),"object"==typeof h){if(r(h),b=a[h.read_from],c=h.equal_match,"string"==typeof c&&(c=this._key_schema.match_lookup[c]),void 0!==c&&(e="="===f||"like"===f?c:e),g=this.value,d=h.cast_to){"string"==typeof d&&(d=this._key_schema.cast_lookup[d]);try{g=d(g)}catch(i){g=void 0}try{b=d(b)}catch(i){b=void 0}}}else b=a[h],g=this.value;return void 0===b||void 0===g?!1:e(b,g)},q.prototype.toString=function(){return(this.key?this.key+":":"")+(this.operator?" "+this.operator:"")+' "'+this.value+'"'},q.prototype.serialized=function(){var a={type:"simple",key:this.key,value:this.value};return void 0!==this.operator&&(a.operator=this.operator),a},q.prototype.toJSON=q.prototype.serialized,q.prototype["="]=function(a,b){var c,d;for(Array.isArray(a)||(a=[a]),d=0;d<a.length;d+=1){if(c=a[d],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp)return 0===c.cmp(b);if(b.toString()===c.toString())return!0}return!1},q.prototype.like=function(a,b){var c,d;for(Array.isArray(a)||(a=[a]),d=0;d<a.length;d+=1){if(c=a[d],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp)return 0===c.cmp(b);if(m(b.toString()).test(c.toString()))return!0}return!1},q.prototype["!="]=function(a,b){var c,d;for(Array.isArray(a)||(a=[a]),d=0;d<a.length;d+=1){if(c=a[d],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp)return 0!==c.cmp(b);if(b.toString()===c.toString())return!1}return!0},q.prototype["<"]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)<0:b>c},q.prototype["<="]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)<=0:b>=c},q.prototype[">"]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)>0:c>b},q.prototype[">="]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)>=0:c>=b},s.simple=q,s.complex=n,i.parseStringToObject=c,i.objectToSearchText=o,b.Query=i,b.SimpleQuery=q,b.ComplexQuery=n,b.QueryFactory=j}(RSVP,window,parseStringToObject),function(a,b){"use strict";var c,d="year",e="month",f="day",g="hour",h="minute",i="second",j="millisecond",k={year:0,month:1,day:2,hour:3,minute:4,second:5,millisecond:6},l=function(a,b){return k[a]<k[b]?a:b};c=function(a){if(!(this instanceof c))return new c(a);if(a instanceof c)return this.mom=a.mom.clone(),void(this._precision=a._precision);if(void 0===a)return this.mom=b(),void this.setPrecision(j);if(this.mom=null,this._str=a,a.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+\-][0-2]\d:[0-5]\d|Z)/)||a.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d/)?(this.mom=b(a),this.setPrecision(j)):a.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+\-][0-2]\d:[0-5]\d|Z)/)||a.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/)?(this.mom=b(a),this.setPrecision(i)):a.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+\-][0-2]\d:[0-5]\d|Z)/)||a.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d/)?(this.mom=b(a),this.setPrecision(h)):a.match(/\d\d\d\d-\d\d-\d\d \d\d/)?(this.mom=b(a),this.setPrecision(g)):a.match(/\d\d\d\d-\d\d-\d\d/)?(this.mom=b(a),this.setPrecision(f)):a.match(/\d\d\d\d-\d\d/)?(this.mom=b(a),this.setPrecision(e)):a.match(/\d\d\d\d/)&&(this.mom=b(a,"YYYY"),this.setPrecision(d)),!this.mom)throw new Error("Cannot parse: "+a)},c.prototype.setPrecision=function(a){this._precision=a},c.prototype.getPrecision=function(){return this._precision},c.prototype.cmp=function(a){var b=this.mom,c=a.mom,d=l(this._precision,a._precision);return b.isBefore(c,d)?-1:b.isSame(c,d)?0:1},c.prototype.toPrecisionString=function(a){var b;if(a=a||this._precision,b={millisecond:"YYYY-MM-DD HH:mm:ss.SSS",second:"YYYY-MM-DD HH:mm:ss",minute:"YYYY-MM-DD HH:mm",hour:"YYYY-MM-DD HH",day:"YYYY-MM-DD",month:"YYYY-MM",year:"YYYY"}[a],!b)throw new TypeError("Unsupported precision value '"+a+"'");return this.mom.format(b)},c.prototype.toString=function(){return this._str},a.jiodate={JIODate:c,YEAR:d,MONTH:e,DAY:f,HOUR:g,MIN:h,SEC:i,MSEC:j}}(window,moment),function(a,b,c,d,e,f,g,h,i){"use strict";function j(a,b){if(void 0!==a&&"string"!=typeof a)throw new TypeError("You must pass a string.");this.message=a||"Default Message",this.status_code=b||500}function k(a){var c=new XMLHttpRequest;return new b.Promise(function(b,d,e){var f;if(c.open(a.type||"GET",a.url,!0),c.responseType=a.dataType||"","object"==typeof a.headers&&null!==a.headers)for(f in a.headers)a.headers.hasOwnProperty(f)&&c.setRequestHeader(f,a.headers[f]);if(c.addEventListener("load",function(a){return a.target.status>=400?d(a):void b(a)}),c.addEventListener("error",d),c.addEventListener("progress",e),"object"==typeof a.xhrFields&&null!==a.xhrFields)for(f in a.xhrFields)a.xhrFields.hasOwnProperty(f)&&(c[f]=a.xhrFields[f]);"function"==typeof a.beforeSend&&a.beforeSend(c),c.send(a.data)},function(){c.abort()})}function l(a,c){var d=new g;return new b.Promise(function(b,e,f){d.addEventListener("load",b),d.addEventListener("error",e),d.addEventListener("progress",f),d.readAsText(a,c)},function(){d.abort()})}function m(a){var c=new g;return new b.Promise(function(b,d,e){c.addEventListener("load",b),c.addEventListener("error",d),c.addEventListener("progress",e),c.readAsArrayBuffer(a)},function(){c.abort()})}function n(a){var c=new g;return new b.Promise(function(b,d,e){c.addEventListener("load",b),c.addEventListener("error",d),c.addEventListener("progress",e),c.readAsDataURL(a)},function(){c.abort()})}function o(a){var b,d=f(a.split(",")[1]),e=a.split(",")[0].split(":")[1],g=new h(d.length),j=new i(g);for(e=e.slice(0,e.length-";base64".length),b=0;b<d.length;b+=1)j[b]=d.charCodeAt(b);return new c([g],{type:e})}function p(a,b,c){if("string"!=typeof a[0]||""===a[0])throw new u.util.jIOError("Document id must be a non empty string on '"+b.__type+"."+c+"'.",400)}function q(a,b,c){if("string"!=typeof a[1]||""===a[1])throw new u.util.jIOError("Attachment id must be a non empty string on '"+b.__type+"."+c+"'.",400)}function r(a,c,d,e){return a.prototype[c]=function(){var a,f=arguments,g=this;return(new b.Queue).push(function(){return void 0!==d?d.apply(g.__storage,[f,g,c]):void 0}).push(function(b){var d=g.__storage[c];if(a=b,void 0===d)throw new u.util.jIOError("Capacity '"+c+"' is not implemented on '"+g.__type+"'",501);return d.apply(g.__storage,f)}).push(function(b){return void 0!==e?e.call(g,f,b,a):b})},this}function s(a,b){return this instanceof s?(this.__type=a,void(this.__storage=b)):new s}function t(){return this instanceof t?void(this.__storage_types={}):new t}var u,v={};j.prototype=new Error,j.prototype.constructor=j,v.jIOError=j,v.ajax=k,v.readBlobAsText=l,v.readBlobAsArrayBuffer=m,v.readBlobAsDataURL=n,v.dataURItoBlob=o,r(s,"put",p,function(a){return a[0]}),r(s,"get",p),r(s,"bulk"),r(s,"remove",p,function(a){return a[0]}),s.prototype.post=function(){var a=this,c=arguments;return(new b.Queue).push(function(){var b=a.__storage.post;if(void 0===b)throw new u.util.jIOError("Capacity 'post' is not implemented on '"+a.__type+"'",501);return a.__storage.post.apply(a.__storage,c)})},r(s,"putAttachment",function(a,b,d){p(a,b,d),q(a,b,d);var e=a[3]||{};if("string"==typeof a[2])a[2]=new c([a[2]],{type:e._content_type||e._mimetype||"text/plain;charset=utf-8"});else if(!(a[2]instanceof c))throw new u.util.jIOError("Attachment content is not a blob",400)}),r(s,"removeAttachment",function(a,b,c){p(a,b,c),q(a,b,c)}),r(s,"getAttachment",function(a,b,c){var d="blob";return p(a,b,c),q(a,b,c),void 0!==a[2]&&(d=a[2].format||d,delete a[2].format),d},function(a,d,e){var f;if(!(d instanceof c))throw new u.util.jIOError("'getAttachment' ("+a[0]+" , "+a[1]+") on '"+this.__type+"' does not return a Blob.",501);if("blob"===e)f=d;else if("data_url"===e)f=(new b.Queue).push(function(){return u.util.readBlobAsDataURL(d)}).push(function(a){return a.target.result});else if("array_buffer"===e)f=(new b.Queue).push(function(){return u.util.readBlobAsArrayBuffer(d)}).push(function(a){return a.target.result});else if("text"===e)f=(new b.Queue).push(function(){return u.util.readBlobAsText(d)}).push(function(a){return a.target.result});else{if("json"!==e)throw new u.util.jIOError(this.__type+".getAttachment format: '"+e+"' is not supported",400);f=(new b.Queue).push(function(){return u.util.readBlobAsText(d)}).push(function(a){return JSON.parse(a.target.result)})}return f}),s.prototype.buildQuery=function(){var a=this.__storage.buildQuery,c=this,d=arguments;if(void 0===a)throw new u.util.jIOError("Capacity 'buildQuery' is not implemented on '"+this.__type+"'",501);return(new b.Queue).push(function(){return a.apply(c.__storage,d)})},s.prototype.hasCapacity=function(a){var b=this.__storage.hasCapacity,c=this.__storage[a];if(void 0!==c)return!0;if(void 0===b||!b.apply(this.__storage,arguments))throw new u.util.jIOError("Capacity '"+a+"' is not implemented on '"+this.__type+"'",501);return!0},s.prototype.allDocs=function(a){var c=this;return void 0===a&&(a={}),(new b.Queue).push(function(){return!c.hasCapacity("list")||void 0!==a.query&&!c.hasCapacity("query")||void 0!==a.sort_on&&!c.hasCapacity("sort")||void 0!==a.select_list&&!c.hasCapacity("select")||void 0!==a.include_docs&&!c.hasCapacity("include")||void 0!==a.limit&&!c.hasCapacity("limit")?void 0:c.buildQuery(a)}).push(function(a){return{data:{rows:a,total_rows:a.length}}})},r(s,"allAttachments",p),r(s,"repair"),s.prototype.repair=function(){var a=this,c=arguments;return(new b.Queue).push(function(){var b=a.__storage.repair;return void 0!==b?a.__storage.repair.apply(a.__storage,c):void 0})},t.prototype.createJIO=function(a,b){if("string"!=typeof a.type)throw new TypeError("Invalid storage description");if(!this.__storage_types[a.type])throw new TypeError("Unknown storage '"+a.type+"'");return new s(a.type,new this.__storage_types[a.type](a,b))},t.prototype.addStorage=function(a,b){if("string"!=typeof a)throw new TypeError("jIO.addStorage(): Argument 1 is not of type 'string'");if("function"!=typeof b)throw new TypeError("jIO.addStorage(): Argument 2 is not of type 'function'");if(void 0!==this.__storage_types[a])throw new TypeError("jIO.addStorage(): Storage type already exists");this.__storage_types[a]=b},t.prototype.util=v,t.prototype.QueryFactory=d,t.prototype.Query=e,u=new t,a.jIO=u}(window,RSVP,Blob,QueryFactory,Query,atob,FileReader,ArrayBuffer,Uint8Array),function(){function a(a){"use strict";var d={fill:0},f=function(a){for(a+=9;a%64>0;a+=1);return a},g=function(a,b){for(var c=b>>2;c<a.length;c++)a[c]=0},h=function(a,b,c){a[b>>2]|=128<<24-(b%4<<3),a[((b>>2)+2&-16)+14]=c>>29,a[((b>>2)+2&-16)+15]=c<<3},i=function(a,b,c,d,e){var f,g=this,h=e%4,i=d%4,j=d-i;if(j>0)switch(h){case 0:a[e+3|0]=g.charCodeAt(c);case 1:a[e+2|0]=g.charCodeAt(c+1);case 2:a[e+1|0]=g.charCodeAt(c+2);case 3:a[0|e]=g.charCodeAt(c+3)}for(f=h;j>f;f=f+4|0)b[e+f>>2]=g.charCodeAt(c+f)<<24|g.charCodeAt(c+f+1)<<16|g.charCodeAt(c+f+2)<<8|g.charCodeAt(c+f+3);switch(i){case 3:a[e+j+1|0]=g.charCodeAt(c+j+2);case 2:a[e+j+2|0]=g.charCodeAt(c+j+1);case 1:a[e+j+3|0]=g.charCodeAt(c+j)}},j=function(a,b,c,d,e){var f,g=this,h=e%4,i=d%4,j=d-i;if(j>0)switch(h){case 0:a[e+3|0]=g[c];case 1:a[e+2|0]=g[c+1];case 2:a[e+1|0]=g[c+2];case 3:a[0|e]=g[c+3]}for(f=4-h;j>f;f=f+=4)b[e+f>>2]=g[c+f]<<24|g[c+f+1]<<16|g[c+f+2]<<8|g[c+f+3];switch(i){case 3:a[e+j+1|0]=g[c+j+2];case 2:a[e+j+2|0]=g[c+j+1];case 1:a[e+j+3|0]=g[c+j]}},k=function(a,b,d,e,f){var g,h=this,i=f%4,j=e%4,k=e-j,l=new Uint8Array(c.readAsArrayBuffer(h.slice(d,d+e)));if(k>0)switch(i){case 0:a[f+3|0]=l[0];case 1:a[f+2|0]=l[1];case 2:a[f+1|0]=l[2];case 3:a[0|f]=l[3]}for(g=4-i;k>g;g=g+=4)b[f+g>>2]=l[g]<<24|l[g+1]<<16|l[g+2]<<8|l[g+3];switch(j){case 3:a[f+k+1|0]=l[k+2];case 2:a[f+k+2|0]=l[k+1];case 1:a[f+k+3|0]=l[k]}},l=function(a){switch(e.getDataType(a)){case"string":
+return i.bind(a);case"array":return j.bind(a);case"buffer":return j.bind(a);case"arraybuffer":return j.bind(new Uint8Array(a));case"view":return j.bind(new Uint8Array(a.buffer,a.byteOffset,a.byteLength));case"blob":return k.bind(a)}},m=function(a){var b,c,d="0123456789abcdef",e=[],f=new Uint8Array(a);for(b=0;b<f.length;b++)c=f[b],e[b]=d.charAt(c>>4&15)+d.charAt(c>>0&15);return e.join("")},n=function(a){var b;if(65536>=a)return 65536;if(16777216>a)for(b=1;a>b;b<<=1);else for(b=16777216;a>b;b+=16777216);return b},o=function(a){if(a%64>0)throw new Error("Chunk size must be a multiple of 128 bit");d.maxChunkLen=a,d.padMaxChunkLen=f(a),d.heap=new ArrayBuffer(n(d.padMaxChunkLen+320+20)),d.h32=new Int32Array(d.heap),d.h8=new Int8Array(d.heap),d.core=b({Int32Array:Int32Array,DataView:DataView},{},d.heap),d.buffer=null};o(a||65536);var p=function(a,b){var c=new Int32Array(a,b+320,5);c[0]=1732584193,c[1]=-271733879,c[2]=-1732584194,c[3]=271733878,c[4]=-1009589776},q=function(a,b){var c=f(a),e=new Int32Array(d.heap,0,c>>2);return g(e,a),h(e,a,b),c},r=function(a,b,c){l(a)(d.h8,d.h32,b,c,0)},s=function(a,b,c,e,f){var g=c;f&&(g=q(c,e)),r(a,b,c),d.core.hash(g,d.padMaxChunkLen)},t=function(a,b){var c=new Int32Array(a,b+320,5),d=new Int32Array(5),e=new DataView(d.buffer);return e.setInt32(0,c[0],!1),e.setInt32(4,c[1],!1),e.setInt32(8,c[2],!1),e.setInt32(12,c[3],!1),e.setInt32(16,c[4],!1),d},u=this.rawDigest=function(a){var b=a.byteLength||a.length||a.size||0;p(d.heap,d.padMaxChunkLen);var c=0,e=d.maxChunkLen;for(c=0;b>c+e;c+=e)s(a,c,e,b,!1);return s(a,c,b-c,b,!0),t(d.heap,d.padMaxChunkLen)};this.digest=this.digestFromString=this.digestFromBuffer=this.digestFromArrayBuffer=function(a){return m(u(a).buffer)}}function b(a,b,c){"use asm";function d(a,b){a|=0,b|=0;var c=0,d=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;for(f=e[b+320>>2]|0,h=e[b+324>>2]|0,j=e[b+328>>2]|0,l=e[b+332>>2]|0,n=e[b+336>>2]|0,c=0;(c|0)<(a|0);c=c+64|0){for(g=f,i=h,k=j,m=l,o=n,d=0;(d|0)<64;d=d+4|0)q=e[c+d>>2]|0,p=((f<<5|f>>>27)+(h&j|~h&l)|0)+((q+n|0)+1518500249|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[a+d>>2]=q;for(d=a+64|0;(d|0)<(a+80|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h&j|~h&l)|0)+((q+n|0)+1518500249|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+80|0;(d|0)<(a+160|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h^j^l)|0)+((q+n|0)+1859775393|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+160|0;(d|0)<(a+240|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h&j|h&l|j&l)|0)+((q+n|0)-1894007588|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+240|0;(d|0)<(a+320|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h^j^l)|0)+((q+n|0)-899497514|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;f=f+g|0,h=h+i|0,j=j+k|0,l=l+m|0,n=n+o|0}e[b+320>>2]=f,e[b+324>>2]=h,e[b+328>>2]=j,e[b+332>>2]=l,e[b+336>>2]=n}var e=new a.Int32Array(c);return{hash:d}}if("undefined"!=typeof module?module.exports=a:"undefined"!=typeof window&&(window.Rusha=a),"undefined"!=typeof FileReaderSync){var c=new FileReaderSync,d=new a(4194304);self.onmessage=function(a){var b,c=a.data.data;try{b=d.digest(c),self.postMessage({id:a.data.id,hash:b})}catch(e){self.postMessage({id:a.data.id,error:e.name})}}}var e={getDataType:function(a){if("string"==typeof a)return"string";if(a instanceof Array)return"array";if("undefined"!=typeof global&&global.Buffer&&global.Buffer.isBuffer(a))return"buffer";if(a instanceof ArrayBuffer)return"arraybuffer";if(a.buffer instanceof ArrayBuffer)return"view";if(a instanceof Blob)return"blob";throw new Error("Unsupported data type.")}}}(),function(a,b,c){"use strict";function d(a){return f.digestFromString(a)}function e(b){if(this._query_options=b.query||{},this._local_sub_storage=a.createJIO(b.local_sub_storage),this._remote_sub_storage=a.createJIO(b.remote_sub_storage),this._signature_hash="_replicate_"+d(JSON.stringify(b.local_sub_storage)+JSON.stringify(b.remote_sub_storage)+JSON.stringify(this._query_options)),this._signature_sub_storage=a.createJIO({type:"document",document_id:this._signature_hash,sub_storage:b.local_sub_storage}),this._use_remote_post=b.use_remote_post||!1,this._conflict_handling=b.conflict_handling||0,this._conflict_handling!==g&&this._conflict_handling!==h&&this._conflict_handling!==i&&this._conflict_handling!==j)throw new a.util.jIOError("Unsupported conflict handling: "+this._conflict_handling,400);this._check_local_modification=b.check_local_modification,void 0===this._check_local_modification&&(this._check_local_modification=!0),this._check_local_creation=b.check_local_creation,void 0===this._check_local_creation&&(this._check_local_creation=!0),this._check_local_deletion=b.check_local_deletion,void 0===this._check_local_deletion&&(this._check_local_deletion=!0),this._check_remote_modification=b.check_remote_modification,void 0===this._check_remote_modification&&(this._check_remote_modification=!0),this._check_remote_creation=b.check_remote_creation,void 0===this._check_remote_creation&&(this._check_remote_creation=!0),this._check_remote_deletion=b.check_remote_deletion,void 0===this._check_remote_deletion&&(this._check_remote_deletion=!0)}var f=new c,g=0,h=1,i=2,j=3;e.prototype.remove=function(b){if(b===this._signature_hash)throw new a.util.jIOError(this._signature_hash+" is frozen",403);return this._local_sub_storage.remove.apply(this._local_sub_storage,arguments)},e.prototype.post=function(){return this._local_sub_storage.post.apply(this._local_sub_storage,arguments)},e.prototype.put=function(b){if(b===this._signature_hash)throw new a.util.jIOError(this._signature_hash+" is frozen",403);return this._local_sub_storage.put.apply(this._local_sub_storage,arguments)},e.prototype.get=function(){return this._local_sub_storage.get.apply(this._local_sub_storage,arguments)},e.prototype.hasCapacity=function(){return this._local_sub_storage.hasCapacity.apply(this._local_sub_storage,arguments)},e.prototype.buildQuery=function(){return this._local_sub_storage.buildQuery.apply(this._local_sub_storage,arguments)},e.prototype.repair=function(){function c(a,b,c,d,e,f){var g,h,i=!0;return void 0===f&&(f={}),g=f.use_post?b.post(c).push(function(b){return i=!1,h=b,a.put(h,c)}).push(function(){return a.remove(e)}).push(function(){return n._signature_sub_storage.remove(e)}).push(function(){return i=!0,n._signature_sub_storage.put(h,{hash:d})}).push(function(){p[h]=null}):b.put(e,c).push(function(){return n._signature_sub_storage.put(e,{hash:d})}),g.push(function(){i&&(p[e]=null)})}function e(b,e,f,g,h,i){var j;b.push(function(){return f.get(g)}).push(function(a){j=a},function(b){if(!(b instanceof a.util.jIOError&&404===b.status_code))throw b}).push(function(){return i(g)}).push(function(b){var i,k=d(JSON.stringify(b));if(void 0===j)return c(e,f,b,k,g,h);if(i=d(JSON.stringify(j)),k===i)return n._signature_sub_storage.put(g,{hash:k}).push(function(){p[g]=null});if(h.conflict_ignore!==!0){if(h.conflict_force===!0)return c(e,f,b,k,g,h);throw new a.util.jIOError("Conflict on '"+g+"': "+JSON.stringify(b)+" !== "+JSON.stringify(j),409)}})}function f(a,c,d,f,g){a.push(function(){return c.bulk(f)}).push(function(a){function h(b){return function(c){if(c!==f[b].parameter_list[0])throw new Error("Does not access expected ID "+c);return a[b]}}var i,j=new b.Queue;for(i=0;i<a.length;i+=1)e(j,c,d,f[i].parameter_list[0],g,h(i));return j})}function g(b,e,f,g){var h;b.push(function(){return n._signature_sub_storage.get(f)}).push(function(b){return h=b.hash,e.get(f).push(function(a){var b=d(JSON.stringify(a));return b===h?e.remove(f).push(function(){return n._signature_sub_storage.remove(f)}).push(function(){p[f]=null}):c(e,g,a,b,f)},function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return n._signature_sub_storage.remove(f).push(function(){p[f]=null});throw b})})}function k(e,f,g,h,i,j,k){e.push(function(){return b.all([k(h),n._signature_sub_storage.get(h)])}).push(function(b){var e=b[0],k=d(JSON.stringify(e)),l=b[1].hash;return k!==l?g.get(h).push(function(b){var m=d(JSON.stringify(b));if(m!==l){if(k===m)return n._signature_sub_storage.put(h,{hash:k}).push(function(){p[h]=null});if(j===!0)return;if(i!==!0)throw new a.util.jIOError("Conflict on '"+h+"': "+JSON.stringify(e)+" !== "+JSON.stringify(b),409)}return c(f,g,e,k,h)},function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return c(f,g,e,k,h);throw b}):void 0})}function l(a,c,d,e,f,g){a.push(function(){return c.bulk(e)}).push(function(a){function h(b){return function(c){if(c!==e[b].parameter_list[0])throw new Error("Does not access expected ID "+c);return a[b]}}var i,j=new b.Queue;for(i=0;i<a.length;i+=1)k(j,c,d,e[i].parameter_list[0],f,g,h(i));return j})}function m(a,c,d){var h=new b.Queue;return d.hasOwnProperty("use_post")||(d.use_post=!1),h.push(function(){return b.all([a.allDocs(n._query_options),n._signature_sub_storage.allDocs()])}).push(function(b){var i,j,m={},n=[],o=[],q={};for(i=0;i<b[0].data.total_rows;i+=1)p.hasOwnProperty(b[0].data.rows[i].id)||(m[b[0].data.rows[i].id]=i);for(i=0;i<b[1].data.total_rows;i+=1)p.hasOwnProperty(b[1].data.rows[i].id)||(q[b[1].data.rows[i].id]=i);if(d.check_creation===!0){for(j in m)m.hasOwnProperty(j)&&(q.hasOwnProperty(j)||(d.use_bulk_get===!0?n.push({method:"get",parameter_list:[j]}):e(h,a,c,j,d,a.get.bind(a))));d.use_bulk_get===!0&&0!==n.length&&f(h,a,c,n,d)}for(j in q)q.hasOwnProperty(j)&&(m.hasOwnProperty(j)?d.check_modification===!0&&(d.use_bulk_get===!0?o.push({method:"get",parameter_list:[j]}):k(h,a,c,j,d.conflict_force,d.conflict_ignore,a.get.bind(a))):d.check_deletion===!0&&g(h,c,j,a));d.use_bulk_get===!0&&0!==o.length&&l(h,a,c,o,d.conflict_force,d.conflict_ignore)})}var n=this,o=arguments,p={};return p[n._signature_hash]=null,(new b.Queue).push(function(){return n._signature_sub_storage.__storage._sub_storage.get(n._signature_hash)}).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return n._signature_sub_storage.__storage._sub_storage.put(n._signature_hash,{});throw b}).push(function(){return b.all([n._local_sub_storage.repair.apply(n._local_sub_storage,o),n._remote_sub_storage.repair.apply(n._remote_sub_storage,o)])}).push(function(){return n._check_local_modification||n._check_local_creation||n._check_local_deletion?m(n._local_sub_storage,n._remote_sub_storage,{use_post:n._use_remote_post,conflict_force:n._conflict_handling===h,conflict_ignore:n._conflict_handling===j||n._conflict_handling===i,check_modification:n._check_local_modification,check_creation:n._check_local_creation,check_deletion:n._check_local_deletion}):void 0}).push(function(){var b=!1;try{b=n._remote_sub_storage.hasCapacity("bulk")}catch(c){if(!(c instanceof a.util.jIOError&&501===c.status_code))throw c}return n._check_remote_modification||n._check_remote_creation||n._check_remote_deletion?m(n._remote_sub_storage,n._local_sub_storage,{use_bulk_get:b,conflict_force:n._conflict_handling===i,conflict_ignore:n._conflict_handling===j,check_modification:n._check_remote_modification,check_creation:n._check_remote_creation,check_deletion:n._check_remote_deletion}):void 0})},a.addStorage("replicate",e)}(jIO,RSVP,Rusha),function(a){"use strict";function b(a){this._sub_storage=jIO.createJIO(a.sub_storage)}var c=new a;b.prototype.post=function(a){return this._sub_storage.put(c.digestFromString(JSON.stringify(a)),a)},b.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},b.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},b.prototype.hasCapacity=function(){return this._sub_storage.hasCapacity.apply(this._sub_storage,arguments)},b.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},b.prototype.getAttachment=function(){return this._sub_storage.getAttachment.apply(this._sub_storage,arguments)},b.prototype.putAttachment=function(){return this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},b.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},b.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},b.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},jIO.addStorage("sha",b)}(Rusha),function(a){"use strict";function b(b){this._sub_storage=a.createJIO(b.sub_storage)}b.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},b.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},b.prototype.post=function(a){function b(){return("0000"+Math.floor(65536*Math.random()).toString(16)).slice(-4)}var c=b()+b()+"-"+b()+"-"+b()+"-"+b()+"-"+b()+b()+b();return this.put(c,a)},b.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},b.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},b.prototype.getAttachment=function(){return this._sub_storage.getAttachment.apply(this._sub_storage,arguments)},b.prototype.putAttachment=function(){return this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},b.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},b.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},b.prototype.hasCapacity=function(a){return this._sub_storage.hasCapacity(a)},b.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},a.addStorage("uuid",b)}(jIO),function(a,b,c){"use strict";function d(){this._database={}}d.prototype.put=function(a,c){return this._database.hasOwnProperty(a)||(this._database[a]={attachments:{}}),this._database[a].doc=b.stringify(c),a},d.prototype.get=function(c){try{return b.parse(this._database[c].doc)}catch(d){if(d instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+c,404);throw d}},d.prototype.allAttachments=function(b){var c,d={};try{for(c in this._database[b].attachments)this._database[b].attachments.hasOwnProperty(c)&&(d[c]={})}catch(e){if(e instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+b,404);throw e}return d},d.prototype.remove=function(a){return delete this._database[a],a},d.prototype.getAttachment=function(b,c){try{var d=this._database[b].attachments[c];if(void 0===d)throw new a.util.jIOError("Cannot find attachment: "+b+" , "+c,404);return a.util.dataURItoBlob(d)}catch(e){if(e instanceof TypeError)throw new a.util.jIOError("Cannot find attachment: "+b+" , "+c,404);throw e}},d.prototype.putAttachment=function(b,d,e){var f;try{f=this._database[b].attachments}catch(g){if(g instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+b,404);throw g}return(new c.Queue).push(function(){return a.util.readBlobAsDataURL(e)}).push(function(a){f[d]=a.target.result})},d.prototype.removeAttachment=function(b,c){try{delete this._database[b].attachments[c]}catch(d){if(d instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+b,404);throw d}},d.prototype.hasCapacity=function(a){return"list"===a||"include"===a},d.prototype.buildQuery=function(a){var c,d=[];for(c in this._database)this._database.hasOwnProperty(c)&&(a.include_docs===!0?d.push({id:c,value:{},doc:b.parse(this._database[c].doc)}):d.push({id:c,value:{}}));return d},a.addStorage("memory",d)}(jIO,JSON,RSVP),function(a,b,c,d){"use strict";function e(a){this._sub_storage=jIO.createJIO(a.sub_storage)}function f(a,b){return a.indexOf(b)===a.length-b.length}var g="application/x-jio-utf16_lz_string";e.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},e.prototype.post=function(){return this._sub_storage.post.apply(this._sub_storage,arguments)},e.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},e.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},e.prototype.hasCapacity=function(){return this._sub_storage.hasCapacity.apply(this._sub_storage,arguments)},e.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},e.prototype.getAttachment=function(b,e){var f=this;return f._sub_storage.getAttachment(b,e).push(function(b){return b.type!==g?b:(new a.Queue).push(function(){return jIO.util.readBlobAsText(b,"utf16")}).push(function(a){var e=c.decompressFromUTF16(a.target.result);if(""===e)return b;try{return jIO.util.dataURItoBlob(e)}catch(f){if(f instanceof d)return b;throw f}})})},e.prototype.putAttachment=function(d,e,h){var i=this;return 0===h.type.indexOf("text/")||f(h.type,"xml")||f(h.type,"json")?(new a.Queue).push(function(){return jIO.util.readBlobAsDataURL(h)}).push(function(a){var f=c.compressToUTF16(a.target.result);return h=new b([f],{type:g}),i._sub_storage.putAttachment(d,e,h)}):this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},e.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},e.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},jIO.addStorage("zip",e)}(RSVP,Blob,LZString,DOMException),function(a,b,c,d){"use strict";function e(b){if(0!==b.indexOf("/"))throw new a.util.jIOError("id "+b+" is forbidden (no begin /)",400);if(b.lastIndexOf("/")!==b.length-1)throw new a.util.jIOError("id "+b+" is forbidden (no end /)",400);return b}function f(b){if(-1!==b.indexOf("/"))throw new a.util.jIOError("attachment "+b+" is forbidden",400)}function g(a){if("string"!=typeof a.access_token||!a.access_token)throw new TypeError("Access Token' must be a string which contains more than one character.");if("string"!=typeof a.root||!a.root||"dropbox"!==a.root&&"sandbox"!==a.root)throw new TypeError("root must be 'dropbox' or 'sandbox'");this._access_token=a.access_token,this._root=a.root}var h="https://content.dropboxapi.com/1/files_put/{+root}{+id}{+name}{?access_token}",i=d.parse(h),j="https://api.dropboxapi.com/1/fileops/create_folder{?access_token,root,path}",k=d.parse(j),l="https://api.dropboxapi.com/1/fileops/delete/{?access_token,root,path}",m=d.parse(l),n="https://content.dropboxapi.com/1/files{/root,id}{+name}{?access_token}",o=d.parse(n),p="https://api.dropboxapi.com/1/metadata{/root}{+id}{?access_token}",q=d.parse(p);g.prototype.put=function(c,d){var f=this;if(c=e(c),Object.getOwnPropertyNames(d).length>0)throw new a.util.jIOError("Can not store properties: "+Object.getOwnPropertyNames(d),400);return(new b.Queue).push(function(){return a.util.ajax({type:"POST",url:k.expand({access_token:f._access_token,root:f._root,path:c})})}).push(void 0,function(a){if(void 0===a.target||405!==a.target.status)throw a})},g.prototype.remove=function(b){return b=e(b),a.util.ajax({type:"POST",url:m.expand({access_token:this._access_token,root:this._root,path:b})})},g.prototype.get=function(c){var d=this;return"/"===c?{}:(c=e(c),(new b.Queue).push(function(){return a.util.ajax({type:"GET",url:q.expand({access_token:d._access_token,root:d._root,id:c})})}).push(function(b){var d=JSON.parse(b.target.response||b.target.responseText);if(d.is_dir)return{};throw new a.util.jIOError("Not a directory: "+c,404)},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document: "+c,404);throw b}))},g.prototype.allAttachments=function(c){var d=this;return c=e(c),(new b.Queue).push(function(){return a.util.ajax({type:"GET",url:q.expand({access_token:d._access_token,root:d._root,id:c})})}).push(function(b){var d,e=JSON.parse(b.target.response||b.target.responseText),f={};if(!e.is_dir)throw new a.util.jIOError("Not a directory: "+c,404);for(d=0;d<e.contents.length;d+=1)e.contents[d].is_dir||(f[e.contents[d].path.split("/").pop()]={});return f},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document: "+c,404);throw b})},g.prototype.putAttachment=function(b,c,d){return b=e(b),f(c),a.util.ajax({type:"PUT",url:i.expand({root:this._root,id:b,name:c,access_token:this._access_token}),dataType:d.type,data:d})},g.prototype.getAttachment=function(d,g){var h=this;return d=e(d),f(g),(new b.Queue).push(function(){return a.util.ajax({type:"GET",dataType:"blob",url:o.expand({root:h._root,id:d,name:g,access_token:h._access_token})})}).push(function(a){return new c([a.target.response||a.target.responseText],{type:a.target.getResponseHeader("Content-Type")||"application/octet-stream"})},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+d+", "+g,404);throw b})},g.prototype.removeAttachment=function(c,d){var g=this;return c=e(c),f(d),(new b.Queue).push(function(){return a.util.ajax({type:"POST",url:m.expand({access_token:g._access_token,root:g._root,path:c+d})})}).push(void 0,function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+c+", "+d,404);throw b})},a.addStorage("dropbox",g)}(jIO,RSVP,Blob,UriTemplate),function(a,b,c,d){"use strict";function e(c,d){return void 0===d&&(d={}),void 0!==c._authorization&&(void 0===d.headers&&(d.headers={}),d.headers.Authorization=c._authorization),void 0!==c._with_credentials&&(void 0===d.xhrFields&&(d.xhrFields={}),d.xhrFields.withCredentials=c._with_credentials),(new b.Queue).push(function(){return a.util.ajax(d)})}function f(b){if(0!==b.indexOf("/"))throw new a.util.jIOError("id "+b+" is forbidden (no begin /)",400);if(b.lastIndexOf("/")!==b.length-1)throw new a.util.jIOError("id "+b+" is forbidden (no end /)",400);return b}function g(b){if(-1!==b.indexOf("/"))throw new a.util.jIOError("attachment "+b+" is forbidden",400)}function h(a){if("string"!=typeof a.url)throw new TypeError("DavStorage 'url' is not of type string");this._url=a.url,"string"==typeof a.basic_login&&(this._authorization="Basic "+a.basic_login),this._with_credentials=a.with_credentials}h.prototype.put=function(c,d){var g=this;if(c=f(c),Object.getOwnPropertyNames(d).length>0)throw new a.util.jIOError("Can not store properties: "+Object.getOwnPropertyNames(d),400);return(new b.Queue).push(function(){return e(g,{type:"MKCOL",url:g._url+c})}).push(void 0,function(a){if(void 0===a.target||405!==a.target.status)throw a})},h.prototype.remove=function(a){return a=f(a),e(this,{type:"DELETE",url:this._url+a})},h.prototype.get=function(c){var d=this;return c=f(c),(new b.Queue).push(function(){return e(d,{type:"PROPFIND",url:d._url+c,dataType:"text",headers:{Depth:"1"}})}).push(function(){return{}},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document",404);throw b})},h.prototype.allAttachments=function(d){var g=this;return d=f(d),(new b.Queue).push(function(){return e(g,{type:"PROPFIND",url:g._url+d,dataType:"text",headers:{Depth:"1"}})}).push(function(a){var b,d,e={},f=(new c).parseFromString(a.target.responseText,"text/xml").querySelectorAll("D\\:response, response");for(b=1;b<f.length;b+=1)d=f[b].querySelector("D\\:href, href").textContent.split("/").slice(-1)[0],void 0!==d&&""!==d&&(e[d]={});return e},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document",404);throw b})},h.prototype.putAttachment=function(c,d,h){var i=this;return c=f(c),g(d),(new b.Queue).push(function(){return e(i,{type:"PUT",url:i._url+c+d,data:h})}).push(void 0,function(b){if(403===b.target.status||424===b.target.status)throw new a.util.jIOError("Cannot access subdocument",404);throw b})},h.prototype.getAttachment=function(c,h){var i=this;return c=f(c),g(h),(new b.Queue).push(function(){return e(i,{type:"GET",url:i._url+c+h,dataType:"blob"})}).push(function(a){return new d([a.target.response||a.target.responseText],{type:a.target.getResponseHeader("Content-Type")||"application/octet-stream"})},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+c+" , "+h,404);throw b})},h.prototype.removeAttachment=function(c,d){var h=this;return c=f(c),g(d),(new b.Queue).push(function(){return e(h,{type:"DELETE",url:h._url+c+d})}).push(void 0,function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+c+" , "+d,404);throw b})},a.addStorage("dav",h)}(jIO,RSVP,DOMParser,Blob),function(a,b,c,d,e){"use strict";function f(b,c){if(404===b.target.status)throw new a.util.jIOError("Cannot find document: "+c,404);throw b}function g(b,d){var g,h;return(new c.Queue).push(function(){return a.util.ajax({type:"GET",url:s.expand({pageToken:b.nextPageToken||"",access_token:d})})}).push(function(a){for(h=e.parse(a.target.response||a.target.responseText),g=0;g<h.items.length;g+=1)h.items[g].value={},b.push(h.items[g]);return b.nextPageToken=h.nextPageToken,b},f)}function h(b){if("enclosure"!==b)throw new a.util.jIOError("Only support 'enclosure' attachment",400)}function i(a){if(void 0===a||void 0===a.access_token||"string"!=typeof a.access_token)throw new TypeError("Access Token must be a string which contains more than one character.");if(void 0!==a.trashing&&a.trashing!==!0&&a.trashing!==!1)throw new TypeError("trashing parameter must be a boolean (true or false)");this._trashing=a.trashing||!0,this._access_token=a.access_token}function j(a,b){return(new c.Queue).push(function(){return g(a,b)}).push(function(){return a.nextPageToken?j(a,b):a})}function k(b,d,g){var h="-------314159265358979323846";return(new c.Queue).push(function(){return a.util.ajax({type:b?"PUT":"POST",url:o.expand({access_token:g,id:b||[],upload:b?[]:"upload",uploadType:"multipart"}),headers:{"Content-Type":'multipart/related; boundary="'+h+'"'},data:"--"+h+"\nContent-Type: application/json; charset=UTF-8\n\n"+e.stringify(d)+"\n\n--"+h+"--"})}).push(function(a){var b=e.parse(a.target.responseText);return b.id},function(a){f(a,b)})}function l(b,d,g){return(new c.Queue).push(function(){return a.util.ajax({type:"PUT",url:o.expand({access_token:g,upload:"upload",id:b,uploadType:"media"}),data:d})}).push(function(b){if(b=e.parse(b.target.responseText),"application/vnd.google-apps.folder"===b.mimeType)throw new a.util.jIOError("cannot put attachments to folder",400);return b},function(a){f(a,b)})}function m(d,g,h){return(new c.Queue).push(function(){return a.util.ajax({type:"GET",dataType:g?"blob":"json",url:u.expand({id:d,alt:g?"media":[],access_token:h}),headers:{Authorization:"Bearer "+h}})}).push(function(a){return a.target.response||(g?new b([a.target.responseText],{type:a.target.responseHeaders["Content-Type"]}):e.parse(a.target.responseText))},function(a){f(a,d)})}var n="https://www.googleapis.com{/upload}/drive/v2/files{/id}{?uploadType,access_token}",o=d.parse(n),p="https://www.googleapis.com/drive/v2/files{/id,trash}{?access_token}",q=d.parse(p),r="https://www.googleapis.com/drive/v2/files?prettyPrint=false{&pageToken}&q=trashed=false&fields=nextPageToken,items(id){&access_token}",s=d.parse(r),t="https://www.googleapis.com/drive/v2/files{/id}{?alt}",u=d.parse(t);i.prototype.hasCapacity=function(a){return"list"===a},i.prototype.buildQuery=function(){return j([],this._access_token)},i.prototype.put=function(a,b){return k(a,b,this._access_token)},i.prototype.post=function(a){return k(void 0,a,this._access_token)},i.prototype.putAttachment=function(a,b,c){return h(b),l(a,c,this._access_token)},i.prototype.remove=function(b){var d=this;return(new c.Queue).push(function(){return a.util.ajax({type:d._trashing?"POST":"DELETE",url:q.expand({id:b,access_token:d._access_token,trash:d._trashing?"trash":[]})})}).push(void 0,function(a){f(a,b)})},i.prototype.get=function(a){return m(a,!1,this._access_token)},i.prototype.getAttachment=function(a,b){return h(b),m(a,!0,this._access_token)},i.prototype.allAttachments=function(a){var b=this._access_token;return(new c.Queue).push(function(){return m(a,!1,b)}).push(function(a){return"application/vnd.google-apps.folder"===a.mimeType?{}:{enclosure:{}}})},a.addStorage("gdrive",i)}(jIO,Blob,RSVP,UriTemplate,JSON),function(a,b){"use strict";function c(b){if(!Array.isArray(b.storage_list))throw new a.util.jIOError("storage_list is not an Array",400);var c;for(this._storage_list=[],c=0;c<b.storage_list.length;c+=1)this._storage_list.push(a.createJIO(b.storage_list[c]))}c.prototype._getWithStorageIndex=function(){function b(b){g.push(void 0,function(c){if(c instanceof a.util.jIOError&&404===c.status_code)return e._storage_list[b].get.apply(e._storage_list[b],f).push(function(a){return d=b,a});throw c})}var c,d=0,e=this,f=arguments,g=this._storage_list[0].get.apply(this._storage_list[0],f);for(c=1;c<this._storage_list.length;c+=1)b(c);return g.push(function(a){return[d,a]})},c.prototype.get=function(){return this._getWithStorageIndex.apply(this,arguments).push(function(a){return a[1]})},c.prototype.allAttachments=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.allAttachments.apply(d,a)})},c.prototype.post=function(){return this._storage_list[0].post.apply(this._storage_list[0],arguments)},c.prototype.put=function(){var b=arguments,c=this;return this._getWithStorageIndex(b[0]).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return[0];throw b}).push(function(a){var d=c._storage_list[a[0]];return d.put.apply(d,b)})},c.prototype.remove=function(){var a=arguments,b=this;return this._getWithStorageIndex(a[0]).push(function(c){var d=b._storage_list[c[0]];return d.remove.apply(d,a)})},c.prototype.buildQuery=function(){var a,c,d=[],e={},f=this._storage_list.length;for(a=0;f>a;a+=1)c=this._storage_list[a],d.push(c.buildQuery.apply(c,arguments));return(new b.Queue).push(function(){return b.all(d)}).push(function(b){var c,d,g,h=[];for(f=b.length,a=0;f>a;a+=1)for(c=b[a],d=c.length,g=0;d>g;g+=1)e.hasOwnProperty(c[g].id)||(e[c[g].id]=null,h.push(c[g]));return h})},c.prototype.hasCapacity=function(a){var b,c,d,e;if("list"===a||"query"===a||"select"===a){for(d=!0,c=this._storage_list.length,b=0;c>b;b+=1)e=this._storage_list[b],d=d&&e.hasCapacity(a);return d}return!1},c.prototype.repair=function(){var a,c=[];for(a=0;a<this._storage_list.length;a+=1)c.push(this._storage_list[a].repair.apply(this._storage_list[a],arguments));return b.all(c)},c.prototype.getAttachment=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.getAttachment.apply(d,a)})},c.prototype.putAttachment=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.putAttachment.apply(d,a)})},c.prototype.removeAttachment=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.removeAttachment.apply(d,a)})},a.addStorage("union",c)}(jIO,RSVP),function(a,b,c,d,e,f,g,h){"use strict";function i(b){return(new d.Queue).push(function(){return a.util.ajax({type:"GET",url:b._url,xhrFields:{withCredentials:!0}})}).push(function(a){return JSON.parse(a.target.responseText)})}function j(c,e,f){return void 0===f&&(f={}),i(c).push(function(c){return(new d.Queue).push(function(){return a.util.ajax({type:"GET",url:b.parse(c._links.traverse.href).expand({relative_url:e,view:f._view}),xhrFields:{withCredentials:!0}})}).push(void 0,function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document: "+e,404);throw b})})}function k(a){return(new d.Queue).push(function(){var b,c,d,f,g=a._embedded._view,h={portal_type:a._links.type.name
+},i={};a._links.hasOwnProperty("parent")&&(h.parent_relative_url=new e(a._links.parent.href).segment(2)),i.form_id={key:[g.form_id.key],"default":g.form_id["default"]};for(c in g)g.hasOwnProperty(c)&&(b=g[c],d=0,0===c.indexOf("my_")&&b.editable&&(d=3),0===c.indexOf("your_")&&(d=5),0!==d&&q.hasOwnProperty(b.type)&&(i[c.substring(d)]={"default":b["default"],key:b.key},h[c.substring(d)]=b["default"]));return f={data:h,form_data:i},g.hasOwnProperty("_actions")&&g._actions.hasOwnProperty("put")&&(f.action_href=g._actions.put.href),f})}function l(b,c){return b.getAttachment(c,"view").push(function(b){return a.util.readBlobAsText(b)}).push(function(a){return JSON.parse(a.target.result)}).push(function(a){return k(a)})}function m(a){if("string"!=typeof a.url||!a.url)throw new TypeError("ERP5 'url' must be a string which contains more than one character.");this._url=a.url,this._default_view_reference=a.default_view_reference}function n(a){var b,c=a.data;for(b in c)c.hasOwnProperty(b)&&(c[b]||delete c[b]);return c}function o(a){return a instanceof g&&"local_roles"===a.key?a.value:void 0}function p(a){var b,c,d=!0,e=[];if(a instanceof h&&"OR"===a.operator){for(b=0;b<a.query_list.length;b+=1)c=a.query_list[b],c instanceof g&&"local_roles"===c.key?e.push(c.value):d=!1;if(d)return e}}var q={StringField:null,EmailField:null,IntegerField:null,FloatField:null,TextAreaField:null};m.prototype.get=function(a){return l(this,a).push(function(a){return n(a)})},m.prototype.bulk=function(b){var e,f=this,g=[];for(e=0;e<b.length;e+=1){if("get"!==b[e].method)throw new Error("ERP5Storage: not supported "+b[e].method+" in bulk");g.push({relative_url:b[e].parameter_list[0],view:f._default_view_reference})}return i(f).push(function(b){var d=new c;return d.append("bulk_list",JSON.stringify(g)),a.util.ajax({type:"POST",url:b._actions.bulk.href,data:d,xhrFields:{withCredentials:!0}})}).push(function(a){function b(a){return k(a).push(function(a){return n(a)})}var c=[],f=JSON.parse(a.target.responseText);for(e=0;e<f.result_list.length;e+=1)c.push(b(f.result_list[e]));return d.all(c)})},m.prototype.post=function(b){var d,f=this;return i(this).push(function(d){var e=new c;return e.append("portal_type",b.portal_type),e.append("parent_relative_url",b.parent_relative_url),a.util.ajax({type:"POST",url:d._actions.add.href,data:e,xhrFields:{withCredentials:!0}})}).push(function(a){var c=a.target.getResponseHeader("X-Location"),g=new e(c);return d=g.segment(2),f.put(d,b)}).push(function(){return d})},m.prototype.put=function(b,c){var d=this;return l(d,b).push(function(e){var g,h=e.form_data,i={};i[h.form_id.key]=h.form_id["default"];for(g in c)if(c.hasOwnProperty(g)){if("form_id"===g)throw new a.util.jIOError("ERP5: forbidden property: "+g,400);if("portal_type"!==g&&"parent_relative_url"!==g){if(!h.hasOwnProperty(g))throw new a.util.jIOError("ERP5: can not store property: "+g,400);i[h[g].key]=c[g]}}if(!e.hasOwnProperty("action_href"))throw new a.util.jIOError("ERP5: can not modify document: "+b,403);return d.putAttachment(b,e.action_href,new f([JSON.stringify(i)],{type:"application/json"}))})},m.prototype.allAttachments=function(a){var b=this;return j(this,a).push(function(){return void 0===b._default_view_reference?{links:{}}:{view:{},links:{}}})},m.prototype.getAttachment=function(b,c,e){if(void 0===e&&(e={}),"view"===c){if(void 0===this._default_view_reference)throw new a.util.jIOError("Cannot find attachment view for: "+b,404);return j(this,b,{_view:this._default_view_reference}).push(function(a){var b=JSON.parse(a.target.responseText);return new f([JSON.stringify(b)],{type:"application/hal+json"})})}if("links"===c)return j(this,b).push(function(a){return new f([JSON.stringify(JSON.parse(a.target.responseText))],{type:"application/hal+json"})});if(0===c.indexOf(this._url))return(new d.Queue).push(function(){var b,d,f,g={type:"GET",dataType:"blob",url:c,xhrFields:{withCredentials:!0}};if(void 0!==e.start||void 0!==e.end){if(b=e.start||0,d=e.end,void 0!==d&&0>d)throw new a.util.jIOError("end must be positive",400);if(0>b)f="bytes="+b;else if(void 0===d)f="bytes="+b+"-";else{if(b>d)throw new a.util.jIOError("start is greater than end",400);f="bytes="+b+"-"+d}g.headers={Range:f}}return a.util.ajax(g)}).push(function(a){return void 0===a.target.response?new f([a.target.responseText],{type:a.target.getResponseHeader("Content-Type")}):a.target.response});throw new a.util.jIOError("ERP5: not support get attachment: "+c,400)},m.prototype.putAttachment=function(b,e,f){if(0!==e.indexOf(this._url))throw new a.util.jIOError("Can not store outside ERP5: "+e,400);return(new d.Queue).push(function(){return a.util.readBlobAsText(f)}).push(function(b){var d,f,g,h,i=JSON.parse(b.target.result),j=new c;for(g in i)if(i.hasOwnProperty(g))for(d=Array.isArray(i[g])?i[g]:[i[g]],f=0;f<d.length;f+=1)h=d[f],"object"==typeof h?j.append(g,a.util.dataURItoBlob(h.url),h.file_name):j.append(g,h);return a.util.ajax({type:"POST",url:e,data:j,xhrFields:{withCredentials:!0}})})},m.prototype.hasCapacity=function(a){return"list"===a||"query"===a||"select"===a||"limit"===a||"sort"===a},m.prototype.buildQuery=function(c){return i(this).push(function(d){var e,f,g,i,j,k=c.query,l=[];if(c.query)if(f=a.QueryFactory.create(c.query),i=o(f))k=void 0,j=i;else if(i=p(f))k=void 0,j=i;else if(f instanceof h&&"AND"===f.operator)for(e=0;e<f.query_list.length;e+=1)g=f.query_list[e],i=o(g),i?(j=i,f.query_list.splice(e,1),k=a.Query.objectToSearchText(f),e=f.query_list.length):(i=p(g),i&&(j=i,f.query_list.splice(e,1),k=a.Query.objectToSearchText(f),e=f.query_list.length));if(c.sort_on){for(e=0;e<c.sort_on.length;e+=1)l.push(JSON.stringify(c.sort_on[e]));c.sort_on=l}return a.util.ajax({type:"GET",url:b.parse(d._links.raw_search.href).expand({query:k,select_list:c.select_list||["title","reference"],limit:c.limit,sort_on:c.sort_on,local_roles:j}),xhrFields:{withCredentials:!0}})}).push(function(a){return JSON.parse(a.target.responseText)}).push(function(a){var b,c,d,f=a._embedded.contents,g=f.length,h=[];for(b=0;g>b;b+=1)d=f[b],c=new e(d._links.self.href),delete d._links,h.push({id:c.segment(2),value:d});return h})},a.addStorage("erp5",m)}(jIO,UriTemplate,FormData,RSVP,URI,Blob,SimpleQuery,ComplexQuery),function(a,b){"use strict";function c(b){this._sub_storage=a.createJIO(b.sub_storage),this._key_schema=b.key_schema}c.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},c.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},c.prototype.post=function(){return this._sub_storage.post.apply(this._sub_storage,arguments)},c.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},c.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},c.prototype.getAttachment=function(){return this._sub_storage.getAttachment.apply(this._sub_storage,arguments)},c.prototype.putAttachment=function(){return this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},c.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},c.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},c.prototype.hasCapacity=function(a){var b=["limit","sort","select","query"];return-1!==b.indexOf(a)?!0:"list"===a?this._sub_storage.hasCapacity(a):!1},c.prototype.buildQuery=function(c){var d=this._sub_storage,e=this,f={},g=!1,h=!1;if(d.hasCapacity("list")){try{void 0!==c.query&&!d.hasCapacity("query")||void 0!==c.sort_on&&!d.hasCapacity("sort")||void 0!==c.select_list&&!d.hasCapacity("select")||void 0!==c.limit&&!d.hasCapacity("limit")||(f.query=c.query,f.sort_on=c.sort_on,f.select_list=c.select_list,f.limit=c.limit)}catch(i){if(!(i instanceof a.util.jIOError&&501===i.status_code))throw i;g=!0}try{(g||c.include_docs===!0)&&d.hasCapacity("include")&&(f.include_docs=!0)}catch(i){if(!(i instanceof a.util.jIOError&&501===i.status_code))throw i;h=!0}return d.buildQuery(f).push(function(c){function e(b){var e=c[b].id;return d.get(e).push(function(a){return a._id=e,a},function(b){if(!(b instanceof a.util.jIOError&&404===b.status_code))throw b})}var f,g,i=[c];if(h){for(f=c.length,g=0;f>g;g+=1)i.push(e(g));c=b.all(i)}return c}).push(function(a){var b,c,d;if(h){for(b=a[0],c=b.length,d=0;c>d;d+=1)b[d].doc=a[d+1];a=b}return a}).push(function(b){var d,f,h=[];if(g){for(d=b.length,f=0;d>f;f+=1)b[f].doc.__id=b[f].id,h.push(b[f].doc);c.select_list&&c.select_list.push("__id"),b=a.QueryFactory.create(c.query||"",e._key_schema).exec(h,c)}return b}).push(function(a){var b,d,e,f=[];if(g){for(d=a.length,e=0;d>e;e+=1){if(b={id:a[e].__id,value:c.select_list?a[e]:{},doc:{}},c.select_list&&delete b.value.__id,c.include_docs)throw new Error("QueryStorage does not support include docs");f.push(b)}a=f}return a})}},a.addStorage("query",c)}(jIO,RSVP),function(a,b,c){"use strict";function d(b){this._sub_storage=a.createJIO(b.sub_storage)}function e(a,b){return-1!==a.indexOf(b,a.length-b.length)}var f=".json",g="/.jio_documents/",h="/";d.prototype.get=function(c){var d=this;return(new b.Queue).push(function(){return d._sub_storage.getAttachment(g,c+f,{format:"json"})}).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return d._sub_storage.allAttachments(h).push(function(b){if(b.hasOwnProperty(c))return{};throw new a.util.jIOError("Cannot find document "+c,404)});throw b})},d.prototype.allAttachments=function(b){var c=this;return c._sub_storage.allAttachments(h).push(function(d){return d.hasOwnProperty(b)?{enclosure:{}}:c._sub_storage.getAttachment(g,b+f).push(function(){return{}},function(c){if(c instanceof a.util.jIOError&&404===c.status_code)throw new a.util.jIOError("Cannot find document "+b,404);throw c})})},d.prototype.put=function(b,d){var e=this;return e._sub_storage.putAttachment(g,b+f,new c([JSON.stringify(d)],{type:"application/json"})).push(void 0,function(h){if(h instanceof a.util.jIOError&&404===h.status_code)return e._sub_storage.put(g,{}).push(function(){return e._sub_storage.putAttachment(g,b+f,new c([JSON.stringify(d)],{type:"application/json"}))});throw h}).push(function(){return b})},d.prototype.remove=function(c){var d=this,e=!1;return(new b.Queue).push(function(){return d._sub_storage.removeAttachment(h,c)}).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return void(e=!0);throw b}).push(function(){return d._sub_storage.removeAttachment(g,c+f)}).push(void 0,function(b){if(!e&&b instanceof a.util.jIOError&&404===b.status_code)return c;throw b})},d.prototype.hasCapacity=function(a){return"list"===a},d.prototype.buildQuery=function(){var c={},d=this;return(new b.Queue).push(function(){return d._sub_storage.allAttachments(g)}).push(function(a){var b;for(b in a)a.hasOwnProperty(b)&&e(b,f)&&(c[b.substring(0,b.length-f.length)]=null)},function(b){if(!(b instanceof a.util.jIOError&&404===b.status_code))throw b}).push(function(){return d._sub_storage.allAttachments(h)}).push(function(a){var b;for(b in a)a.hasOwnProperty(b)&&(c[b]=null)}).push(function(){var a,b=[];for(a in c)c.hasOwnProperty(a)&&b.push({id:a,value:{}});return b})},d.prototype.getAttachment=function(b,c){if("enclosure"!==c)throw new a.util.jIOError("Only support 'enclosure' attachment",400);return this._sub_storage.getAttachment(h,b)},d.prototype.putAttachment=function(b,c,d){if("enclosure"!==c)throw new a.util.jIOError("Only support 'enclosure' attachment",400);return this._sub_storage.putAttachment(h,b,d)},d.prototype.removeAttachment=function(b,c){if("enclosure"!==c)throw new a.util.jIOError("Only support 'enclosure' attachment",400);return this._sub_storage.removeAttachment(h,b)},d.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},a.addStorage("drivetojiomapping",d)}(jIO,RSVP,Blob),function(a,b,c,d,e){"use strict";function f(b){this._sub_storage=a.createJIO(b.sub_storage),this._document_id=b.document_id,this._repair_attachment=b.repair_attachment||!1}function g(a,b){return void 0===b?"jio_document/"+d(a)+h:"jio_attachment/"+d(a)+"/"+d(b)}var h=".json",i=new RegExp("^jio_document/([\\w=]+)"+h+"$"),j=new RegExp("^jio_attachment/([\\w=]+)/([\\w=]+)$");f.prototype.get=function(a){return this._sub_storage.getAttachment(this._document_id,g(a),{format:"json"})},f.prototype.allAttachments=function(a){return this._sub_storage.allAttachments(this._document_id).push(function(b){var d,e,f={};for(e in b)if(b.hasOwnProperty(e)&&j.test(e)){d=j.exec(e);try{c(d[1])===a&&(f[c(d[2])]={})}catch(g){if(!g instanceof ReferenceError)throw g}}return f})},f.prototype.put=function(a,c){return this._sub_storage.putAttachment(this._document_id,g(a),new b([JSON.stringify(c)],{type:"application/json"})).push(function(){return a})},f.prototype.remove=function(a){var b=this;return this.allAttachments(a).push(function(c){var d,f=[];for(d in c)c.hasOwnProperty(d)&&f.push(b.removeAttachment(a,d));return e.all(f)}).push(function(){return b._sub_storage.removeAttachment(b._document_id,g(a))}).push(function(){return a})},f.prototype.repair=function(){var a=this;return this._sub_storage.repair.apply(this._sub_storage,arguments).push(function(b){return a._repair_attachment?a._sub_storage.allAttachments(a._document_id).push(function(b){var d,f,g,h,k=[],l={},m={};for(h in b)if(b.hasOwnProperty(h))if(d=void 0,f=void 0,i.test(h)){try{d=c(i.exec(h)[1])}catch(n){if(!n instanceof ReferenceError)throw n}void 0!==d&&(l[d]=null)}else if(j.test(h)){g=j.exec(h);try{d=c(g[1]),f=c(g[2])}catch(n){if(!n instanceof ReferenceError)throw n}void 0!==f&&(l.hasOwnProperty(d)||(m.hasOwnProperty(d)||(m[d]={}),m[d][f]=null))}for(d in m)if(m.hasOwnProperty(d)&&!l.hasOwnProperty(d))for(f in m[d])m[d].hasOwnProperty(f)&&k.push(a.removeAttachment(d,f));return e.all(k)}):b})},f.prototype.hasCapacity=function(a){return"list"===a},f.prototype.buildQuery=function(){return this._sub_storage.allAttachments(this._document_id).push(function(a){var b,d=[];for(b in a)if(a.hasOwnProperty(b)&&i.test(b))try{d.push({id:c(i.exec(b)[1]),value:{}})}catch(e){if(!e instanceof ReferenceError)throw e}return d})},f.prototype.getAttachment=function(a,b){return this._sub_storage.getAttachment(this._document_id,g(a,b))},f.prototype.putAttachment=function(a,b,c){return this._sub_storage.putAttachment(this._document_id,g(a,b),c)},f.prototype.removeAttachment=function(a,b){return this._sub_storage.removeAttachment(this._document_id,g(a,b))},a.addStorage("document",f)}(jIO,Blob,atob,btoa,RSVP),function(a,b,c,d){"use strict";function e(a){a.sessiononly===!0?this._storage=b:this._storage=c}function f(b){if("/"!==b)throw new a.util.jIOError("id "+b+" is forbidden (!== /)",400)}e.prototype.get=function(a){return f(a),{}},e.prototype.allAttachments=function(a){f(a);var b,c={};for(b in this._storage)this._storage.hasOwnProperty(b)&&(c[b]={});return c},e.prototype.getAttachment=function(b,c){f(b);var d=this._storage.getItem(c);if(null===d)throw new a.util.jIOError("Cannot find attachment "+c,404);return a.util.dataURItoBlob(d)},e.prototype.putAttachment=function(b,c,e){var g=this;return f(b),(new d.Queue).push(function(){return a.util.readBlobAsDataURL(e)}).push(function(a){g._storage.setItem(c,a.target.result)})},e.prototype.removeAttachment=function(a,b){return f(a),this._storage.removeItem(b)},e.prototype.hasCapacity=function(a){return"list"===a},e.prototype.buildQuery=function(){return[{id:"/",value:{}}]},a.addStorage("local",e)}(jIO,sessionStorage,localStorage,RSVP),function(a,b,c,d,e,f){"use strict";function g(a){if("string"!=typeof a.database||""===a.database)throw new TypeError("IndexedDBStorage 'database' description property must be a non-empty string");this._database_name="jio:"+a.database}function h(a){return a.join("_")}function i(a){var b,c=a.target.result;b=c.createObjectStore("metadata",{keyPath:"_id",autoIncrement:!1}),b.createIndex("_id","_id",{unique:!0}),b=c.createObjectStore("attachment",{keyPath:"_key_path",autoIncrement:!1}),b.createIndex("_id","_id",{unique:!1}),b=c.createObjectStore("blob",{keyPath:"_key_path",autoIncrement:!1}),b.createIndex("_id_attachment",["_id","_attachment"],{unique:!1}),b.createIndex("_id","_id",{unique:!1})}function j(b){function d(b,c){var d=a.open(e);d.onerror=function(a){d.result&&d.result.close(),c(a)},d.onabort=function(){d.result.close(),c("Aborting connection to: "+e)},d.ontimeout=function(){d.result.close(),c("Connection to: "+e+" timeout")},d.onblocked=function(){d.result.close(),c("Connection to: "+e+" was blocked")},d.onupgradeneeded=i,d.onversionchange=function(){d.result.close(),c(e+" was upgraded")},d.onsuccess=function(){b(d.result)}}var e=b._database_name;return(new c.Queue).push(function(){return new c.Promise(d)})}function k(a,b,c,d){var e=a.transaction(b,c);return d!==!1&&(e.oncomplete=function(){a.close()}),e.onabort=function(){a.close()},e}function l(a,b){function d(c,d){a.onerror=function(b){a.transaction&&a.transaction.abort(),d(b)},a.onsuccess=function(a){var e=a.target.result;if(e){try{b(e)}catch(f){d(f)}e["continue"]()}else c()}}return new c.Promise(d)}function m(a){function d(c,d){a.onerror=d,a.onsuccess=function(){a.result&&c(a.result),d(new b.util.jIOError("Cannot find document",404))}}return new c.Promise(d)}function n(a){function b(b,c){a.onerror=c,a.onsuccess=function(){b(a.result)}}return new c.Promise(b)}function o(a){a["delete"]()}function p(a,b,d){return c.all([n(a.objectStore("attachment")["delete"](h([b,d]))),l(a.objectStore("blob").index("_id_attachment").openCursor(f.only([b,d])),o)])}var q=2e6;g.prototype.hasCapacity=function(a){return"list"===a||"include"===a},g.prototype.buildQuery=function(a){function b(a){d.push({id:a.key,value:{},doc:a.value.doc})}function c(a){d.push({id:a.key,value:{}})}var d=[];return j(this).push(function(d){var e=k(d,["metadata"],"readonly");return a.include_docs===!0?l(e.objectStore("metadata").index("_id").openCursor(),b):l(e.objectStore("metadata").index("_id").openKeyCursor(),c)}).push(function(){return d})},g.prototype.get=function(a){return j(this).push(function(b){var c=k(b,["metadata"],"readonly");return m(c.objectStore("metadata").get(a))}).push(function(a){return a.doc})},g.prototype.allAttachments=function(a){function b(a){d[a.value._attachment]={}}var d={};return j(this).push(function(d){var e=k(d,["metadata","attachment"],"readonly");return c.all([m(e.objectStore("metadata").get(a)),l(e.objectStore("attachment").index("_id").openCursor(f.only(a)),b)])}).push(function(){return d})},g.prototype.put=function(a,b){return j(this).push(function(c){var d=k(c,["metadata"],"readwrite");return n(d.objectStore("metadata").put({_id:a,doc:b}))})},g.prototype.remove=function(a){return j(this).push(function(b){var d=k(b,["metadata","attachment","blob"],"readwrite");return c.all([n(d.objectStore("metadata")["delete"](a)),l(d.objectStore("attachment").index("_id").openCursor(f.only(a)),o),l(d.objectStore("blob").index("_id").openCursor(f.only(a)),o)])})},g.prototype.getAttachment=function(a,f,g){var i,l,n,o;return void 0===g&&(g={}),j(this).push(function(b){return i=k(b,["attachment","blob"],"readonly"),m(i.objectStore("attachment").get(h([a,f])))}).push(function(d){var j,k,p,r=d.info.length,s=[],t=i.objectStore("blob");if(l=d.info.content_type,n=g.start||0,o=g.end||r,o>r&&(o=r),0>n||0>o)throw new b.util.jIOError("_start and _end must be positive",400);if(n>o)throw new b.util.jIOError("_start is greater than _end",400);for(k=e.floor(n/q),p=e.floor(o/q),o%q===0&&(p-=1),j=k;p>=j;j+=1)s.push(m(t.get(h([a,f,j]))));return c.all(s)}).push(function(a){var b,c,f,h=[],i=a.length;for(c=0;i>c;c+=1)h.push(a[c].blob);return void 0===g.start&&void 0===g.end?new d(h,{type:l}):(f=e.floor(n/q)*q,b=new d(h,{type:"application/octet-stream"}),b.slice(n-f,o-f,"application/octet-stream"))})},g.prototype.putAttachment=function(a,d,e){var f,g,i=[];return j(this).push(function(a){return g=a,b.util.readBlobAsArrayBuffer(e)}).push(function(b){for(var c=b.target.result,h=e.size,j=0;h>j;)i.push(c.slice(j,j+q)),j+=q;return f=k(g,["attachment","blob"],"readwrite"),p(f,a,d)}).push(function(){var b,g=[n(f.objectStore("attachment").put({_key_path:h([a,d]),_id:a,_attachment:d,info:{content_type:e.type,length:e.size}}))],j=i.length,k=f.objectStore("blob");for(b=0;j>b;b+=1)g.push(n(k.put({_key_path:h([a,d,b]),_id:a,_attachment:d,_part:b,blob:i[b]})));return c.all(g)})},g.prototype.removeAttachment=function(a,b){return j(this).push(function(c){var d=k(c,["attachment","blob"],"readwrite");return p(d,a,b)})},b.addStorage("indexeddb",g)}(indexedDB,jIO,RSVP,Blob,Math,IDBKeyRange),function(a,b,c,d,e,f,g){"use strict";function h(b){this._key=b.key,this._jsonKey=!0,this._sub_storage=a.createJIO(b.sub_storage)}function i(a){return(new b.Queue).push(function(){return e.subtle.importKey("jwk",a._key,"AES-GCM",!1,["encrypt","decrypt"])}).push(function(b){a._key=b,a._jsonKey=!1})}var j="application/x-jio-aes-gcm-encryption";h.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},h.prototype.post=function(){return this._sub_storage.post.apply(this._sub_storage,arguments)},h.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},h.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},h.prototype.hasCapacity=function(){return this._sub_storage.hasCapacity.apply(this._sub_storage,arguments)},h.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},h.prototype.putAttachment=function(c,h,k){var l=e.getRandomValues(new f(12)),m=this;return(new b.Queue).push(function(){return m._jsonKey===!0?i(m):void 0}).push(function(){return a.util.readBlobAsDataURL(k)}).push(function(a){var b,c=a.currentTarget.result.length,d=new g(c),h=new f(d);for(a=a.currentTarget.result,b=0;c>b;b+=1)h[b]=a.charCodeAt(b);return e.subtle.encrypt({name:"AES-GCM",iv:l},m._key,d)}).push(function(a){var b=new d([l,a],{type:j});return m._sub_storage.putAttachment(c,h,b)})},h.prototype.getAttachment=function(d,g){var h=this;return h._sub_storage.getAttachment(d,g).push(function(d){return d.type!==j?d:(new b.Queue).push(function(){return h._jsonKey===!0?i(h):void 0}).push(function(){return a.util.readBlobAsArrayBuffer(d)}).push(function(g){var i;return g=g.currentTarget.result,i=new f(g.slice(0,12)),(new b.Queue).push(function(){return e.subtle.decrypt({name:"AES-GCM",iv:i},h._key,g.slice(12))}).push(function(b){return b=String.fromCharCode.apply(null,new f(b)),a.util.dataURItoBlob(b)}).push(void 0,function(a){if(a instanceof c)return d;throw a})})})},h.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},h.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},a.addStorage("crypt",h)}(jIO,RSVP,DOMException,Blob,crypto,Uint8Array,ArrayBuffer),function(a,b,c,d){"use strict";function e(a,c,d){return new b.Promise(function(b,e){a.transaction(function(a){function f(a,c){j.push(c),j.length===i&&b(j)}function g(a,b){return e(b),!0}var h,i=c.length,j=[];for(h=0;i>h;h+=1)a.executeSql(c[h],d[h],f,g)},function(a,b){e(b)})})}function f(a){var c=["CREATE TABLE IF NOT EXISTS document(id VARCHAR PRIMARY KEY NOT NULL, data TEXT)","CREATE TABLE IF NOT EXISTS attachment(id VARCHAR, attachment VARCHAR, part INT, blob TEXT)","CREATE TRIGGER IF NOT EXISTS removeAttachment BEFORE DELETE ON document FOR EACH ROW BEGIN DELETE from attachment WHERE id = OLD.id;END;","CREATE INDEX IF NOT EXISTS index_document ON document (id);","CREATE INDEX IF NOT EXISTS index_attachment ON attachment (id, attachment);"];return(new b.Queue).push(function(){return e(a,c,[])})}function g(a){if("string"!=typeof a.database||!a.database)throw new TypeError("database must be a string which contains more than one character.");if(this._database=d("jio:"+a.database,"1.0","",2097152),a.blob_length&&("number"!=typeof a.blob_length||a.blob_length<20))throw new TypeError("blob_len parameter must be a number >= 20");this._blob_length=a.blob_length||2e6,this._init_db_promise=f(this._database)}function h(b,c,d,e){e.push(function(){return a.util.readBlobAsDataURL(b)}).push(function(a){c[d+2].push(a.currentTarget.result)})}g.prototype.put=function(a,c){var d=this._database,f=this,g=JSON.stringify(c);return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["INSERT OR REPLACE INTO document(id, data) VALUES(?,?)"],[[a,g]])}).push(function(){return a})},g.prototype.remove=function(c){var d=this._database,f=this;return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["DELETE FROM document WHERE id = ?"],[[c]])}).push(function(b){if(0===b[0].rowsAffected)throw new a.util.jIOError("Cannot find document",404);return c})},g.prototype.get=function(c){var d=this._database,f=this;return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["SELECT data FROM document WHERE id = ?"],[[c]])}).push(function(b){if(0===b[0].rows.length)throw new a.util.jIOError("Cannot find document",404);return JSON.parse(b[0].rows[0].data)})},g.prototype.allAttachments=function(c){var d=this._database,f=this;return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["SELECT id FROM document WHERE id = ?","SELECT DISTINCT attachment FROM attachment WHERE id = ?"],[[c],[c]])}).push(function(b){if(0===b[0].rows.length)throw new a.util.jIOError("Cannot find document",404);var c,d=b[1].rows.length,e={};for(c=0;d>c;c+=1)e[b[1].rows[c].attachment]={};return e})},g.prototype.putAttachment=function(c,d,f){var g=this._database,i=this,j=this._blob_length;return(new b.Queue).push(function(){return i._init_db_promise}).push(function(){return e(g,["SELECT id FROM document WHERE id = ?"],[[c]])}).push(function(i){var k,l,m=[],n=[],o=f.size,p=new b.Queue;if(0===i[0].rows.length)throw new a.util.jIOError("Cannot access subdocument",404);for(m.push("DELETE FROM attachment WHERE id = ? AND attachment = ?"),n.push([c,d]),m.push("INSERT INTO attachment(id, attachment, part, blob)VALUES(?, ?, ?, ?)"),n.push([c,d,-1,f.type||"application/octet-stream"]),k=0,l=0;o>k;k+=j,l+=1)m.push("INSERT INTO attachment(id, attachment, part, blob)VALUES(?, ?, ?, ?)"),n.push([c,d,l]),h(f.slice(k,k+j),n,l,p);return p.push(function(){return e(g,m,n)}),p})},g.prototype.getAttachment=function(d,f,g){var h,i,j,k,l=this._database,m=this,n=this._blob_length;if(void 0===g&&(g={}),h=g.start||0,i=g.end||-1,0>h||void 0!==g.end&&g.end<0)throw new a.util.jIOError("_start and _end must be positive",400);if(h>i&&-1!==i)throw new a.util.jIOError("_start is greater than _end",400);return j=Math.floor(h/n),0===h&&(j-=1),k=Math.floor(i/n),i%n===0&&(k-=1),(new b.Queue).push(function(){return m._init_db_promise}).push(function(){var a="SELECT part, blob FROM attachment WHERE id = ? AND attachment = ? AND part >= ?",b=[d,f,j];return-1!==i&&(a+=" AND part <= ?",b.push(k)),e(l,[a],[b])}).push(function(b){var d,e,f,k,l=[];if(e=b[0].rows,0===e.length)throw new a.util.jIOError("Cannot find document",404);for(d=0;d<e.length;d+=1)-1===e[d].part?(k=e[d].blob,j+=1):l.push(a.util.dataURItoBlob(e[d].blob));return 0===h&&void 0===g.end?new c(l,{type:k}):(f=new c(l,{}),f.slice(h-j*n,-1===i?f.size:i-j*n,"application/octet-stream"))})},g.prototype.removeAttachment=function(c,d){var f=this._database,g=this;return(new b.Queue).push(function(){return g._init_db_promise}).push(function(){return e(f,["DELETE FROM attachment WHERE id = ? AND attachment = ?"],[[c,d]])}).push(function(b){if(0===b[0].rowsAffected)throw new a.util.jIOError("Cannot find document",404);return d})},g.prototype.hasCapacity=function(a){return"list"===a||"include"===a},g.prototype.buildQuery=function(a){var c=this._database,d=this,f="SELECT id";return(new b.Queue).push(function(){return d._init_db_promise}).push(function(){return void 0===a&&(a={}),a.include_docs===!0&&(f+=", data AS doc"),f+=" FROM document",e(c,[f],[[]])}).push(function(a){var b,c=[],d=a[0].rows.length;for(b=0;d>b;b+=1)c.push(a[0].rows[b]),c[b].value={},void 0!==c[b].doc&&(c[b].doc=JSON.parse(c[b].doc));return c})},a.addStorage("websql",g)}(jIO,RSVP,Blob,openDatabase);
\ No newline at end of file
diff --git a/dist/jio-v3.11.0.js b/dist/jio-v3.11.0.js
new file mode 100644
index 0000000000000000000000000000000000000000..6a11dbee290f8e70855043333abf2b2ad8cfaed9
--- /dev/null
+++ b/dist/jio-v3.11.0.js
@@ -0,0 +1,12804 @@
+/*! URI.js v1.12.0 http://medialize.github.com/URI.js/ */
+/* build contains: IPv6.js, punycode.js, SecondLevelDomains.js, URI.js, URI.fragmentQuery.js */
+(function(e,k){"object"===typeof exports?module.exports=k():"function"===typeof define&&define.amd?define(k):e.IPv6=k(e)})(this,function(e){var k=e&&e.IPv6;return{best:function(e){e=e.toLowerCase().split(":");var k=e.length,d=8;""===e[0]&&""===e[1]&&""===e[2]?(e.shift(),e.shift()):""===e[0]&&""===e[1]?e.shift():""===e[k-1]&&""===e[k-2]&&e.pop();k=e.length;-1!==e[k-1].indexOf(".")&&(d=7);var g;for(g=0;g<k&&""!==e[g];g++);if(g<d)for(e.splice(g,1,"0000");e.length<d;)e.splice(g,0,"0000");for(g=0;g<d;g++){for(var k=
+e[g].split(""),q=0;3>q;q++)if("0"===k[0]&&1<k.length)k.splice(0,1);else break;e[g]=k.join("")}var k=-1,l=q=0,r=-1,z=!1;for(g=0;g<d;g++)z?"0"===e[g]?l+=1:(z=!1,l>q&&(k=r,q=l)):"0"==e[g]&&(z=!0,r=g,l=1);l>q&&(k=r,q=l);1<q&&e.splice(k,q,"");k=e.length;d="";""===e[0]&&(beststr=":");for(g=0;g<k;g++){d+=e[g];if(g===k-1)break;d+=":"}""===e[k-1]&&(d+=":");return d},noConflict:function(){e.IPv6===this&&(e.IPv6=k);return this}}});
+(function(e){function k(a){throw RangeError(p[a]);}function u(a,b){for(var c=a.length;c--;)a[c]=b(a[c]);return a}function m(a,b){return u(a.split(h),b).join(".")}function d(a){for(var b=[],c=0,d=a.length,h,p;c<d;)h=a.charCodeAt(c++),55296<=h&&56319>=h&&c<d?(p=a.charCodeAt(c++),56320==(p&64512)?b.push(((h&1023)<<10)+(p&1023)+65536):(b.push(h),c--)):b.push(h);return b}function g(a){return u(a,function(a){var b="";65535<a&&(a-=65536,b+=x(a>>>10&1023|55296),a=56320|a&1023);return b+=x(a)}).join("")}function q(a,
+b){return a+22+75*(26>a)-((0!=b)<<5)}function l(a,b,c){var d=0;a=c?A(a/H):a>>1;for(a+=A(a/b);a>n*y>>1;d+=s)a=A(a/n);return A(d+(n+1)*a/(a+I))}function r(b){var c=[],d=b.length,h,p=0,e=F,f=G,n,x,q,t,m;n=b.lastIndexOf(a);0>n&&(n=0);for(x=0;x<n;++x)128<=b.charCodeAt(x)&&k("not-basic"),c.push(b.charCodeAt(x));for(n=0<n?n+1:0;n<d;){x=p;h=1;for(q=s;;q+=s){n>=d&&k("invalid-input");t=b.charCodeAt(n++);t=10>t-48?t-22:26>t-65?t-65:26>t-97?t-97:s;(t>=s||t>A((w-p)/h))&&k("overflow");p+=t*h;m=q<=f?v:q>=f+y?y:
+q-f;if(t<m)break;t=s-m;h>A(w/t)&&k("overflow");h*=t}h=c.length+1;f=l(p-x,h,0==x);A(p/h)>w-e&&k("overflow");e+=A(p/h);p%=h;c.splice(p++,0,e)}return g(c)}function z(b){var c,h,p,e,f,n,g,m,r,t=[],B,u,z;b=d(b);B=b.length;c=F;h=0;f=G;for(n=0;n<B;++n)r=b[n],128>r&&t.push(x(r));for((p=e=t.length)&&t.push(a);p<B;){g=w;for(n=0;n<B;++n)r=b[n],r>=c&&r<g&&(g=r);u=p+1;g-c>A((w-h)/u)&&k("overflow");h+=(g-c)*u;c=g;for(n=0;n<B;++n)if(r=b[n],r<c&&++h>w&&k("overflow"),r==c){m=h;for(g=s;;g+=s){r=g<=f?v:g>=f+y?y:g-f;
+if(m<r)break;z=m-r;m=s-r;t.push(x(q(r+z%m,0)));m=A(z/m)}t.push(x(q(m,0)));f=l(h,u,p==e);h=0;++p}++h;++c}return t.join("")}var D="object"==typeof exports&&exports,E="object"==typeof module&&module&&module.exports==D&&module,C="object"==typeof global&&global;if(C.global===C||C.window===C)e=C;var f,w=2147483647,s=36,v=1,y=26,I=38,H=700,G=72,F=128,a="-",b=/^xn--/,c=/[^ -~]/,h=/\x2E|\u3002|\uFF0E|\uFF61/g,p={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)",
+"invalid-input":"Invalid input"},n=s-v,A=Math.floor,x=String.fromCharCode,B;f={version:"1.2.3",ucs2:{decode:d,encode:g},decode:r,encode:z,toASCII:function(a){return m(a,function(a){return c.test(a)?"xn--"+z(a):a})},toUnicode:function(a){return m(a,function(a){return b.test(a)?r(a.slice(4).toLowerCase()):a})}};if("function"==typeof define&&"object"==typeof define.amd&&define.amd)define(function(){return f});else if(D&&!D.nodeType)if(E)E.exports=f;else for(B in f)f.hasOwnProperty(B)&&(D[B]=f[B]);else e.punycode=
+f})(this);
+(function(e,k){"object"===typeof exports?module.exports=k():"function"===typeof define&&define.amd?define(k):e.SecondLevelDomains=k(e)})(this,function(e){var k=e&&e.SecondLevelDomains,u=Object.prototype.hasOwnProperty,m={list:{ac:"com|gov|mil|net|org",ae:"ac|co|gov|mil|name|net|org|pro|sch",af:"com|edu|gov|net|org",al:"com|edu|gov|mil|net|org",ao:"co|ed|gv|it|og|pb",ar:"com|edu|gob|gov|int|mil|net|org|tur",at:"ac|co|gv|or",au:"asn|com|csiro|edu|gov|id|net|org",ba:"co|com|edu|gov|mil|net|org|rs|unbi|unmo|unsa|untz|unze",bb:"biz|co|com|edu|gov|info|net|org|store|tv",
+bh:"biz|cc|com|edu|gov|info|net|org",bn:"com|edu|gov|net|org",bo:"com|edu|gob|gov|int|mil|net|org|tv",br:"adm|adv|agr|am|arq|art|ato|b|bio|blog|bmd|cim|cng|cnt|com|coop|ecn|edu|eng|esp|etc|eti|far|flog|fm|fnd|fot|fst|g12|ggf|gov|imb|ind|inf|jor|jus|lel|mat|med|mil|mus|net|nom|not|ntr|odo|org|ppg|pro|psc|psi|qsl|rec|slg|srv|tmp|trd|tur|tv|vet|vlog|wiki|zlg",bs:"com|edu|gov|net|org",bz:"du|et|om|ov|rg",ca:"ab|bc|mb|nb|nf|nl|ns|nt|nu|on|pe|qc|sk|yk",ck:"biz|co|edu|gen|gov|info|net|org",cn:"ac|ah|bj|com|cq|edu|fj|gd|gov|gs|gx|gz|ha|hb|he|hi|hl|hn|jl|js|jx|ln|mil|net|nm|nx|org|qh|sc|sd|sh|sn|sx|tj|tw|xj|xz|yn|zj",
+co:"com|edu|gov|mil|net|nom|org",cr:"ac|c|co|ed|fi|go|or|sa",cy:"ac|biz|com|ekloges|gov|ltd|name|net|org|parliament|press|pro|tm","do":"art|com|edu|gob|gov|mil|net|org|sld|web",dz:"art|asso|com|edu|gov|net|org|pol",ec:"com|edu|fin|gov|info|med|mil|net|org|pro",eg:"com|edu|eun|gov|mil|name|net|org|sci",er:"com|edu|gov|ind|mil|net|org|rochest|w",es:"com|edu|gob|nom|org",et:"biz|com|edu|gov|info|name|net|org",fj:"ac|biz|com|info|mil|name|net|org|pro",fk:"ac|co|gov|net|nom|org",fr:"asso|com|f|gouv|nom|prd|presse|tm",
+gg:"co|net|org",gh:"com|edu|gov|mil|org",gn:"ac|com|gov|net|org",gr:"com|edu|gov|mil|net|org",gt:"com|edu|gob|ind|mil|net|org",gu:"com|edu|gov|net|org",hk:"com|edu|gov|idv|net|org",id:"ac|co|go|mil|net|or|sch|web",il:"ac|co|gov|idf|k12|muni|net|org","in":"ac|co|edu|ernet|firm|gen|gov|i|ind|mil|net|nic|org|res",iq:"com|edu|gov|i|mil|net|org",ir:"ac|co|dnssec|gov|i|id|net|org|sch",it:"edu|gov",je:"co|net|org",jo:"com|edu|gov|mil|name|net|org|sch",jp:"ac|ad|co|ed|go|gr|lg|ne|or",ke:"ac|co|go|info|me|mobi|ne|or|sc",
+kh:"com|edu|gov|mil|net|org|per",ki:"biz|com|de|edu|gov|info|mob|net|org|tel",km:"asso|com|coop|edu|gouv|k|medecin|mil|nom|notaires|pharmaciens|presse|tm|veterinaire",kn:"edu|gov|net|org",kr:"ac|busan|chungbuk|chungnam|co|daegu|daejeon|es|gangwon|go|gwangju|gyeongbuk|gyeonggi|gyeongnam|hs|incheon|jeju|jeonbuk|jeonnam|k|kg|mil|ms|ne|or|pe|re|sc|seoul|ulsan",kw:"com|edu|gov|net|org",ky:"com|edu|gov|net|org",kz:"com|edu|gov|mil|net|org",lb:"com|edu|gov|net|org",lk:"assn|com|edu|gov|grp|hotel|int|ltd|net|ngo|org|sch|soc|web",
+lr:"com|edu|gov|net|org",lv:"asn|com|conf|edu|gov|id|mil|net|org",ly:"com|edu|gov|id|med|net|org|plc|sch",ma:"ac|co|gov|m|net|org|press",mc:"asso|tm",me:"ac|co|edu|gov|its|net|org|priv",mg:"com|edu|gov|mil|nom|org|prd|tm",mk:"com|edu|gov|inf|name|net|org|pro",ml:"com|edu|gov|net|org|presse",mn:"edu|gov|org",mo:"com|edu|gov|net|org",mt:"com|edu|gov|net|org",mv:"aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro",mw:"ac|co|com|coop|edu|gov|int|museum|net|org",mx:"com|edu|gob|net|org",my:"com|edu|gov|mil|name|net|org|sch",
+nf:"arts|com|firm|info|net|other|per|rec|store|web",ng:"biz|com|edu|gov|mil|mobi|name|net|org|sch",ni:"ac|co|com|edu|gob|mil|net|nom|org",np:"com|edu|gov|mil|net|org",nr:"biz|com|edu|gov|info|net|org",om:"ac|biz|co|com|edu|gov|med|mil|museum|net|org|pro|sch",pe:"com|edu|gob|mil|net|nom|org|sld",ph:"com|edu|gov|i|mil|net|ngo|org",pk:"biz|com|edu|fam|gob|gok|gon|gop|gos|gov|net|org|web",pl:"art|bialystok|biz|com|edu|gda|gdansk|gorzow|gov|info|katowice|krakow|lodz|lublin|mil|net|ngo|olsztyn|org|poznan|pwr|radom|slupsk|szczecin|torun|warszawa|waw|wroc|wroclaw|zgora",
+pr:"ac|biz|com|edu|est|gov|info|isla|name|net|org|pro|prof",ps:"com|edu|gov|net|org|plo|sec",pw:"belau|co|ed|go|ne|or",ro:"arts|com|firm|info|nom|nt|org|rec|store|tm|www",rs:"ac|co|edu|gov|in|org",sb:"com|edu|gov|net|org",sc:"com|edu|gov|net|org",sh:"co|com|edu|gov|net|nom|org",sl:"com|edu|gov|net|org",st:"co|com|consulado|edu|embaixada|gov|mil|net|org|principe|saotome|store",sv:"com|edu|gob|org|red",sz:"ac|co|org",tr:"av|bbs|bel|biz|com|dr|edu|gen|gov|info|k12|name|net|org|pol|tel|tsk|tv|web",tt:"aero|biz|cat|co|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel",
+tw:"club|com|ebiz|edu|game|gov|idv|mil|net|org",mu:"ac|co|com|gov|net|or|org",mz:"ac|co|edu|gov|org",na:"co|com",nz:"ac|co|cri|geek|gen|govt|health|iwi|maori|mil|net|org|parliament|school",pa:"abo|ac|com|edu|gob|ing|med|net|nom|org|sld",pt:"com|edu|gov|int|net|nome|org|publ",py:"com|edu|gov|mil|net|org",qa:"com|edu|gov|mil|net|org",re:"asso|com|nom",ru:"ac|adygeya|altai|amur|arkhangelsk|astrakhan|bashkiria|belgorod|bir|bryansk|buryatia|cbg|chel|chelyabinsk|chita|chukotka|chuvashia|com|dagestan|e-burg|edu|gov|grozny|int|irkutsk|ivanovo|izhevsk|jar|joshkar-ola|kalmykia|kaluga|kamchatka|karelia|kazan|kchr|kemerovo|khabarovsk|khakassia|khv|kirov|koenig|komi|kostroma|kranoyarsk|kuban|kurgan|kursk|lipetsk|magadan|mari|mari-el|marine|mil|mordovia|mosreg|msk|murmansk|nalchik|net|nnov|nov|novosibirsk|nsk|omsk|orenburg|org|oryol|penza|perm|pp|pskov|ptz|rnd|ryazan|sakhalin|samara|saratov|simbirsk|smolensk|spb|stavropol|stv|surgut|tambov|tatarstan|tom|tomsk|tsaritsyn|tsk|tula|tuva|tver|tyumen|udm|udmurtia|ulan-ude|vladikavkaz|vladimir|vladivostok|volgograd|vologda|voronezh|vrn|vyatka|yakutia|yamal|yekaterinburg|yuzhno-sakhalinsk",
+rw:"ac|co|com|edu|gouv|gov|int|mil|net",sa:"com|edu|gov|med|net|org|pub|sch",sd:"com|edu|gov|info|med|net|org|tv",se:"a|ac|b|bd|c|d|e|f|g|h|i|k|l|m|n|o|org|p|parti|pp|press|r|s|t|tm|u|w|x|y|z",sg:"com|edu|gov|idn|net|org|per",sn:"art|com|edu|gouv|org|perso|univ",sy:"com|edu|gov|mil|net|news|org",th:"ac|co|go|in|mi|net|or",tj:"ac|biz|co|com|edu|go|gov|info|int|mil|name|net|nic|org|test|web",tn:"agrinet|com|defense|edunet|ens|fin|gov|ind|info|intl|mincom|nat|net|org|perso|rnrt|rns|rnu|tourism",tz:"ac|co|go|ne|or",
+ua:"biz|cherkassy|chernigov|chernovtsy|ck|cn|co|com|crimea|cv|dn|dnepropetrovsk|donetsk|dp|edu|gov|if|in|ivano-frankivsk|kh|kharkov|kherson|khmelnitskiy|kiev|kirovograd|km|kr|ks|kv|lg|lugansk|lutsk|lviv|me|mk|net|nikolaev|od|odessa|org|pl|poltava|pp|rovno|rv|sebastopol|sumy|te|ternopil|uzhgorod|vinnica|vn|zaporizhzhe|zhitomir|zp|zt",ug:"ac|co|go|ne|or|org|sc",uk:"ac|bl|british-library|co|cym|gov|govt|icnet|jet|lea|ltd|me|mil|mod|national-library-scotland|nel|net|nhs|nic|nls|org|orgn|parliament|plc|police|sch|scot|soc",
+us:"dni|fed|isa|kids|nsn",uy:"com|edu|gub|mil|net|org",ve:"co|com|edu|gob|info|mil|net|org|web",vi:"co|com|k12|net|org",vn:"ac|biz|com|edu|gov|health|info|int|name|net|org|pro",ye:"co|com|gov|ltd|me|net|org|plc",yu:"ac|co|edu|gov|org",za:"ac|agric|alt|bourse|city|co|cybernet|db|edu|gov|grondar|iaccess|imt|inca|landesign|law|mil|net|ngo|nis|nom|olivetti|org|pix|school|tm|web",zm:"ac|co|com|edu|gov|net|org|sch"},has_expression:null,is_expression:null,has:function(d){return!!d.match(m.has_expression)},
+is:function(d){return!!d.match(m.is_expression)},get:function(d){return(d=d.match(m.has_expression))&&d[1]||null},noConflict:function(){e.SecondLevelDomains===this&&(e.SecondLevelDomains=k);return this},init:function(){var d="",e;for(e in m.list)u.call(m.list,e)&&(d+="|("+("("+m.list[e]+")."+e)+")");m.has_expression=RegExp("\\.("+d.substr(1)+")$","i");m.is_expression=RegExp("^("+d.substr(1)+")$","i")}};m.init();return m});
+(function(e,k){"object"===typeof exports?module.exports=k(require("./punycode"),require("./IPv6"),require("./SecondLevelDomains")):"function"===typeof define&&define.amd?define(["./punycode","./IPv6","./SecondLevelDomains"],k):e.URI=k(e.punycode,e.IPv6,e.SecondLevelDomains,e)})(this,function(e,k,u,m){function d(a,b){if(!(this instanceof d))return new d(a,b);void 0===a&&(a="undefined"!==typeof location?location.href+"":"");this.href(a);return void 0!==b?this.absoluteTo(b):this}function g(a){return a.replace(/([.*+?^=!:${}()|[\]\/\\])/g,
+"\\$1")}function q(a){return void 0===a?"Undefined":String(Object.prototype.toString.call(a)).slice(8,-1)}function l(a){return"Array"===q(a)}function r(a,b){var c,d;if(l(b)){c=0;for(d=b.length;c<d;c++)if(!r(a,b[c]))return!1;return!0}var p=q(b);c=0;for(d=a.length;c<d;c++)if("RegExp"===p){if("string"===typeof a[c]&&a[c].match(b))return!0}else if(a[c]===b)return!0;return!1}function z(a,b){if(!l(a)||!l(b)||a.length!==b.length)return!1;a.sort();b.sort();for(var c=0,d=a.length;c<d;c++)if(a[c]!==b[c])return!1;
+return!0}function D(a){return escape(a)}function E(a){return encodeURIComponent(a).replace(/[!'()*]/g,D).replace(/\*/g,"%2A")}var C=m&&m.URI;d.version="1.12.0";var f=d.prototype,w=Object.prototype.hasOwnProperty;d._parts=function(){return{protocol:null,username:null,password:null,hostname:null,urn:null,port:null,path:null,query:null,fragment:null,duplicateQueryParameters:d.duplicateQueryParameters,escapeQuerySpace:d.escapeQuerySpace}};d.duplicateQueryParameters=!1;d.escapeQuerySpace=!0;d.protocol_expression=
+/^[a-z][a-z0-9.+-]*$/i;d.idn_expression=/[^a-z0-9\.-]/i;d.punycode_expression=/(xn--)/i;d.ip4_expression=/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;d.ip6_expression=/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/;
+d.find_uri_expression=/\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u2018\u2019]))/ig;d.findUri={start:/\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,end:/[\s\r\n]|$/,trim:/[`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u201e\u2018\u2019]+$/};d.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"};d.invalid_hostname_characters=
+/[^a-zA-Z0-9\.-]/;d.domAttributes={a:"href",blockquote:"cite",link:"href",base:"href",script:"src",form:"action",img:"src",area:"href",iframe:"src",embed:"src",source:"src",track:"src",input:"src"};d.getDomAttribute=function(a){if(a&&a.nodeName){var b=a.nodeName.toLowerCase();return"input"===b&&"image"!==a.type?void 0:d.domAttributes[b]}};d.encode=E;d.decode=decodeURIComponent;d.iso8859=function(){d.encode=escape;d.decode=unescape};d.unicode=function(){d.encode=E;d.decode=decodeURIComponent};d.characters=
+{pathname:{encode:{expression:/%(24|26|2B|2C|3B|3D|3A|40)/ig,map:{"%24":"$","%26":"&","%2B":"+","%2C":",","%3B":";","%3D":"=","%3A":":","%40":"@"}},decode:{expression:/[\/\?#]/g,map:{"/":"%2F","?":"%3F","#":"%23"}}},reserved:{encode:{expression:/%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,map:{"%3A":":","%2F":"/","%3F":"?","%23":"#","%5B":"[","%5D":"]","%40":"@","%21":"!","%24":"$","%26":"&","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"="}}}};d.encodeQuery=
+function(a,b){var c=d.encode(a+"");return b?c.replace(/%20/g,"+"):c};d.decodeQuery=function(a,b){a+="";try{return d.decode(b?a.replace(/\+/g,"%20"):a)}catch(c){return a}};d.recodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;b<c;b++)a[b]=d.encodePathSegment(d.decode(a[b]));return a.join("/")};d.decodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;b<c;b++)a[b]=d.decodePathSegment(a[b]);return a.join("/")};var s={encode:"encode",decode:"decode"},v,y=function(a,b){return function(c){return d[b](c+
+"").replace(d.characters[a][b].expression,function(c){return d.characters[a][b].map[c]})}};for(v in s)d[v+"PathSegment"]=y("pathname",s[v]);d.encodeReserved=y("reserved","encode");d.parse=function(a,b){var c;b||(b={});c=a.indexOf("#");-1<c&&(b.fragment=a.substring(c+1)||null,a=a.substring(0,c));c=a.indexOf("?");-1<c&&(b.query=a.substring(c+1)||null,a=a.substring(0,c));"//"===a.substring(0,2)?(b.protocol=null,a=a.substring(2),a=d.parseAuthority(a,b)):(c=a.indexOf(":"),-1<c&&(b.protocol=a.substring(0,
+c)||null,b.protocol&&!b.protocol.match(d.protocol_expression)?b.protocol=void 0:"file"===b.protocol?a=a.substring(c+3):"//"===a.substring(c+1,c+3)?(a=a.substring(c+3),a=d.parseAuthority(a,b)):(a=a.substring(c+1),b.urn=!0)));b.path=a;return b};d.parseHost=function(a,b){var c=a.indexOf("/"),d;-1===c&&(c=a.length);"["===a.charAt(0)?(d=a.indexOf("]"),b.hostname=a.substring(1,d)||null,b.port=a.substring(d+2,c)||null):a.indexOf(":")!==a.lastIndexOf(":")?(b.hostname=a.substring(0,c)||null,b.port=null):(d=
+a.substring(0,c).split(":"),b.hostname=d[0]||null,b.port=d[1]||null);b.hostname&&"/"!==a.substring(c).charAt(0)&&(c++,a="/"+a);return a.substring(c)||"/"};d.parseAuthority=function(a,b){a=d.parseUserinfo(a,b);return d.parseHost(a,b)};d.parseUserinfo=function(a,b){var c=a.indexOf("/"),h=-1<c?a.lastIndexOf("@",c):a.indexOf("@");-1<h&&(-1===c||h<c)?(c=a.substring(0,h).split(":"),b.username=c[0]?d.decode(c[0]):null,c.shift(),b.password=c[0]?d.decode(c.join(":")):null,a=a.substring(h+1)):(b.username=null,
+b.password=null);return a};d.parseQuery=function(a,b){if(!a)return{};a=a.replace(/&+/g,"&").replace(/^\?*&*|&+$/g,"");if(!a)return{};for(var c={},h=a.split("&"),p=h.length,n,e,f=0;f<p;f++)n=h[f].split("="),e=d.decodeQuery(n.shift(),b),n=n.length?d.decodeQuery(n.join("="),b):null,c[e]?("string"===typeof c[e]&&(c[e]=[c[e]]),c[e].push(n)):c[e]=n;return c};d.build=function(a){var b="";a.protocol&&(b+=a.protocol+":");a.urn||!b&&!a.hostname||(b+="//");b+=d.buildAuthority(a)||"";"string"===typeof a.path&&
+("/"!==a.path.charAt(0)&&"string"===typeof a.hostname&&(b+="/"),b+=a.path);"string"===typeof a.query&&a.query&&(b+="?"+a.query);"string"===typeof a.fragment&&a.fragment&&(b+="#"+a.fragment);return b};d.buildHost=function(a){var b="";if(a.hostname)d.ip6_expression.test(a.hostname)?b=a.port?b+("["+a.hostname+"]:"+a.port):b+a.hostname:(b+=a.hostname,a.port&&(b+=":"+a.port));else return"";return b};d.buildAuthority=function(a){return d.buildUserinfo(a)+d.buildHost(a)};d.buildUserinfo=function(a){var b=
+"";a.username&&(b+=d.encode(a.username),a.password&&(b+=":"+d.encode(a.password)),b+="@");return b};d.buildQuery=function(a,b,c){var h="",p,e,f,k;for(e in a)if(w.call(a,e)&&e)if(l(a[e]))for(p={},f=0,k=a[e].length;f<k;f++)void 0!==a[e][f]&&void 0===p[a[e][f]+""]&&(h+="&"+d.buildQueryParameter(e,a[e][f],c),!0!==b&&(p[a[e][f]+""]=!0));else void 0!==a[e]&&(h+="&"+d.buildQueryParameter(e,a[e],c));return h.substring(1)};d.buildQueryParameter=function(a,b,c){return d.encodeQuery(a,c)+(null!==b?"="+d.encodeQuery(b,
+c):"")};d.addQuery=function(a,b,c){if("object"===typeof b)for(var h in b)w.call(b,h)&&d.addQuery(a,h,b[h]);else if("string"===typeof b)void 0===a[b]?a[b]=c:("string"===typeof a[b]&&(a[b]=[a[b]]),l(c)||(c=[c]),a[b]=a[b].concat(c));else throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");};d.removeQuery=function(a,b,c){var h;if(l(b))for(c=0,h=b.length;c<h;c++)a[b[c]]=void 0;else if("object"===typeof b)for(h in b)w.call(b,h)&&d.removeQuery(a,h,b[h]);else if("string"===
+typeof b)if(void 0!==c)if(a[b]===c)a[b]=void 0;else{if(l(a[b])){h=a[b];var p={},e,f;if(l(c))for(e=0,f=c.length;e<f;e++)p[c[e]]=!0;else p[c]=!0;e=0;for(f=h.length;e<f;e++)void 0!==p[h[e]]&&(h.splice(e,1),f--,e--);a[b]=h}}else a[b]=void 0;else throw new TypeError("URI.addQuery() accepts an object, string as the first parameter");};d.hasQuery=function(a,b,c,h){if("object"===typeof b){for(var e in b)if(w.call(b,e)&&!d.hasQuery(a,e,b[e]))return!1;return!0}if("string"!==typeof b)throw new TypeError("URI.hasQuery() accepts an object, string as the name parameter");
+switch(q(c)){case "Undefined":return b in a;case "Boolean":return a=Boolean(l(a[b])?a[b].length:a[b]),c===a;case "Function":return!!c(a[b],b,a);case "Array":return l(a[b])?(h?r:z)(a[b],c):!1;case "RegExp":return l(a[b])?h?r(a[b],c):!1:Boolean(a[b]&&a[b].match(c));case "Number":c=String(c);case "String":return l(a[b])?h?r(a[b],c):!1:a[b]===c;default:throw new TypeError("URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter");}};d.commonPath=function(a,b){var c=
+Math.min(a.length,b.length),d;for(d=0;d<c;d++)if(a.charAt(d)!==b.charAt(d)){d--;break}if(1>d)return a.charAt(0)===b.charAt(0)&&"/"===a.charAt(0)?"/":"";if("/"!==a.charAt(d)||"/"!==b.charAt(d))d=a.substring(0,d).lastIndexOf("/");return a.substring(0,d+1)};d.withinString=function(a,b,c){c||(c={});var h=c.start||d.findUri.start,e=c.end||d.findUri.end,f=c.trim||d.findUri.trim,k=/[a-z0-9-]=["']?$/i;for(h.lastIndex=0;;){var g=h.exec(a);if(!g)break;g=g.index;if(c.ignoreHtml){var l=a.slice(Math.max(g-3,0),
+g);if(l&&k.test(l))continue}var l=g+a.slice(g).search(e),q=a.slice(g,l).replace(f,"");c.ignore&&c.ignore.test(q)||(l=g+q.length,q=b(q,g,l,a),a=a.slice(0,g)+q+a.slice(l),h.lastIndex=g+q.length)}h.lastIndex=0;return a};d.ensureValidHostname=function(a){if(a.match(d.invalid_hostname_characters)){if(!e)throw new TypeError("Hostname '"+a+"' contains characters other than [A-Z0-9.-] and Punycode.js is not available");if(e.toASCII(a).match(d.invalid_hostname_characters))throw new TypeError("Hostname '"+
+a+"' contains characters other than [A-Z0-9.-]");}};d.noConflict=function(a){if(a)return a={URI:this.noConflict()},URITemplate&&"function"==typeof URITemplate.noConflict&&(a.URITemplate=URITemplate.noConflict()),k&&"function"==typeof k.noConflict&&(a.IPv6=k.noConflict()),SecondLevelDomains&&"function"==typeof SecondLevelDomains.noConflict&&(a.SecondLevelDomains=SecondLevelDomains.noConflict()),a;m.URI===this&&(m.URI=C);return this};f.build=function(a){if(!0===a)this._deferred_build=!0;else if(void 0===
+a||this._deferred_build)this._string=d.build(this._parts),this._deferred_build=!1;return this};f.clone=function(){return new d(this)};f.valueOf=f.toString=function(){return this.build(!1)._string};s={protocol:"protocol",username:"username",password:"password",hostname:"hostname",port:"port"};y=function(a){return function(b,c){if(void 0===b)return this._parts[a]||"";this._parts[a]=b||null;this.build(!c);return this}};for(v in s)f[v]=y(s[v]);s={query:"?",fragment:"#"};y=function(a,b){return function(c,
+d){if(void 0===c)return this._parts[a]||"";null!==c&&(c+="",c.charAt(0)===b&&(c=c.substring(1)));this._parts[a]=c;this.build(!d);return this}};for(v in s)f[v]=y(v,s[v]);s={search:["?","query"],hash:["#","fragment"]};y=function(a,b){return function(c,d){var e=this[a](c,d);return"string"===typeof e&&e.length?b+e:e}};for(v in s)f[v]=y(s[v][1],s[v][0]);f.pathname=function(a,b){if(void 0===a||!0===a){var c=this._parts.path||(this._parts.hostname?"/":"");return a?d.decodePath(c):c}this._parts.path=a?d.recodePath(a):
+"/";this.build(!b);return this};f.path=f.pathname;f.href=function(a,b){var c;if(void 0===a)return this.toString();this._string="";this._parts=d._parts();var h=a instanceof d,e="object"===typeof a&&(a.hostname||a.path||a.pathname);a.nodeName&&(e=d.getDomAttribute(a),a=a[e]||"",e=!1);!h&&e&&void 0!==a.pathname&&(a=a.toString());if("string"===typeof a)this._parts=d.parse(a,this._parts);else if(h||e)for(c in h=h?a._parts:a,h)w.call(this._parts,c)&&(this._parts[c]=h[c]);else throw new TypeError("invalid input");
+this.build(!b);return this};f.is=function(a){var b=!1,c=!1,h=!1,e=!1,f=!1,g=!1,k=!1,l=!this._parts.urn;this._parts.hostname&&(l=!1,c=d.ip4_expression.test(this._parts.hostname),h=d.ip6_expression.test(this._parts.hostname),b=c||h,f=(e=!b)&&u&&u.has(this._parts.hostname),g=e&&d.idn_expression.test(this._parts.hostname),k=e&&d.punycode_expression.test(this._parts.hostname));switch(a.toLowerCase()){case "relative":return l;case "absolute":return!l;case "domain":case "name":return e;case "sld":return f;
+case "ip":return b;case "ip4":case "ipv4":case "inet4":return c;case "ip6":case "ipv6":case "inet6":return h;case "idn":return g;case "url":return!this._parts.urn;case "urn":return!!this._parts.urn;case "punycode":return k}return null};var I=f.protocol,H=f.port,G=f.hostname;f.protocol=function(a,b){if(void 0!==a&&a&&(a=a.replace(/:(\/\/)?$/,""),!a.match(d.protocol_expression)))throw new TypeError("Protocol '"+a+"' contains characters other than [A-Z0-9.+-] or doesn't start with [A-Z]");return I.call(this,
+a,b)};f.scheme=f.protocol;f.port=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a&&(0===a&&(a=null),a&&(a+="",":"===a.charAt(0)&&(a=a.substring(1)),a.match(/[^0-9]/))))throw new TypeError("Port '"+a+"' contains characters other than [0-9]");return H.call(this,a,b)};f.hostname=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a){var c={};d.parseHost(a,c);a=c.hostname}return G.call(this,a,b)};f.host=function(a,b){if(this._parts.urn)return void 0===a?"":this;
+if(void 0===a)return this._parts.hostname?d.buildHost(this._parts):"";d.parseHost(a,this._parts);this.build(!b);return this};f.authority=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a)return this._parts.hostname?d.buildAuthority(this._parts):"";d.parseAuthority(a,this._parts);this.build(!b);return this};f.userinfo=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.username)return"";var c=d.buildUserinfo(this._parts);return c.substring(0,
+c.length-1)}"@"!==a[a.length-1]&&(a+="@");d.parseUserinfo(a,this._parts);this.build(!b);return this};f.resource=function(a,b){var c;if(void 0===a)return this.path()+this.search()+this.hash();c=d.parse(a);this._parts.path=c.path;this._parts.query=c.query;this._parts.fragment=c.fragment;this.build(!b);return this};f.subdomain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.length-this.domain().length-
+1;return this._parts.hostname.substring(0,c)||""}c=this._parts.hostname.length-this.domain().length;c=this._parts.hostname.substring(0,c);c=RegExp("^"+g(c));a&&"."!==a.charAt(a.length-1)&&(a+=".");a&&d.ensureValidHostname(a);this._parts.hostname=this._parts.hostname.replace(c,a);this.build(!b);return this};f.domain=function(a,b){if(this._parts.urn)return void 0===a?"":this;"boolean"===typeof a&&(b=a,a=void 0);if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.match(/\./g);
+if(c&&2>c.length)return this._parts.hostname;c=this._parts.hostname.length-this.tld(b).length-1;c=this._parts.hostname.lastIndexOf(".",c-1)+1;return this._parts.hostname.substring(c)||""}if(!a)throw new TypeError("cannot set domain empty");d.ensureValidHostname(a);!this._parts.hostname||this.is("IP")?this._parts.hostname=a:(c=RegExp(g(this.domain())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a));this.build(!b);return this};f.tld=function(a,b){if(this._parts.urn)return void 0===a?"":
+this;"boolean"===typeof a&&(b=a,a=void 0);if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.lastIndexOf("."),c=this._parts.hostname.substring(c+1);return!0!==b&&u&&u.list[c.toLowerCase()]?u.get(this._parts.hostname)||c:c}if(a)if(a.match(/[^a-zA-Z0-9-]/))if(u&&u.is(a))c=RegExp(g(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a);else throw new TypeError("TLD '"+a+"' contains characters other than [A-Z0-9]");else{if(!this._parts.hostname||
+this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");c=RegExp(g(this.tld())+"$");this._parts.hostname=this._parts.hostname.replace(c,a)}else throw new TypeError("cannot set TLD empty");this.build(!b);return this};f.directory=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var c=this._parts.path.length-this.filename().length-1,c=this._parts.path.substring(0,
+c)||(this._parts.hostname?"/":"");return a?d.decodePath(c):c}c=this._parts.path.length-this.filename().length;c=this._parts.path.substring(0,c);c=RegExp("^"+g(c));this.is("relative")||(a||(a="/"),"/"!==a.charAt(0)&&(a="/"+a));a&&"/"!==a.charAt(a.length-1)&&(a+="/");a=d.recodePath(a);this._parts.path=this._parts.path.replace(c,a);this.build(!b);return this};f.filename=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";
+var c=this._parts.path.lastIndexOf("/"),c=this._parts.path.substring(c+1);return a?d.decodePathSegment(c):c}c=!1;"/"===a.charAt(0)&&(a=a.substring(1));a.match(/\.?\//)&&(c=!0);var h=RegExp(g(this.filename())+"$");a=d.recodePath(a);this._parts.path=this._parts.path.replace(h,a);c?this.normalizePath(b):this.build(!b);return this};f.suffix=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var c=this.filename(),h=c.lastIndexOf(".");
+if(-1===h)return"";c=c.substring(h+1);c=/^[a-z0-9%]+$/i.test(c)?c:"";return a?d.decodePathSegment(c):c}"."===a.charAt(0)&&(a=a.substring(1));if(c=this.suffix())h=a?RegExp(g(c)+"$"):RegExp(g("."+c)+"$");else{if(!a)return this;this._parts.path+="."+d.recodePath(a)}h&&(a=d.recodePath(a),this._parts.path=this._parts.path.replace(h,a));this.build(!b);return this};f.segment=function(a,b,c){var d=this._parts.urn?":":"/",e=this.path(),f="/"===e.substring(0,1),e=e.split(d);void 0!==a&&"number"!==typeof a&&
+(c=b,b=a,a=void 0);if(void 0!==a&&"number"!==typeof a)throw Error("Bad segment '"+a+"', must be 0-based integer");f&&e.shift();0>a&&(a=Math.max(e.length+a,0));if(void 0===b)return void 0===a?e:e[a];if(null===a||void 0===e[a])if(l(b)){e=[];a=0;for(var g=b.length;a<g;a++)if(b[a].length||e.length&&e[e.length-1].length)e.length&&!e[e.length-1].length&&e.pop(),e.push(b[a])}else{if(b||"string"===typeof b)""===e[e.length-1]?e[e.length-1]=b:e.push(b)}else b||"string"===typeof b&&b.length?e[a]=b:e.splice(a,
+1);f&&e.unshift("");return this.path(e.join(d),c)};f.segmentCoded=function(a,b,c){var e,f;"number"!==typeof a&&(c=b,b=a,a=void 0);if(void 0===b){a=this.segment(a,b,c);if(l(a))for(e=0,f=a.length;e<f;e++)a[e]=d.decode(a[e]);else a=void 0!==a?d.decode(a):void 0;return a}if(l(b))for(e=0,f=b.length;e<f;e++)b[e]=d.decode(b[e]);else b="string"===typeof b?d.encode(b):b;return this.segment(a,b,c)};var F=f.query;f.query=function(a,b){if(!0===a)return d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);
+if("function"===typeof a){var c=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace),e=a.call(this,c);this._parts.query=d.buildQuery(e||c,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);this.build(!b);return this}return void 0!==a&&"string"!==typeof a?(this._parts.query=d.buildQuery(a,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!b),this):F.call(this,a,b)};f.setQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);
+if("object"===typeof a)for(var f in a)w.call(a,f)&&(e[f]=a[f]);else if("string"===typeof a)e[a]=void 0!==b?b:null;else throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");this._parts.query=d.buildQuery(e,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);"string"!==typeof a&&(c=b);this.build(!c);return this};f.addQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);d.addQuery(e,a,void 0===b?null:b);this._parts.query=
+d.buildQuery(e,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);"string"!==typeof a&&(c=b);this.build(!c);return this};f.removeQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);d.removeQuery(e,a,b);this._parts.query=d.buildQuery(e,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);"string"!==typeof a&&(c=b);this.build(!c);return this};f.hasQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);
+return d.hasQuery(e,a,b,c)};f.setSearch=f.setQuery;f.addSearch=f.addQuery;f.removeSearch=f.removeQuery;f.hasSearch=f.hasQuery;f.normalize=function(){return this._parts.urn?this.normalizeProtocol(!1).normalizeQuery(!1).normalizeFragment(!1).build():this.normalizeProtocol(!1).normalizeHostname(!1).normalizePort(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build()};f.normalizeProtocol=function(a){"string"===typeof this._parts.protocol&&(this._parts.protocol=this._parts.protocol.toLowerCase(),
+this.build(!a));return this};f.normalizeHostname=function(a){this._parts.hostname&&(this.is("IDN")&&e?this._parts.hostname=e.toASCII(this._parts.hostname):this.is("IPv6")&&k&&(this._parts.hostname=k.best(this._parts.hostname)),this._parts.hostname=this._parts.hostname.toLowerCase(),this.build(!a));return this};f.normalizePort=function(a){"string"===typeof this._parts.protocol&&this._parts.port===d.defaultPorts[this._parts.protocol]&&(this._parts.port=null,this.build(!a));return this};f.normalizePath=
+function(a){if(this._parts.urn||!this._parts.path||"/"===this._parts.path)return this;var b,c=this._parts.path,e="",f,g;"/"!==c.charAt(0)&&(b=!0,c="/"+c);c=c.replace(/(\/(\.\/)+)|(\/\.$)/g,"/").replace(/\/{2,}/g,"/");b&&(e=c.substring(1).match(/^(\.\.\/)+/)||"")&&(e=e[0]);for(;;){f=c.indexOf("/..");if(-1===f)break;else if(0===f){c=c.substring(3);continue}g=c.substring(0,f).lastIndexOf("/");-1===g&&(g=f);c=c.substring(0,g)+c.substring(f+3)}b&&this.is("relative")&&(c=e+c.substring(1));c=d.recodePath(c);
+this._parts.path=c;this.build(!a);return this};f.normalizePathname=f.normalizePath;f.normalizeQuery=function(a){"string"===typeof this._parts.query&&(this._parts.query.length?this.query(d.parseQuery(this._parts.query,this._parts.escapeQuerySpace)):this._parts.query=null,this.build(!a));return this};f.normalizeFragment=function(a){this._parts.fragment||(this._parts.fragment=null,this.build(!a));return this};f.normalizeSearch=f.normalizeQuery;f.normalizeHash=f.normalizeFragment;f.iso8859=function(){var a=
+d.encode,b=d.decode;d.encode=escape;d.decode=decodeURIComponent;this.normalize();d.encode=a;d.decode=b;return this};f.unicode=function(){var a=d.encode,b=d.decode;d.encode=E;d.decode=unescape;this.normalize();d.encode=a;d.decode=b;return this};f.readable=function(){var a=this.clone();a.username("").password("").normalize();var b="";a._parts.protocol&&(b+=a._parts.protocol+"://");a._parts.hostname&&(a.is("punycode")&&e?(b+=e.toUnicode(a._parts.hostname),a._parts.port&&(b+=":"+a._parts.port)):b+=a.host());
+a._parts.hostname&&a._parts.path&&"/"!==a._parts.path.charAt(0)&&(b+="/");b+=a.path(!0);if(a._parts.query){for(var c="",f=0,g=a._parts.query.split("&"),k=g.length;f<k;f++){var l=(g[f]||"").split("="),c=c+("&"+d.decodeQuery(l[0],this._parts.escapeQuerySpace).replace(/&/g,"%26"));void 0!==l[1]&&(c+="="+d.decodeQuery(l[1],this._parts.escapeQuerySpace).replace(/&/g,"%26"))}b+="?"+c.substring(1)}return b+=d.decodeQuery(a.hash(),!0)};f.absoluteTo=function(a){var b=this.clone(),c=["protocol","username",
+"password","hostname","port"],e,f;if(this._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");a instanceof d||(a=new d(a));b._parts.protocol||(b._parts.protocol=a._parts.protocol);if(this._parts.hostname)return b;for(e=0;f=c[e];e++)b._parts[f]=a._parts[f];b._parts.path?".."===b._parts.path.substring(-2)&&(b._parts.path+="/"):(b._parts.path=a._parts.path,b._parts.query||(b._parts.query=a._parts.query));"/"!==b.path().charAt(0)&&(a=a.directory(),b._parts.path=(a?
+a+"/":"")+b._parts.path,b.normalizePath());b.build();return b};f.relativeTo=function(a){var b=this.clone().normalize(),c,e,f,g;if(b._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");a=(new d(a)).normalize();c=b._parts;e=a._parts;f=b.path();g=a.path();if("/"!==f.charAt(0))throw Error("URI is already relative");if("/"!==g.charAt(0))throw Error("Cannot calculate a URI relative to another relative URI");c.protocol===e.protocol&&(c.protocol=null);if(c.username===
+e.username&&c.password===e.password&&null===c.protocol&&null===c.username&&null===c.password&&c.hostname===e.hostname&&c.port===e.port)c.hostname=null,c.port=null;else return b.build();if(f===g)return c.path="",b.build();a=d.commonPath(b.path(),a.path());if(!a)return b.build();e=e.path.substring(a.length).replace(/[^\/]*$/,"").replace(/.*?\//g,"../");c.path=e+c.path.substring(a.length);return b.build()};f.equals=function(a){var b=this.clone();a=new d(a);var c={},e={},f={},g;b.normalize();a.normalize();
+if(b.toString()===a.toString())return!0;c=b.query();e=a.query();b.query("");a.query("");if(b.toString()!==a.toString()||c.length!==e.length)return!1;c=d.parseQuery(c,this._parts.escapeQuerySpace);e=d.parseQuery(e,this._parts.escapeQuerySpace);for(g in c)if(w.call(c,g)){if(!l(c[g])){if(c[g]!==e[g])return!1}else if(!z(c[g],e[g]))return!1;f[g]=!0}for(g in e)if(w.call(e,g)&&!f[g])return!1;return!0};f.duplicateQueryParameters=function(a){this._parts.duplicateQueryParameters=!!a;return this};f.escapeQuerySpace=
+function(a){this._parts.escapeQuerySpace=!!a;return this};return d});
+(function(e,k){"object"===typeof exports?module.exports=k(require("./URI")):"function"===typeof define&&define.amd?define(["./URI"],k):k(e.URI)})(this,function(e){var k=e.prototype,u=k.fragment;e.fragmentPrefix="?";var m=e._parts;e._parts=function(){var d=m();d.fragmentPrefix=e.fragmentPrefix;return d};k.fragmentPrefix=function(d){this._parts.fragmentPrefix=d;return this};k.fragment=function(d,g){var k=this._parts.fragmentPrefix,l=this._parts.fragment||"";return!0===d?l.substring(0,k.length)!==k?
+{}:e.parseQuery(l.substring(k.length)):void 0!==d&&"string"!==typeof d?(this._parts.fragment=k+e.buildQuery(d),this.build(!g),this):u.call(this,d,g)};k.addFragment=function(d,g,k){var l=this._parts.fragmentPrefix,m=e.parseQuery((this._parts.fragment||"").substring(l.length));e.addQuery(m,d,g);this._parts.fragment=l+e.buildQuery(m);"string"!==typeof d&&(k=g);this.build(!k);return this};k.removeFragment=function(d,g,k){var l=this._parts.fragmentPrefix,m=e.parseQuery((this._parts.fragment||"").substring(l.length));
+e.removeQuery(m,d,g);this._parts.fragment=l+e.buildQuery(m);"string"!==typeof d&&(k=g);this.build(!k);return this};k.addHash=k.addFragment;k.removeHash=k.removeFragment;return{}});
+;/*global unescape, module, define, window, global*/
+
+/*
+ UriTemplate Copyright (c) 2012-2013 Franz Antesberger. All Rights Reserved.
+ Available via the MIT license.
+*/
+
+(function (exportCallback) {
+    "use strict";
+
+var UriTemplateError = (function () {
+
+    function UriTemplateError (options) {
+        this.options = options;
+    }
+
+    UriTemplateError.prototype.toString = function () {
+        if (JSON && JSON.stringify) {
+            return JSON.stringify(this.options);
+        }
+        else {
+            return this.options;
+        }
+    };
+
+    return UriTemplateError;
+}());
+
+var objectHelper = (function () {
+    function isArray (value) {
+        return Object.prototype.toString.apply(value) === '[object Array]';
+    }
+
+    function isString (value) {
+        return Object.prototype.toString.apply(value) === '[object String]';
+    }
+    
+    function isNumber (value) {
+        return Object.prototype.toString.apply(value) === '[object Number]';
+    }
+    
+    function isBoolean (value) {
+        return Object.prototype.toString.apply(value) === '[object Boolean]';
+    }
+    
+    function join (arr, separator) {
+        var
+            result = '',
+            first = true,
+            index;
+        for (index = 0; index < arr.length; index += 1) {
+            if (first) {
+                first = false;
+            }
+            else {
+                result += separator;
+            }
+            result += arr[index];
+        }
+        return result;
+    }
+
+    function map (arr, mapper) {
+        var
+            result = [],
+            index = 0;
+        for (; index < arr.length; index += 1) {
+            result.push(mapper(arr[index]));
+        }
+        return result;
+    }
+
+    function filter (arr, predicate) {
+        var
+            result = [],
+            index = 0;
+        for (; index < arr.length; index += 1) {
+            if (predicate(arr[index])) {
+                result.push(arr[index]);
+            }
+        }
+        return result;
+    }
+
+    function deepFreezeUsingObjectFreeze (object) {
+        if (typeof object !== "object" || object === null) {
+            return object;
+        }
+        Object.freeze(object);
+        var property, propertyName;
+        for (propertyName in object) {
+            if (object.hasOwnProperty(propertyName)) {
+                property = object[propertyName];
+                // be aware, arrays are 'object', too
+                if ((typeof property === "object") && !(property instanceof RegExp)) {
+                    deepFreeze(property);
+                }
+            }
+        }
+        return object;
+    }
+
+    function deepFreeze (object) {
+        if (typeof Object.freeze === 'function') {
+            return deepFreezeUsingObjectFreeze(object);
+        }
+        return object;
+    }
+
+
+    return {
+        isArray: isArray,
+        isString: isString,
+        isNumber: isNumber,
+        isBoolean: isBoolean,
+        join: join,
+        map: map,
+        filter: filter,
+        deepFreeze: deepFreeze
+    };
+}());
+
+var charHelper = (function () {
+
+    function isAlpha (chr) {
+        return (chr >= 'a' && chr <= 'z') || ((chr >= 'A' && chr <= 'Z'));
+    }
+
+    function isDigit (chr) {
+        return chr >= '0' && chr <= '9';
+    }
+
+    function isHexDigit (chr) {
+        return isDigit(chr) || (chr >= 'a' && chr <= 'f') || (chr >= 'A' && chr <= 'F');
+    }
+
+    return {
+        isAlpha: isAlpha,
+        isDigit: isDigit,
+        isHexDigit: isHexDigit
+    };
+}());
+
+var pctEncoder = (function () {
+    var utf8 = {
+        encode: function (chr) {
+            // see http://ecmanaut.blogspot.de/2006/07/encoding-decoding-utf8-in-javascript.html
+            return unescape(encodeURIComponent(chr));
+        },
+        numBytes: function (firstCharCode) {
+            if (firstCharCode <= 0x7F) {
+                return 1;
+            }
+            else if (0xC2 <= firstCharCode && firstCharCode <= 0xDF) {
+                return 2;
+            }
+            else if (0xE0 <= firstCharCode && firstCharCode <= 0xEF) {
+                return 3;
+            }
+            else if (0xF0 <= firstCharCode && firstCharCode <= 0xF4) {
+                return 4;
+            }
+            // no valid first octet
+            return 0;
+        },
+        isValidFollowingCharCode: function (charCode) {
+            return 0x80 <= charCode && charCode <= 0xBF;
+        }
+    };
+
+    /**
+     * encodes a character, if needed or not.
+     * @param chr
+     * @return pct-encoded character
+     */
+    function encodeCharacter (chr) {
+        var
+            result = '',
+            octets = utf8.encode(chr),
+            octet,
+            index;
+        for (index = 0; index < octets.length; index += 1) {
+            octet = octets.charCodeAt(index);
+            result += '%' + (octet < 0x10 ? '0' : '') + octet.toString(16).toUpperCase();
+        }
+        return result;
+    }
+
+    /**
+     * Returns, whether the given text at start is in the form 'percent hex-digit hex-digit', like '%3F'
+     * @param text
+     * @param start
+     * @return {boolean|*|*}
+     */
+    function isPercentDigitDigit (text, start) {
+        return text.charAt(start) === '%' && charHelper.isHexDigit(text.charAt(start + 1)) && charHelper.isHexDigit(text.charAt(start + 2));
+    }
+
+    /**
+     * Parses a hex number from start with length 2.
+     * @param text a string
+     * @param start the start index of the 2-digit hex number
+     * @return {Number}
+     */
+    function parseHex2 (text, start) {
+        return parseInt(text.substr(start, 2), 16);
+    }
+
+    /**
+     * Returns whether or not the given char sequence is a correctly pct-encoded sequence.
+     * @param chr
+     * @return {boolean}
+     */
+    function isPctEncoded (chr) {
+        if (!isPercentDigitDigit(chr, 0)) {
+            return false;
+        }
+        var firstCharCode = parseHex2(chr, 1);
+        var numBytes = utf8.numBytes(firstCharCode);
+        if (numBytes === 0) {
+            return false;
+        }
+        for (var byteNumber = 1; byteNumber < numBytes; byteNumber += 1) {
+            if (!isPercentDigitDigit(chr, 3*byteNumber) || !utf8.isValidFollowingCharCode(parseHex2(chr, 3*byteNumber + 1))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Reads as much as needed from the text, e.g. '%20' or '%C3%B6'. It does not decode!
+     * @param text
+     * @param startIndex
+     * @return the character or pct-string of the text at startIndex
+     */
+    function pctCharAt(text, startIndex) {
+        var chr = text.charAt(startIndex);
+        if (!isPercentDigitDigit(text, startIndex)) {
+            return chr;
+        }
+        var utf8CharCode = parseHex2(text, startIndex + 1);
+        var numBytes = utf8.numBytes(utf8CharCode);
+        if (numBytes === 0) {
+            return chr;
+        }
+        for (var byteNumber = 1; byteNumber < numBytes; byteNumber += 1) {
+            if (!isPercentDigitDigit(text, startIndex + 3 * byteNumber) || !utf8.isValidFollowingCharCode(parseHex2(text, startIndex + 3 * byteNumber + 1))) {
+                return chr;
+            }
+        }
+        return text.substr(startIndex, 3 * numBytes);
+    }
+
+    return {
+        encodeCharacter: encodeCharacter,
+        isPctEncoded: isPctEncoded,
+        pctCharAt: pctCharAt
+    };
+}());
+
+var rfcCharHelper = (function () {
+
+    /**
+     * Returns if an character is an varchar character according 2.3 of rfc 6570
+     * @param chr
+     * @return (Boolean)
+     */
+    function isVarchar (chr) {
+        return charHelper.isAlpha(chr) || charHelper.isDigit(chr) || chr === '_' || pctEncoder.isPctEncoded(chr);
+    }
+
+    /**
+     * Returns if chr is an unreserved character according 1.5 of rfc 6570
+     * @param chr
+     * @return {Boolean}
+     */
+    function isUnreserved (chr) {
+        return charHelper.isAlpha(chr) || charHelper.isDigit(chr) || chr === '-' || chr === '.' || chr === '_' || chr === '~';
+    }
+
+    /**
+     * Returns if chr is an reserved character according 1.5 of rfc 6570
+     * or the percent character mentioned in 3.2.1.
+     * @param chr
+     * @return {Boolean}
+     */
+    function isReserved (chr) {
+        return chr === ':' || chr === '/' || chr === '?' || chr === '#' || chr === '[' || chr === ']' || chr === '@' || chr === '!' || chr === '$' || chr === '&' || chr === '(' ||
+            chr === ')' || chr === '*' || chr === '+' || chr === ',' || chr === ';' || chr === '=' || chr === "'";
+    }
+
+    return {
+        isVarchar: isVarchar,
+        isUnreserved: isUnreserved,
+        isReserved: isReserved
+    };
+
+}());
+
+/**
+ * encoding of rfc 6570
+ */
+var encodingHelper = (function () {
+
+    function encode (text, passReserved) {
+        var
+            result = '',
+            index,
+            chr = '';
+        if (typeof text === "number" || typeof text === "boolean") {
+            text = text.toString();
+        }
+        for (index = 0; index < text.length; index += chr.length) {
+            chr = text.charAt(index);
+            result += rfcCharHelper.isUnreserved(chr) || (passReserved && rfcCharHelper.isReserved(chr)) ? chr : pctEncoder.encodeCharacter(chr);
+        }
+        return result;
+    }
+
+    function encodePassReserved (text) {
+        return encode(text, true);
+    }
+
+    function encodeLiteralCharacter (literal, index) {
+        var chr = pctEncoder.pctCharAt(literal, index);
+        if (chr.length > 1) {
+            return chr;
+        }
+        else {
+            return rfcCharHelper.isReserved(chr) || rfcCharHelper.isUnreserved(chr) ? chr : pctEncoder.encodeCharacter(chr);
+        }
+    }
+
+    function encodeLiteral (literal) {
+        var
+            result = '',
+            index,
+            chr = '';
+        for (index = 0; index < literal.length; index += chr.length) {
+            chr = pctEncoder.pctCharAt(literal, index);
+            if (chr.length > 1) {
+                result += chr;
+            }
+            else {
+                result += rfcCharHelper.isReserved(chr) || rfcCharHelper.isUnreserved(chr) ? chr : pctEncoder.encodeCharacter(chr);
+            }
+        }
+        return result;
+    }
+
+    return {
+        encode: encode,
+        encodePassReserved: encodePassReserved,
+        encodeLiteral: encodeLiteral,
+        encodeLiteralCharacter: encodeLiteralCharacter
+    };
+
+}());
+
+
+// the operators defined by rfc 6570
+var operators = (function () {
+
+    var
+        bySymbol = {};
+
+    function create (symbol) {
+        bySymbol[symbol] = {
+            symbol: symbol,
+            separator: (symbol === '?') ? '&' : (symbol === '' || symbol === '+' || symbol === '#') ? ',' : symbol,
+            named: symbol === ';' || symbol === '&' || symbol === '?',
+            ifEmpty: (symbol === '&' || symbol === '?') ? '=' : '',
+            first: (symbol === '+' ) ? '' : symbol,
+            encode: (symbol === '+' || symbol === '#') ? encodingHelper.encodePassReserved : encodingHelper.encode,
+            toString: function () {
+                return this.symbol;
+            }
+        };
+    }
+
+    create('');
+    create('+');
+    create('#');
+    create('.');
+    create('/');
+    create(';');
+    create('?');
+    create('&');
+    return {
+        valueOf: function (chr) {
+            if (bySymbol[chr]) {
+                return bySymbol[chr];
+            }
+            if ("=,!@|".indexOf(chr) >= 0) {
+                return null;
+            }
+            return bySymbol[''];
+        }
+    };
+}());
+
+
+/**
+ * Detects, whether a given element is defined in the sense of rfc 6570
+ * Section 2.3 of the RFC makes clear defintions:
+ * * undefined and null are not defined.
+ * * the empty string is defined
+ * * an array ("list") is defined, if it is not empty (even if all elements are not defined)
+ * * an object ("map") is defined, if it contains at least one property with defined value
+ * @param object
+ * @return {Boolean}
+ */
+function isDefined (object) {
+    var
+        propertyName;
+    if (object === null || object === undefined) {
+        return false;
+    }
+    if (objectHelper.isArray(object)) {
+        // Section 2.3: A variable defined as a list value is considered undefined if the list contains zero members
+        return object.length > 0;
+    }
+    if (typeof object === "string" || typeof object === "number" || typeof object === "boolean") {
+        // falsy values like empty strings, false or 0 are "defined"
+        return true;
+    }
+    // else Object
+    for (propertyName in object) {
+        if (object.hasOwnProperty(propertyName) && isDefined(object[propertyName])) {
+            return true;
+        }
+    }
+    return false;
+}
+
+var LiteralExpression = (function () {
+    function LiteralExpression (literal) {
+        this.literal = encodingHelper.encodeLiteral(literal);
+    }
+
+    LiteralExpression.prototype.expand = function () {
+        return this.literal;
+    };
+
+    LiteralExpression.prototype.toString = LiteralExpression.prototype.expand;
+
+    return LiteralExpression;
+}());
+
+var parse = (function () {
+
+    function parseExpression (expressionText) {
+        var
+            operator,
+            varspecs = [],
+            varspec = null,
+            varnameStart = null,
+            maxLengthStart = null,
+            index,
+            chr = '';
+
+        function closeVarname () {
+            var varname = expressionText.substring(varnameStart, index);
+            if (varname.length === 0) {
+                throw new UriTemplateError({expressionText: expressionText, message: "a varname must be specified", position: index});
+            }
+            varspec = {varname: varname, exploded: false, maxLength: null};
+            varnameStart = null;
+        }
+
+        function closeMaxLength () {
+            if (maxLengthStart === index) {
+                throw new UriTemplateError({expressionText: expressionText, message: "after a ':' you have to specify the length", position: index});
+            }
+            varspec.maxLength = parseInt(expressionText.substring(maxLengthStart, index), 10);
+            maxLengthStart = null;
+        }
+
+        operator = (function (operatorText) {
+            var op = operators.valueOf(operatorText);
+            if (op === null) {
+                throw new UriTemplateError({expressionText: expressionText, message: "illegal use of reserved operator", position: index, operator: operatorText});
+            }
+            return op;
+        }(expressionText.charAt(0)));
+        index = operator.symbol.length;
+
+        varnameStart = index;
+
+        for (; index < expressionText.length; index += chr.length) {
+            chr = pctEncoder.pctCharAt(expressionText, index);
+
+            if (varnameStart !== null) {
+                // the spec says: varname =  varchar *( ["."] varchar )
+                // so a dot is allowed except for the first char
+                if (chr === '.') {
+                    if (varnameStart === index) {
+                        throw new UriTemplateError({expressionText: expressionText, message: "a varname MUST NOT start with a dot", position: index});
+                    }
+                    continue;
+                }
+                if (rfcCharHelper.isVarchar(chr)) {
+                    continue;
+                }
+                closeVarname();
+            }
+            if (maxLengthStart !== null) {
+                if (index === maxLengthStart && chr === '0') {
+                    throw new UriTemplateError({expressionText: expressionText, message: "A :prefix must not start with digit 0", position: index});
+                }
+                if (charHelper.isDigit(chr)) {
+                    if (index - maxLengthStart >= 4) {
+                        throw new UriTemplateError({expressionText: expressionText, message: "A :prefix must have max 4 digits", position: index});
+                    }
+                    continue;
+                }
+                closeMaxLength();
+            }
+            if (chr === ':') {
+                if (varspec.maxLength !== null) {
+                    throw new UriTemplateError({expressionText: expressionText, message: "only one :maxLength is allowed per varspec", position: index});
+                }
+                if (varspec.exploded) {
+                    throw new UriTemplateError({expressionText: expressionText, message: "an exploeded varspec MUST NOT be varspeced", position: index});
+                }
+                maxLengthStart = index + 1;
+                continue;
+            }
+            if (chr === '*') {
+                if (varspec === null) {
+                    throw new UriTemplateError({expressionText: expressionText, message: "exploded without varspec", position: index});
+                }
+                if (varspec.exploded) {
+                    throw new UriTemplateError({expressionText: expressionText, message: "exploded twice", position: index});
+                }
+                if (varspec.maxLength) {
+                    throw new UriTemplateError({expressionText: expressionText, message: "an explode (*) MUST NOT follow to a prefix", position: index});
+                }
+                varspec.exploded = true;
+                continue;
+            }
+            // the only legal character now is the comma
+            if (chr === ',') {
+                varspecs.push(varspec);
+                varspec = null;
+                varnameStart = index + 1;
+                continue;
+            }
+            throw new UriTemplateError({expressionText: expressionText, message: "illegal character", character: chr, position: index});
+        } // for chr
+        if (varnameStart !== null) {
+            closeVarname();
+        }
+        if (maxLengthStart !== null) {
+            closeMaxLength();
+        }
+        varspecs.push(varspec);
+        return new VariableExpression(expressionText, operator, varspecs);
+    }
+
+    function escape_regexp_string(string) {
+      // http://simonwillison.net/2006/Jan/20/escape/
+      return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
+    }
+
+    function parse (uriTemplateText) {
+        // assert filled string
+        var
+            index,
+            chr,
+            expressions = [],
+            expression,
+            braceOpenIndex = null,
+            regexp_string = '',
+            can_match = true,
+            literalStart = 0;
+        for (index = 0; index < uriTemplateText.length; index += 1) {
+            chr = uriTemplateText.charAt(index);
+            if (literalStart !== null) {
+                if (chr === '}') {
+                    throw new UriTemplateError({templateText: uriTemplateText, message: "unopened brace closed", position: index});
+                }
+                if (chr === '{') {
+                    if (literalStart < index) {
+                        expression = new LiteralExpression(uriTemplateText.substring(literalStart, index));
+                        expressions.push(expression);
+                        regexp_string += escape_regexp_string(
+                            expression.literal);
+                    }
+                    literalStart = null;
+                    braceOpenIndex = index;
+                }
+                continue;
+            }
+
+            if (braceOpenIndex !== null) {
+                // here just { is forbidden
+                if (chr === '{') {
+                    throw new UriTemplateError({templateText: uriTemplateText, message: "brace already opened", position: index});
+                }
+                if (chr === '}') {
+                    if (braceOpenIndex + 1 === index) {
+                        throw new UriTemplateError({templateText: uriTemplateText, message: "empty braces", position: braceOpenIndex});
+                    }
+                    try {
+                        expression = parseExpression(uriTemplateText.substring(braceOpenIndex + 1, index));
+                    }
+                    catch (error) {
+                        if (error.prototype === UriTemplateError.prototype) {
+                            throw new UriTemplateError({templateText: uriTemplateText, message: error.options.message, position: braceOpenIndex + error.options.position, details: error.options});
+                        }
+                        throw error;
+                    }
+                    expressions.push(expression);
+                    if (expression.operator.symbol.length === 0) {
+                      regexp_string += "([^/]+)";
+                    } else {
+                      can_match = false;
+                    }
+                    braceOpenIndex = null;
+                    literalStart = index + 1;
+                }
+                continue;
+            }
+            throw new Error('reached unreachable code');
+        }
+        if (braceOpenIndex !== null) {
+            throw new UriTemplateError({templateText: uriTemplateText, message: "unclosed brace", position: braceOpenIndex});
+        }
+        if (literalStart < uriTemplateText.length) {
+            expression = new LiteralExpression(uriTemplateText.substring(literalStart));
+            expressions.push(expression);
+            regexp_string += escape_regexp_string(expression.literal);
+        }
+        if (can_match === false) {
+          regexp_string = undefined;
+        }
+        return new UriTemplate(uriTemplateText, expressions, regexp_string);
+    }
+
+    return parse;
+}());
+
+var VariableExpression = (function () {
+    // helper function if JSON is not available
+    function prettyPrint (value) {
+        return (JSON && JSON.stringify) ? JSON.stringify(value) : value;
+    }
+
+    function isEmpty (value) {
+        if (!isDefined(value)) {
+            return true;
+        }
+        if (objectHelper.isString(value)) {
+            return value === '';
+        }
+        if (objectHelper.isNumber(value) || objectHelper.isBoolean(value)) {
+            return false;
+        }
+        if (objectHelper.isArray(value)) {
+            return value.length === 0;
+        }
+        for (var propertyName in value) {
+            if (value.hasOwnProperty(propertyName)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    function propertyArray (object) {
+        var
+            result = [],
+            propertyName;
+        for (propertyName in object) {
+            if (object.hasOwnProperty(propertyName)) {
+                result.push({name: propertyName, value: object[propertyName]});
+            }
+        }
+        return result;
+    }
+
+    function VariableExpression (templateText, operator, varspecs) {
+        this.templateText = templateText;
+        this.operator = operator;
+        this.varspecs = varspecs;
+    }
+
+    VariableExpression.prototype.toString = function () {
+        return this.templateText;
+    };
+
+    function expandSimpleValue(varspec, operator, value) {
+        var result = '';
+        value = value.toString();
+        if (operator.named) {
+            result += encodingHelper.encodeLiteral(varspec.varname);
+            if (value === '') {
+                result += operator.ifEmpty;
+                return result;
+            }
+            result += '=';
+        }
+        if (varspec.maxLength !== null) {
+            value = value.substr(0, varspec.maxLength);
+        }
+        result += operator.encode(value);
+        return result;
+    }
+
+    function valueDefined (nameValue) {
+        return isDefined(nameValue.value);
+    }
+
+    function expandNotExploded(varspec, operator, value) {
+        var
+            arr = [],
+            result = '';
+        if (operator.named) {
+            result += encodingHelper.encodeLiteral(varspec.varname);
+            if (isEmpty(value)) {
+                result += operator.ifEmpty;
+                return result;
+            }
+            result += '=';
+        }
+        if (objectHelper.isArray(value)) {
+            arr = value;
+            arr = objectHelper.filter(arr, isDefined);
+            arr = objectHelper.map(arr, operator.encode);
+            result += objectHelper.join(arr, ',');
+        }
+        else {
+            arr = propertyArray(value);
+            arr = objectHelper.filter(arr, valueDefined);
+            arr = objectHelper.map(arr, function (nameValue) {
+                return operator.encode(nameValue.name) + ',' + operator.encode(nameValue.value);
+            });
+            result += objectHelper.join(arr, ',');
+        }
+        return result;
+    }
+
+    function expandExplodedNamed (varspec, operator, value) {
+        var
+            isArray = objectHelper.isArray(value),
+            arr = [];
+        if (isArray) {
+            arr = value;
+            arr = objectHelper.filter(arr, isDefined);
+            arr = objectHelper.map(arr, function (listElement) {
+                var tmp = encodingHelper.encodeLiteral(varspec.varname);
+                if (isEmpty(listElement)) {
+                    tmp += operator.ifEmpty;
+                }
+                else {
+                    tmp += '=' + operator.encode(listElement);
+                }
+                return tmp;
+            });
+        }
+        else {
+            arr = propertyArray(value);
+            arr = objectHelper.filter(arr, valueDefined);
+            arr = objectHelper.map(arr, function (nameValue) {
+                var tmp = encodingHelper.encodeLiteral(nameValue.name);
+                if (isEmpty(nameValue.value)) {
+                    tmp += operator.ifEmpty;
+                }
+                else {
+                    tmp += '=' + operator.encode(nameValue.value);
+                }
+                return tmp;
+            });
+        }
+        return objectHelper.join(arr, operator.separator);
+    }
+
+    function expandExplodedUnnamed (operator, value) {
+        var
+            arr = [],
+            result = '';
+        if (objectHelper.isArray(value)) {
+            arr = value;
+            arr = objectHelper.filter(arr, isDefined);
+            arr = objectHelper.map(arr, operator.encode);
+            result += objectHelper.join(arr, operator.separator);
+        }
+        else {
+            arr = propertyArray(value);
+            arr = objectHelper.filter(arr, function (nameValue) {
+                return isDefined(nameValue.value);
+            });
+            arr = objectHelper.map(arr, function (nameValue) {
+                return operator.encode(nameValue.name) + '=' + operator.encode(nameValue.value);
+            });
+            result += objectHelper.join(arr, operator.separator);
+        }
+        return result;
+    }
+
+
+    VariableExpression.prototype.expand = function (variables) {
+        var
+            expanded = [],
+            index,
+            varspec,
+            value,
+            valueIsArr,
+            oneExploded = false,
+            operator = this.operator;
+
+        // expand each varspec and join with operator's separator
+        for (index = 0; index < this.varspecs.length; index += 1) {
+            varspec = this.varspecs[index];
+            value = variables[varspec.varname];
+            // if (!isDefined(value)) {
+            // if (variables.hasOwnProperty(varspec.name)) {
+            if (value === null || value === undefined) {
+                continue;
+            }
+            if (varspec.exploded) {
+                oneExploded = true;
+            }
+            valueIsArr = objectHelper.isArray(value);
+            if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
+                expanded.push(expandSimpleValue(varspec, operator, value));
+            }
+            else if (varspec.maxLength && isDefined(value)) {
+                // 2.4.1 of the spec says: "Prefix modifiers are not applicable to variables that have composite values."
+                throw new Error('Prefix modifiers are not applicable to variables that have composite values. You tried to expand ' + this + " with " + prettyPrint(value));
+            }
+            else if (!varspec.exploded) {
+                if (operator.named || !isEmpty(value)) {
+                    expanded.push(expandNotExploded(varspec, operator, value));
+                }
+            }
+            else if (isDefined(value)) {
+                if (operator.named) {
+                    expanded.push(expandExplodedNamed(varspec, operator, value));
+                }
+                else {
+                    expanded.push(expandExplodedUnnamed(operator, value));
+                }
+            }
+        }
+
+        if (expanded.length === 0) {
+            return "";
+        }
+        else {
+            return operator.first + objectHelper.join(expanded, operator.separator);
+        }
+    };
+
+    return VariableExpression;
+}());
+
+var UriTemplate = (function () {
+    function UriTemplate (templateText, expressions, regexp_string) {
+        this.templateText = templateText;
+        this.expressions = expressions;
+
+        if (regexp_string !== undefined) {
+          this.regexp = new RegExp("^" + regexp_string + "$");
+        }
+
+        objectHelper.deepFreeze(this);
+    }
+
+    UriTemplate.prototype.toString = function () {
+        return this.templateText;
+    };
+
+    UriTemplate.prototype.expand = function (variables) {
+        // this.expressions.map(function (expression) {return expression.expand(variables);}).join('');
+        var
+            index,
+            result = '';
+        for (index = 0; index < this.expressions.length; index += 1) {
+            result += this.expressions[index].expand(variables);
+        }
+        return result;
+    };
+
+    UriTemplate.prototype.extract = function (text) {
+      var expression_index,
+          extracted_index = 1,
+          expression,
+          varspec,
+          matched = true,
+          variables = {},
+          result;
+
+      if ((this.regexp !== undefined) && (this.regexp.test(text))) {
+        result = this.regexp.exec(text);
+        for (expression_index = 0; expression_index < this.expressions.length; expression_index += 1) {
+          expression = this.expressions[expression_index];
+          if (expression.literal === undefined) {
+            if ((expression.operator !== undefined) && (expression.operator.symbol.length === 0) && (expression.varspecs.length === 1)) {
+              varspec = expression.varspecs[0];
+              if ((varspec.exploded === false) && (varspec.maxLength === null)) {
+                if (result[extracted_index].indexOf(',') === -1) {
+                  variables[varspec.varname] = decodeURIComponent(result[extracted_index]);
+                  extracted_index += 1;
+                } else {
+                  matched = false;
+                }
+              } else {
+                matched = false;
+              }
+            } else {
+              matched = false;
+            }
+          }
+        }
+        if (matched) {
+          return variables;
+        }
+      }
+      return false;
+    };
+
+    UriTemplate.parse = parse;
+    UriTemplate.UriTemplateError = UriTemplateError;
+    return UriTemplate;
+}());
+
+    exportCallback(UriTemplate);
+
+}(function (UriTemplate) {
+        "use strict";
+        // export UriTemplate, when module is present, or pass it to window or global
+        if (typeof module !== "undefined") {
+            module.exports = UriTemplate;
+        }
+        else if (typeof define === "function") {
+            define([],function() {
+                return UriTemplate;
+            });
+        }
+        else if (typeof window !== "undefined") {
+            window.UriTemplate = UriTemplate;
+        }
+        else {
+            global.UriTemplate = UriTemplate;
+        }
+    }
+));
+;// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
+// This work is free. You can redistribute it and/or modify it
+// under the terms of the WTFPL, Version 2
+// For more information see LICENSE.txt or http://www.wtfpl.net/
+//
+// For more information, the home page:
+// http://pieroxy.net/blog/pages/lz-string/testing.html
+//
+// LZ-based compression algorithm, version 1.4.4
+var LZString = (function() {
+
+// private property
+var f = String.fromCharCode;
+var keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
+var baseReverseDic = {};
+
+function getBaseValue(alphabet, character) {
+  if (!baseReverseDic[alphabet]) {
+    baseReverseDic[alphabet] = {};
+    for (var i=0 ; i<alphabet.length ; i++) {
+      baseReverseDic[alphabet][alphabet.charAt(i)] = i;
+    }
+  }
+  return baseReverseDic[alphabet][character];
+}
+
+var LZString = {
+  compressToBase64 : function (input) {
+    if (input == null) return "";
+    var res = LZString._compress(input, 6, function(a){return keyStrBase64.charAt(a);});
+    switch (res.length % 4) { // To produce valid Base64
+    default: // When could this happen ?
+    case 0 : return res;
+    case 1 : return res+"===";
+    case 2 : return res+"==";
+    case 3 : return res+"=";
+    }
+  },
+
+  decompressFromBase64 : function (input) {
+    if (input == null) return "";
+    if (input == "") return null;
+    return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrBase64, input.charAt(index)); });
+  },
+
+  compressToUTF16 : function (input) {
+    if (input == null) return "";
+    return LZString._compress(input, 15, function(a){return f(a+32);}) + " ";
+  },
+
+  decompressFromUTF16: function (compressed) {
+    if (compressed == null) return "";
+    if (compressed == "") return null;
+    return LZString._decompress(compressed.length, 16384, function(index) { return compressed.charCodeAt(index) - 32; });
+  },
+
+  //compress into uint8array (UCS-2 big endian format)
+  compressToUint8Array: function (uncompressed) {
+    var compressed = LZString.compress(uncompressed);
+    var buf=new Uint8Array(compressed.length*2); // 2 bytes per character
+
+    for (var i=0, TotalLen=compressed.length; i<TotalLen; i++) {
+      var current_value = compressed.charCodeAt(i);
+      buf[i*2] = current_value >>> 8;
+      buf[i*2+1] = current_value % 256;
+    }
+    return buf;
+  },
+
+  //decompress from uint8array (UCS-2 big endian format)
+  decompressFromUint8Array:function (compressed) {
+    if (compressed===null || compressed===undefined){
+        return LZString.decompress(compressed);
+    } else {
+        var buf=new Array(compressed.length/2); // 2 bytes per character
+        for (var i=0, TotalLen=buf.length; i<TotalLen; i++) {
+          buf[i]=compressed[i*2]*256+compressed[i*2+1];
+        }
+
+        var result = [];
+        buf.forEach(function (c) {
+          result.push(f(c));
+        });
+        return LZString.decompress(result.join(''));
+
+    }
+
+  },
+
+
+  //compress into a string that is already URI encoded
+  compressToEncodedURIComponent: function (input) {
+    if (input == null) return "";
+    return LZString._compress(input, 6, function(a){return keyStrUriSafe.charAt(a);});
+  },
+
+  //decompress from an output of compressToEncodedURIComponent
+  decompressFromEncodedURIComponent:function (input) {
+    if (input == null) return "";
+    if (input == "") return null;
+    input = input.replace(/ /g, "+");
+    return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrUriSafe, input.charAt(index)); });
+  },
+
+  compress: function (uncompressed) {
+    return LZString._compress(uncompressed, 16, function(a){return f(a);});
+  },
+  _compress: function (uncompressed, bitsPerChar, getCharFromInt) {
+    if (uncompressed == null) return "";
+    var i, value,
+        context_dictionary= {},
+        context_dictionaryToCreate= {},
+        context_c="",
+        context_wc="",
+        context_w="",
+        context_enlargeIn= 2, // Compensate for the first entry which should not count
+        context_dictSize= 3,
+        context_numBits= 2,
+        context_data=[],
+        context_data_val=0,
+        context_data_position=0,
+        ii;
+
+    for (ii = 0; ii < uncompressed.length; ii += 1) {
+      context_c = uncompressed.charAt(ii);
+      if (!Object.prototype.hasOwnProperty.call(context_dictionary,context_c)) {
+        context_dictionary[context_c] = context_dictSize++;
+        context_dictionaryToCreate[context_c] = true;
+      }
+
+      context_wc = context_w + context_c;
+      if (Object.prototype.hasOwnProperty.call(context_dictionary,context_wc)) {
+        context_w = context_wc;
+      } else {
+        if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
+          if (context_w.charCodeAt(0)<256) {
+            for (i=0 ; i<context_numBits ; i++) {
+              context_data_val = (context_data_val << 1);
+              if (context_data_position == bitsPerChar-1) {
+                context_data_position = 0;
+                context_data.push(getCharFromInt(context_data_val));
+                context_data_val = 0;
+              } else {
+                context_data_position++;
+              }
+            }
+            value = context_w.charCodeAt(0);
+            for (i=0 ; i<8 ; i++) {
+              context_data_val = (context_data_val << 1) | (value&1);
+              if (context_data_position == bitsPerChar-1) {
+                context_data_position = 0;
+                context_data.push(getCharFromInt(context_data_val));
+                context_data_val = 0;
+              } else {
+                context_data_position++;
+              }
+              value = value >> 1;
+            }
+          } else {
+            value = 1;
+            for (i=0 ; i<context_numBits ; i++) {
+              context_data_val = (context_data_val << 1) | value;
+              if (context_data_position ==bitsPerChar-1) {
+                context_data_position = 0;
+                context_data.push(getCharFromInt(context_data_val));
+                context_data_val = 0;
+              } else {
+                context_data_position++;
+              }
+              value = 0;
+            }
+            value = context_w.charCodeAt(0);
+            for (i=0 ; i<16 ; i++) {
+              context_data_val = (context_data_val << 1) | (value&1);
+              if (context_data_position == bitsPerChar-1) {
+                context_data_position = 0;
+                context_data.push(getCharFromInt(context_data_val));
+                context_data_val = 0;
+              } else {
+                context_data_position++;
+              }
+              value = value >> 1;
+            }
+          }
+          context_enlargeIn--;
+          if (context_enlargeIn == 0) {
+            context_enlargeIn = Math.pow(2, context_numBits);
+            context_numBits++;
+          }
+          delete context_dictionaryToCreate[context_w];
+        } else {
+          value = context_dictionary[context_w];
+          for (i=0 ; i<context_numBits ; i++) {
+            context_data_val = (context_data_val << 1) | (value&1);
+            if (context_data_position == bitsPerChar-1) {
+              context_data_position = 0;
+              context_data.push(getCharFromInt(context_data_val));
+              context_data_val = 0;
+            } else {
+              context_data_position++;
+            }
+            value = value >> 1;
+          }
+
+
+        }
+        context_enlargeIn--;
+        if (context_enlargeIn == 0) {
+          context_enlargeIn = Math.pow(2, context_numBits);
+          context_numBits++;
+        }
+        // Add wc to the dictionary.
+        context_dictionary[context_wc] = context_dictSize++;
+        context_w = String(context_c);
+      }
+    }
+
+    // Output the code for w.
+    if (context_w !== "") {
+      if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
+        if (context_w.charCodeAt(0)<256) {
+          for (i=0 ; i<context_numBits ; i++) {
+            context_data_val = (context_data_val << 1);
+            if (context_data_position == bitsPerChar-1) {
+              context_data_position = 0;
+              context_data.push(getCharFromInt(context_data_val));
+              context_data_val = 0;
+            } else {
+              context_data_position++;
+            }
+          }
+          value = context_w.charCodeAt(0);
+          for (i=0 ; i<8 ; i++) {
+            context_data_val = (context_data_val << 1) | (value&1);
+            if (context_data_position == bitsPerChar-1) {
+              context_data_position = 0;
+              context_data.push(getCharFromInt(context_data_val));
+              context_data_val = 0;
+            } else {
+              context_data_position++;
+            }
+            value = value >> 1;
+          }
+        } else {
+          value = 1;
+          for (i=0 ; i<context_numBits ; i++) {
+            context_data_val = (context_data_val << 1) | value;
+            if (context_data_position == bitsPerChar-1) {
+              context_data_position = 0;
+              context_data.push(getCharFromInt(context_data_val));
+              context_data_val = 0;
+            } else {
+              context_data_position++;
+            }
+            value = 0;
+          }
+          value = context_w.charCodeAt(0);
+          for (i=0 ; i<16 ; i++) {
+            context_data_val = (context_data_val << 1) | (value&1);
+            if (context_data_position == bitsPerChar-1) {
+              context_data_position = 0;
+              context_data.push(getCharFromInt(context_data_val));
+              context_data_val = 0;
+            } else {
+              context_data_position++;
+            }
+            value = value >> 1;
+          }
+        }
+        context_enlargeIn--;
+        if (context_enlargeIn == 0) {
+          context_enlargeIn = Math.pow(2, context_numBits);
+          context_numBits++;
+        }
+        delete context_dictionaryToCreate[context_w];
+      } else {
+        value = context_dictionary[context_w];
+        for (i=0 ; i<context_numBits ; i++) {
+          context_data_val = (context_data_val << 1) | (value&1);
+          if (context_data_position == bitsPerChar-1) {
+            context_data_position = 0;
+            context_data.push(getCharFromInt(context_data_val));
+            context_data_val = 0;
+          } else {
+            context_data_position++;
+          }
+          value = value >> 1;
+        }
+
+
+      }
+      context_enlargeIn--;
+      if (context_enlargeIn == 0) {
+        context_enlargeIn = Math.pow(2, context_numBits);
+        context_numBits++;
+      }
+    }
+
+    // Mark the end of the stream
+    value = 2;
+    for (i=0 ; i<context_numBits ; i++) {
+      context_data_val = (context_data_val << 1) | (value&1);
+      if (context_data_position == bitsPerChar-1) {
+        context_data_position = 0;
+        context_data.push(getCharFromInt(context_data_val));
+        context_data_val = 0;
+      } else {
+        context_data_position++;
+      }
+      value = value >> 1;
+    }
+
+    // Flush the last char
+    while (true) {
+      context_data_val = (context_data_val << 1);
+      if (context_data_position == bitsPerChar-1) {
+        context_data.push(getCharFromInt(context_data_val));
+        break;
+      }
+      else context_data_position++;
+    }
+    return context_data.join('');
+  },
+
+  decompress: function (compressed) {
+    if (compressed == null) return "";
+    if (compressed == "") return null;
+    return LZString._decompress(compressed.length, 32768, function(index) { return compressed.charCodeAt(index); });
+  },
+
+  _decompress: function (length, resetValue, getNextValue) {
+    var dictionary = [],
+        next,
+        enlargeIn = 4,
+        dictSize = 4,
+        numBits = 3,
+        entry = "",
+        result = [],
+        i,
+        w,
+        bits, resb, maxpower, power,
+        c,
+        data = {val:getNextValue(0), position:resetValue, index:1};
+
+    for (i = 0; i < 3; i += 1) {
+      dictionary[i] = i;
+    }
+
+    bits = 0;
+    maxpower = Math.pow(2,2);
+    power=1;
+    while (power!=maxpower) {
+      resb = data.val & data.position;
+      data.position >>= 1;
+      if (data.position == 0) {
+        data.position = resetValue;
+        data.val = getNextValue(data.index++);
+      }
+      bits |= (resb>0 ? 1 : 0) * power;
+      power <<= 1;
+    }
+
+    switch (next = bits) {
+      case 0:
+          bits = 0;
+          maxpower = Math.pow(2,8);
+          power=1;
+          while (power!=maxpower) {
+            resb = data.val & data.position;
+            data.position >>= 1;
+            if (data.position == 0) {
+              data.position = resetValue;
+              data.val = getNextValue(data.index++);
+            }
+            bits |= (resb>0 ? 1 : 0) * power;
+            power <<= 1;
+          }
+        c = f(bits);
+        break;
+      case 1:
+          bits = 0;
+          maxpower = Math.pow(2,16);
+          power=1;
+          while (power!=maxpower) {
+            resb = data.val & data.position;
+            data.position >>= 1;
+            if (data.position == 0) {
+              data.position = resetValue;
+              data.val = getNextValue(data.index++);
+            }
+            bits |= (resb>0 ? 1 : 0) * power;
+            power <<= 1;
+          }
+        c = f(bits);
+        break;
+      case 2:
+        return "";
+    }
+    dictionary[3] = c;
+    w = c;
+    result.push(c);
+    while (true) {
+      if (data.index > length) {
+        return "";
+      }
+
+      bits = 0;
+      maxpower = Math.pow(2,numBits);
+      power=1;
+      while (power!=maxpower) {
+        resb = data.val & data.position;
+        data.position >>= 1;
+        if (data.position == 0) {
+          data.position = resetValue;
+          data.val = getNextValue(data.index++);
+        }
+        bits |= (resb>0 ? 1 : 0) * power;
+        power <<= 1;
+      }
+
+      switch (c = bits) {
+        case 0:
+          bits = 0;
+          maxpower = Math.pow(2,8);
+          power=1;
+          while (power!=maxpower) {
+            resb = data.val & data.position;
+            data.position >>= 1;
+            if (data.position == 0) {
+              data.position = resetValue;
+              data.val = getNextValue(data.index++);
+            }
+            bits |= (resb>0 ? 1 : 0) * power;
+            power <<= 1;
+          }
+
+          dictionary[dictSize++] = f(bits);
+          c = dictSize-1;
+          enlargeIn--;
+          break;
+        case 1:
+          bits = 0;
+          maxpower = Math.pow(2,16);
+          power=1;
+          while (power!=maxpower) {
+            resb = data.val & data.position;
+            data.position >>= 1;
+            if (data.position == 0) {
+              data.position = resetValue;
+              data.val = getNextValue(data.index++);
+            }
+            bits |= (resb>0 ? 1 : 0) * power;
+            power <<= 1;
+          }
+          dictionary[dictSize++] = f(bits);
+          c = dictSize-1;
+          enlargeIn--;
+          break;
+        case 2:
+          return result.join('');
+      }
+
+      if (enlargeIn == 0) {
+        enlargeIn = Math.pow(2, numBits);
+        numBits++;
+      }
+
+      if (dictionary[c]) {
+        entry = dictionary[c];
+      } else {
+        if (c === dictSize) {
+          entry = w + w.charAt(0);
+        } else {
+          return null;
+        }
+      }
+      result.push(entry);
+
+      // Add w+entry[0] to the dictionary.
+      dictionary[dictSize++] = w + entry.charAt(0);
+      enlargeIn--;
+
+      w = entry;
+
+      if (enlargeIn == 0) {
+        enlargeIn = Math.pow(2, numBits);
+        numBits++;
+      }
+
+    }
+  }
+};
+  return LZString;
+})();
+
+if (typeof define === 'function' && define.amd) {
+  define(function () { return LZString; });
+} else if( typeof module !== 'undefined' && module != null ) {
+  module.exports = LZString
+}
+;//! moment.js
+//! version : 2.13.0
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+//! license : MIT
+//! momentjs.com
+
+;(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 utils_hooks__hooks () {
+        return hookCallback.apply(null, arguments);
+    }
+
+    // This is done to register the method called with moment()
+    // without creating circular dependencies.
+    function setHookCallback (callback) {
+        hookCallback = callback;
+    }
+
+    function isArray(input) {
+        return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
+    }
+
+    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 create_utc__createUTC (input, format, locale, strict) {
+        return createLocalOrUTC(input, format, locale, strict, true).utc();
+    }
+
+    function defaultParsingFlags() {
+        // We need to deep clone this object.
+        return {
+            empty           : false,
+            unusedTokens    : [],
+            unusedInput     : [],
+            overflow        : -2,
+            charsLeftOver   : 0,
+            nullInput       : false,
+            invalidMonth    : null,
+            invalidFormat   : false,
+            userInvalidated : false,
+            iso             : false,
+            parsedDateParts : [],
+            meridiem        : null
+        };
+    }
+
+    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 valid__isValid(m) {
+        if (m._isValid == null) {
+            var flags = getParsingFlags(m);
+            var parsedParts = some.call(flags.parsedDateParts, function (i) {
+                return i != null;
+            });
+            m._isValid = !isNaN(m._d.getTime()) &&
+                flags.overflow < 0 &&
+                !flags.empty &&
+                !flags.invalidMonth &&
+                !flags.invalidWeekday &&
+                !flags.nullInput &&
+                !flags.invalidFormat &&
+                !flags.userInvalidated &&
+                (!flags.meridiem || (flags.meridiem && parsedParts));
+
+            if (m._strict) {
+                m._isValid = m._isValid &&
+                    flags.charsLeftOver === 0 &&
+                    flags.unusedTokens.length === 0 &&
+                    flags.bigHour === undefined;
+            }
+        }
+        return m._isValid;
+    }
+
+    function valid__createInvalid (flags) {
+        var m = create_utc__createUTC(NaN);
+        if (flags != null) {
+            extend(getParsingFlags(m), flags);
+        }
+        else {
+            getParsingFlags(m).userInvalidated = true;
+        }
+
+        return m;
+    }
+
+    function isUndefined(input) {
+        return input === void 0;
+    }
+
+    // Plugins that add properties should also add the key here (null value),
+    // so we can properly clone ourselves.
+    var momentProperties = utils_hooks__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 in momentProperties) {
+                prop = momentProperties[i];
+                val = from[prop];
+                if (!isUndefined(val)) {
+                    to[prop] = val;
+                }
+            }
+        }
+
+        return to;
+    }
+
+    var updateInProgress = false;
+
+    // Moment prototype object
+    function Moment(config) {
+        copyConfig(this, config);
+        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
+        // Prevent infinite loop in case updateOffset creates new moment
+        // objects.
+        if (updateInProgress === false) {
+            updateInProgress = true;
+            utils_hooks__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);
+        } else {
+            return Math.floor(number);
+        }
+    }
+
+    function toInt(argumentForCoercion) {
+        var coercedNumber = +argumentForCoercion,
+            value = 0;
+
+        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
+            value = absFloor(coercedNumber);
+        }
+
+        return value;
+    }
+
+    // compare two arrays, return the number of differences
+    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 (utils_hooks__hooks.suppressDeprecationWarnings === false &&
+                (typeof console !==  'undefined') && console.warn) {
+            console.warn('Deprecation warning: ' + msg);
+        }
+    }
+
+    function deprecate(msg, fn) {
+        var firstTime = true;
+
+        return extend(function () {
+            if (utils_hooks__hooks.deprecationHandler != null) {
+                utils_hooks__hooks.deprecationHandler(null, msg);
+            }
+            if (firstTime) {
+                warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack);
+                firstTime = false;
+            }
+            return fn.apply(this, arguments);
+        }, fn);
+    }
+
+    var deprecations = {};
+
+    function deprecateSimple(name, msg) {
+        if (utils_hooks__hooks.deprecationHandler != null) {
+            utils_hooks__hooks.deprecationHandler(name, msg);
+        }
+        if (!deprecations[name]) {
+            warn(msg);
+            deprecations[name] = true;
+        }
+    }
+
+    utils_hooks__hooks.suppressDeprecationWarnings = false;
+    utils_hooks__hooks.deprecationHandler = null;
+
+    function isFunction(input) {
+        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
+    }
+
+    function isObject(input) {
+        return Object.prototype.toString.call(input) === '[object Object]';
+    }
+
+    function locale_set__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;
+        // Lenient ordinal parsing accepts just a number in addition to
+        // number + (possibly) stuff coming from _ordinalParseLenient.
+        this._ordinalParseLenient = new RegExp(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];
+                }
+            }
+        }
+        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;
+        };
+    }
+
+    // internal storage for locale config files
+    var locales = {};
+    var globalLocale;
+
+    function normalizeLocale(key) {
+        return key ? key.toLowerCase().replace('_', '-') : key;
+    }
+
+    // pick the locale from the array
+    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
+    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
+    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) {
+                    //the next array item is better than a shallower substring of this one
+                    break;
+                }
+                j--;
+            }
+            i++;
+        }
+        return null;
+    }
+
+    function loadLocale(name) {
+        var oldLocale = null;
+        // TODO: Find a better way to register and load all the locales in Node
+        if (!locales[name] && (typeof module !== 'undefined') &&
+                module && module.exports) {
+            try {
+                oldLocale = globalLocale._abbr;
+                require('./locale/' + name);
+                // because defineLocale currently also sets the global locale, we
+                // want to undo that for lazy loaded locales
+                locale_locales__getSetGlobalLocale(oldLocale);
+            } catch (e) { }
+        }
+        return locales[name];
+    }
+
+    // This function will load locale and then set the global locale.  If
+    // no arguments are passed in, it will simply return the current global
+    // locale key.
+    function locale_locales__getSetGlobalLocale (key, values) {
+        var data;
+        if (key) {
+            if (isUndefined(values)) {
+                data = locale_locales__getLocale(key);
+            }
+            else {
+                data = defineLocale(key, values);
+            }
+
+            if (data) {
+                // moment.duration._locale = moment._locale = data;
+                globalLocale = data;
+            }
+        }
+
+        return globalLocale._abbr;
+    }
+
+    function defineLocale (name, config) {
+        if (config !== null) {
+            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');
+                config = mergeConfigs(locales[name]._config, config);
+            } else if (config.parentLocale != null) {
+                if (locales[config.parentLocale] != null) {
+                    config = mergeConfigs(locales[config.parentLocale]._config, config);
+                } else {
+                    // treat as if there is no base config
+                    deprecateSimple('parentLocaleUndefined',
+                            'specified parentLocale is not defined yet');
+                }
+            }
+            locales[name] = new Locale(config);
+
+            // backwards compat for now: also set the locale
+            locale_locales__getSetGlobalLocale(name);
+
+            return locales[name];
+        } else {
+            // useful for testing
+            delete locales[name];
+            return null;
+        }
+    }
+
+    function updateLocale(name, config) {
+        if (config != null) {
+            var locale;
+            if (locales[name] != null) {
+                config = mergeConfigs(locales[name]._config, config);
+            }
+            locale = new Locale(config);
+            locale.parentLocale = locales[name];
+            locales[name] = locale;
+
+            // backwards compat for now: also set the locale
+            locale_locales__getSetGlobalLocale(name);
+        } else {
+            // pass null for config to unupdate, useful for tests
+            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];
+    }
+
+    // returns locale data
+    function locale_locales__getLocale (key) {
+        var locale;
+
+        if (key && key._locale && key._locale._abbr) {
+            key = key._locale._abbr;
+        }
+
+        if (!key) {
+            return globalLocale;
+        }
+
+        if (!isArray(key)) {
+            //short-circuit everything else
+            locale = loadLocale(key);
+            if (locale) {
+                return locale;
+            }
+            key = [key];
+        }
+
+        return chooseLocale(key);
+    }
+
+    function locale_locales__listLocales() {
+        return keys(locales);
+    }
+
+    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;
+    }
+
+    function makeGetSet (unit, keepTime) {
+        return function (value) {
+            if (value != null) {
+                get_set__set(this, unit, value);
+                utils_hooks__hooks.updateOffset(this, keepTime);
+                return this;
+            } else {
+                return get_set__get(this, unit);
+            }
+        };
+    }
+
+    function get_set__get (mom, unit) {
+        return mom.isValid() ?
+            mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
+    }
+
+    function get_set__set (mom, unit, value) {
+        if (mom.isValid()) {
+            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
+        }
+    }
+
+    // MOMENTS
+
+    function getSet (units, value) {
+        var unit;
+        if (typeof units === 'object') {
+            for (unit in units) {
+                this.set(unit, units[unit]);
+            }
+        } else {
+            units = normalizeUnits(units);
+            if (isFunction(this[units])) {
+                return this[units](value);
+            }
+        }
+        return this;
+    }
+
+    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 = {};
+
+    // token:    'M'
+    // padded:   ['MM', 2]
+    // ordinal:  'Mo'
+    // callback: function () { this.month() + 1 }
+    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 += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
+            }
+            return output;
+        };
+    }
+
+    // format date using native date object
+    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/;            //       0 - 9
+    var match2         = /\d\d/;          //      00 - 99
+    var match3         = /\d{3}/;         //     000 - 999
+    var match4         = /\d{4}/;         //    0000 - 9999
+    var match6         = /[+-]?\d{6}/;    // -999999 - 999999
+    var match1to2      = /\d\d?/;         //       0 - 99
+    var match3to4      = /\d\d\d\d?/;     //     999 - 9999
+    var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
+    var match1to3      = /\d{1,3}/;       //       0 - 999
+    var match1to4      = /\d{1,4}/;       //       0 - 9999
+    var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
+
+    var matchUnsigned  = /\d+/;           //       0 - inf
+    var matchSigned    = /[+-]?\d+/;      //    -inf - inf
+
+    var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
+    var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
+
+    var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
+
+    // any word (or two) characters or numbers including two/three word month in arabic.
+    // includes scottish gaelic two word and hyphenated months
+    var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){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);
+    }
+
+    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+    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 (typeof callback === 'number') {
+            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;
+
+    var indexOf;
+
+    if (Array.prototype.indexOf) {
+        indexOf = Array.prototype.indexOf;
+    } else {
+        indexOf = function (o) {
+            // I know
+            var i;
+            for (i = 0; i < this.length; ++i) {
+                if (this[i] === o) {
+                    return i;
+                }
+            }
+            return -1;
+        };
+    }
+
+    function daysInMonth(year, month) {
+        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
+    }
+
+    // FORMATTING
+
+    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);
+    });
+
+    // ALIASES
+
+    addUnitAlias('month', 'M');
+
+    // PARSING
+
+    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 we didn't find a month name, mark the date as invalid.
+        if (month != null) {
+            array[MONTH] = month;
+        } else {
+            getParsingFlags(config).invalidMonth = input;
+        }
+    });
+
+    // LOCALES
+
+    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) {
+        return isArray(this._months) ? this._months[m.month()] :
+            this._months[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) {
+        return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
+            this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
+    }
+
+    function units_month__handleStrictParse(monthName, format, strict) {
+        var i, ii, mom, llc = monthName.toLocaleLowerCase();
+        if (!this._monthsParse) {
+            // this is not used
+            this._monthsParse = [];
+            this._longMonthsParse = [];
+            this._shortMonthsParse = [];
+            for (i = 0; i < 12; ++i) {
+                mom = create_utc__createUTC([2000, 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 units_month__handleStrictParse.call(this, monthName, format, strict);
+        }
+
+        if (!this._monthsParse) {
+            this._monthsParse = [];
+            this._longMonthsParse = [];
+            this._shortMonthsParse = [];
+        }
+
+        // TODO: add sorting
+        // Sorting makes sure if one month (or abbr) is a prefix of another
+        // see sorting in computeMonthsParse
+        for (i = 0; i < 12; i++) {
+            // make the regex if we don't have it already
+            mom = create_utc__createUTC([2000, 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');
+            }
+            // test the regex
+            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;
+            }
+        }
+    }
+
+    // MOMENTS
+
+    function setMonth (mom, value) {
+        var dayOfMonth;
+
+        if (!mom.isValid()) {
+            // No op
+            return mom;
+        }
+
+        if (typeof value === 'string') {
+            if (/^\d+$/.test(value)) {
+                value = toInt(value);
+            } else {
+                value = mom.localeData().monthsParse(value);
+                // TODO: Another silent failure?
+                if (typeof value !== 'number') {
+                    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);
+            utils_hooks__hooks.updateOffset(this, true);
+            return this;
+        } else {
+            return get_set__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 {
+            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 {
+            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++) {
+            // make the regex if we don't have it already
+            mom = create_utc__createUTC([2000, i]);
+            shortPieces.push(this.monthsShort(mom, ''));
+            longPieces.push(this.months(mom, ''));
+            mixedPieces.push(this.months(mom, ''));
+            mixedPieces.push(this.monthsShort(mom, ''));
+        }
+        // Sorting makes sure if one month (or abbr) is a prefix of another it
+        // will match the longer piece.
+        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]);
+            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 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;
+    }
+
+    // iso 8601 regex
+    // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
+    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}/],
+        // YYYYMM is NOT allowed by the standard
+        ['GGGG[W]WWE', /\d{4}W\d{3}/],
+        ['GGGG[W]WW', /\d{4}W\d{2}/, false],
+        ['YYYYDDD', /\d{7}/]
+    ];
+
+    // iso time formats and regexes
+    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;
+
+    // date from iso format
+    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])) {
+                        // match[2] should be 'T' or space
+                        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;
+        }
+    }
+
+    // date from iso format or fallback
+    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;
+            utils_hooks__hooks.createFromInputFallback(config);
+        }
+    }
+
+    utils_hooks__hooks.createFromInputFallback = deprecate(
+        'moment construction falls back to js Date. This is ' +
+        'discouraged and will be removed in upcoming major ' +
+        'release. Please refer to ' +
+        'https://github.com/moment/moment/issues/1407 for more info.',
+        function (config) {
+            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
+        }
+    );
+
+    function createDate (y, m, d, h, M, s, ms) {
+        //can't just apply() to create a date:
+        //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
+        var date = new Date(y, m, d, h, M, s, ms);
+
+        //the date constructor remaps years 0-99 to 1900-1999
+        if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
+            date.setFullYear(y);
+        }
+        return date;
+    }
+
+    function createUTCDate (y) {
+        var date = new Date(Date.UTC.apply(null, arguments));
+
+        //the Date.UTC function remaps years 0-99 to 1900-1999
+        if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
+            date.setUTCFullYear(y);
+        }
+        return date;
+    }
+
+    // FORMATTING
+
+    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');
+
+    // ALIASES
+
+    addUnitAlias('year', 'y');
+
+    // PARSING
+
+    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 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
+    });
+    addParseToken('YY', function (input, array) {
+        array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
+    });
+    addParseToken('Y', function (input, array) {
+        array[YEAR] = parseInt(input, 10);
+    });
+
+    // HELPERS
+
+    function daysInYear(year) {
+        return isLeapYear(year) ? 366 : 365;
+    }
+
+    function isLeapYear(year) {
+        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+    }
+
+    // HOOKS
+
+    utils_hooks__hooks.parseTwoDigitYear = function (input) {
+        return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
+    };
+
+    // MOMENTS
+
+    var getSetYear = makeGetSet('FullYear', true);
+
+    function getIsLeapYear () {
+        return isLeapYear(this.year());
+    }
+
+    // start-of-first-week - start-of-year
+    function firstWeekOffset(year, dow, doy) {
+        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
+            fwd = 7 + dow - doy,
+            // first-week day local weekday -- which local weekday is fwd
+            fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
+
+        return -fwdlw + fwd - 1;
+    }
+
+    //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
+    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;
+    }
+
+    // Pick the first defined of two or three arguments.
+    function defaults(a, b, c) {
+        if (a != null) {
+            return a;
+        }
+        if (b != null) {
+            return b;
+        }
+        return c;
+    }
+
+    function currentDateArray(config) {
+        // hooks is actually the exported moment object
+        var nowValue = new Date(utils_hooks__hooks.now());
+        if (config._useUTC) {
+            return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
+        }
+        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
+    }
+
+    // convert an array to a date.
+    // the array should mirror the parameters below
+    // note: all values past the year are optional and will default to the lowest possible value.
+    // [year, month, day , hour, minute, second, millisecond]
+    function configFromArray (config) {
+        var i, date, input = [], currentDate, yearToUse;
+
+        if (config._d) {
+            return;
+        }
+
+        currentDate = currentDateArray(config);
+
+        //compute day of the year from weeks and weekdays
+        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
+            dayOfYearFromWeekInfo(config);
+        }
+
+        //if the day of the year is set, figure out what it is
+        if (config._dayOfYear) {
+            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
+
+            if (config._dayOfYear > daysInYear(yearToUse)) {
+                getParsingFlags(config)._overflowDayOfYear = true;
+            }
+
+            date = createUTCDate(yearToUse, 0, config._dayOfYear);
+            config._a[MONTH] = date.getUTCMonth();
+            config._a[DATE] = date.getUTCDate();
+        }
+
+        // Default to current date.
+        // * if no year, month, day of month are given, default to today
+        // * if day of month is given, default month and year
+        // * if month is given, default only year
+        // * if year is given, don't default anything
+        for (i = 0; i < 3 && config._a[i] == null; ++i) {
+            config._a[i] = input[i] = currentDate[i];
+        }
+
+        // Zero out whatever was not defaulted, including time
+        for (; i < 7; i++) {
+            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
+        }
+
+        // Check for 24:00:00.000
+        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);
+        // Apply timezone offset from input. The actual utcOffset can be changed
+        // with parseZone.
+        if (config._tzm != null) {
+            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
+        }
+
+        if (config._nextDay) {
+            config._a[HOUR] = 24;
+        }
+    }
+
+    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;
+
+            // TODO: We need to take the current isoWeekYear, but that depends on
+            // how we interpret now (local, utc, fixed offset). So create
+            // a now version of current config (take local/utc/offset flags, and
+            // create now).
+            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__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;
+
+            weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
+            week = defaults(w.w, 1);
+
+            if (w.d != null) {
+                // weekday -- low day numbers are considered next week
+                weekday = w.d;
+                if (weekday < 0 || weekday > 6) {
+                    weekdayOverflow = true;
+                }
+            } else if (w.e != null) {
+                // local weekday -- counting starts from begining of week
+                weekday = w.e + dow;
+                if (w.e < 0 || w.e > 6) {
+                    weekdayOverflow = true;
+                }
+            } else {
+                // default to begining of week
+                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;
+        }
+    }
+
+    // constant that refers to the ISO standard
+    utils_hooks__hooks.ISO_8601 = function () {};
+
+    // date from string and format string
+    function configFromStringAndFormat(config) {
+        // TODO: Move this to another part of the creation flow to prevent circular deps
+        if (config._f === utils_hooks__hooks.ISO_8601) {
+            configFromISO(config);
+            return;
+        }
+
+        config._a = [];
+        getParsingFlags(config).empty = true;
+
+        // This array is used to make a Date, either with `new Date` or `Date.UTC`
+        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];
+            // console.log('token', token, 'parsedInput', parsedInput,
+            //         'regex', getParseRegexForToken(token, config));
+            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;
+            }
+            // don't parse if it's not a known token
+            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);
+            }
+        }
+
+        // add remaining unparsed input length to the string
+        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
+        if (string.length > 0) {
+            getParsingFlags(config).unusedInput.push(string);
+        }
+
+        // clear _12h flag if hour is <= 12
+        if (getParsingFlags(config).bigHour === true &&
+                config._a[HOUR] <= 12 &&
+                config._a[HOUR] > 0) {
+            getParsingFlags(config).bigHour = undefined;
+        }
+
+        getParsingFlags(config).parsedDateParts = config._a.slice(0);
+        getParsingFlags(config).meridiem = config._meridiem;
+        // handle 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) {
+            // nothing to do
+            return hour;
+        }
+        if (locale.meridiemHour != null) {
+            return locale.meridiemHour(hour, meridiem);
+        } else if (locale.isPM != null) {
+            // Fallback
+            isPm = locale.isPM(meridiem);
+            if (isPm && hour < 12) {
+                hour += 12;
+            }
+            if (!isPm && hour === 12) {
+                hour = 0;
+            }
+            return hour;
+        } else {
+            // this is not supposed to happen
+            return hour;
+        }
+    }
+
+    // date from string and array of format strings
+    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 (!valid__isValid(tempConfig)) {
+                continue;
+            }
+
+            // if there is any input that was not parsed add a penalty for that format
+            currentScore += getParsingFlags(tempConfig).charsLeftOver;
+
+            //or tokens
+            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) {
+            // Adding is smart enough around DST
+            res.add(1, 'd');
+            res._nextDay = undefined;
+        }
+
+        return res;
+    }
+
+    function prepareConfig (config) {
+        var input = config._i,
+            format = config._f;
+
+        config._locale = config._locale || locale_locales__getLocale(config._l);
+
+        if (input === null || (format === undefined && input === '')) {
+            return valid__createInvalid({nullInput: true});
+        }
+
+        if (typeof input === 'string') {
+            config._i = input = config._locale.preparse(input);
+        }
+
+        if (isMoment(input)) {
+            return new Moment(checkOverflow(input));
+        } else if (isArray(format)) {
+            configFromStringAndArray(config);
+        } else if (format) {
+            configFromStringAndFormat(config);
+        } else if (isDate(input)) {
+            config._d = input;
+        } else {
+            configFromInput(config);
+        }
+
+        if (!valid__isValid(config)) {
+            config._d = null;
+        }
+
+        return config;
+    }
+
+    function configFromInput(config) {
+        var input = config._i;
+        if (input === undefined) {
+            config._d = new Date(utils_hooks__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 (typeof(input) === 'object') {
+            configFromObject(config);
+        } else if (typeof(input) === 'number') {
+            // from milliseconds
+            config._d = new Date(input);
+        } else {
+            utils_hooks__hooks.createFromInputFallback(config);
+        }
+    }
+
+    function createLocalOrUTC (input, format, locale, strict, isUTC) {
+        var c = {};
+
+        if (typeof(locale) === 'boolean') {
+            strict = locale;
+            locale = undefined;
+        }
+        // object construction must be done this way.
+        // https://github.com/moment/moment/issues/1423
+        c._isAMomentObject = true;
+        c._useUTC = c._isUTC = isUTC;
+        c._l = locale;
+        c._i = input;
+        c._f = format;
+        c._strict = strict;
+
+        return createFromConfig(c);
+    }
+
+    function local__createLocal (input, format, locale, strict) {
+        return createLocalOrUTC(input, format, locale, strict, false);
+    }
+
+    var prototypeMin = deprecate(
+         'moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
+         function () {
+             var other = local__createLocal.apply(null, arguments);
+             if (this.isValid() && other.isValid()) {
+                 return other < this ? this : other;
+             } else {
+                 return valid__createInvalid();
+             }
+         }
+     );
+
+    var prototypeMax = deprecate(
+        'moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
+        function () {
+            var other = local__createLocal.apply(null, arguments);
+            if (this.isValid() && other.isValid()) {
+                return other > this ? this : other;
+            } else {
+                return valid__createInvalid();
+            }
+        }
+    );
+
+    // Pick a moment m from moments so that m[fn](other) is true for all
+    // other. This relies on the function fn to be transitive.
+    //
+    // moments should either be an array of moment objects or an array, whose
+    // first element is an array of moment objects.
+    function pickBy(fn, moments) {
+        var res, i;
+        if (moments.length === 1 && isArray(moments[0])) {
+            moments = moments[0];
+        }
+        if (!moments.length) {
+            return local__createLocal();
+        }
+        res = moments[0];
+        for (i = 1; i < moments.length; ++i) {
+            if (!moments[i].isValid() || moments[i][fn](res)) {
+                res = moments[i];
+            }
+        }
+        return res;
+    }
+
+    // TODO: Use [].sort instead?
+    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());
+    };
+
+    function Duration (duration) {
+        var normalizedInput = normalizeObjectUnits(duration),
+            years = normalizedInput.year || 0,
+            quarters = normalizedInput.quarter || 0,
+            months = normalizedInput.month || 0,
+            weeks = normalizedInput.week || 0,
+            days = normalizedInput.day || 0,
+            hours = normalizedInput.hour || 0,
+            minutes = normalizedInput.minute || 0,
+            seconds = normalizedInput.second || 0,
+            milliseconds = normalizedInput.millisecond || 0;
+
+        // representation for dateAddRemove
+        this._milliseconds = +milliseconds +
+            seconds * 1e3 + // 1000
+            minutes * 6e4 + // 1000 * 60
+            hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
+        // Because of dateAddRemove treats 24 hours as different from a
+        // day when working around DST, we need to store them separately
+        this._days = +days +
+            weeks * 7;
+        // It is impossible translate months into days without knowing
+        // which months you are are talking about, so we have to store
+        // it separately.
+        this._months = +months +
+            quarters * 3 +
+            years * 12;
+
+        this._data = {};
+
+        this._locale = locale_locales__getLocale();
+
+        this._bubble();
+    }
+
+    function isDuration (obj) {
+        return obj instanceof Duration;
+    }
+
+    // FORMATTING
+
+    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', '');
+
+    // PARSING
+
+    addRegexToken('Z',  matchShortOffset);
+    addRegexToken('ZZ', matchShortOffset);
+    addParseToken(['Z', 'ZZ'], function (input, array, config) {
+        config._useUTC = true;
+        config._tzm = offsetFromString(matchShortOffset, input);
+    });
+
+    // HELPERS
+
+    // timezone chunker
+    // '+10:00' > ['10',  '00']
+    // '-1530'  > ['-15', '30']
+    var chunkOffset = /([\+\-]|\d\d)/gi;
+
+    function offsetFromString(matcher, string) {
+        var matches = ((string || '').match(matcher) || []);
+        var chunk   = matches[matches.length - 1] || [];
+        var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
+        var minutes = +(parts[1] * 60) + toInt(parts[2]);
+
+        return parts[0] === '+' ? minutes : -minutes;
+    }
+
+    // Return a moment from input, that is local/utc/zone equivalent to model.
+    function cloneWithOffset(input, model) {
+        var res, diff;
+        if (model._isUTC) {
+            res = model.clone();
+            diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf();
+            // Use low-level api, because this fn is low-level api.
+            res._d.setTime(res._d.valueOf() + diff);
+            utils_hooks__hooks.updateOffset(res, false);
+            return res;
+        } else {
+            return local__createLocal(input).local();
+        }
+    }
+
+    function getDateOffset (m) {
+        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
+        // https://github.com/moment/moment/pull/1871
+        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
+    }
+
+    // HOOKS
+
+    // This function will be called whenever a moment is mutated.
+    // It is intended to keep the offset in sync with the timezone.
+    utils_hooks__hooks.updateOffset = function () {};
+
+    // MOMENTS
+
+    // keepLocalTime = true means only change the timezone, without
+    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
+    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
+    // +0200, so we adjust the time as needed, to be valid.
+    //
+    // Keeping the time actually adds/subtracts (one hour)
+    // from the actual represented time. That is why we call updateOffset
+    // a second time. In case it wants us to change the offset again
+    // _changeInProgress == true case, then we have to adjust, because
+    // there is no such time in the given timezone.
+    function getSetOffset (input, keepLocalTime) {
+        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);
+            } else if (Math.abs(input) < 16) {
+                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) {
+                    add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
+                } else if (!this._changeInProgress) {
+                    this._changeInProgress = true;
+                    utils_hooks__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) {
+            this.utcOffset(this._tzm);
+        } else if (typeof this._i === 'string') {
+            this.utcOffset(offsetFromString(matchOffset, this._i));
+        }
+        return this;
+    }
+
+    function hasAlignedHourOffset (input) {
+        if (!this.isValid()) {
+            return false;
+        }
+        input = input ? local__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 ? create_utc__createUTC(c._a) : local__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;
+    }
+
+    // ASP.NET json date format regex
+    var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/;
+
+    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
+    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
+    // and further modified to allow for strings containing both week and day
+    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 create__createDuration (input, key) {
+        var duration = input,
+            // matching against regexp is expensive, do it on demand
+            match = null,
+            sign,
+            ret,
+            diffRes;
+
+        if (isDuration(input)) {
+            duration = {
+                ms : input._milliseconds,
+                d  : input._days,
+                M  : input._months
+            };
+        } else if (typeof input === 'number') {
+            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(match[MILLISECOND]) * 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) {// checks for null or undefined
+            duration = {};
+        } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
+            diffRes = momentsDifference(local__createLocal(duration.from), local__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;
+    }
+
+    create__createDuration.fn = Duration.prototype;
+
+    function parseIso (inp, sign) {
+        // We'd normally use ~~inp for this, but unfortunately it also
+        // converts floats to ints.
+        // inp may be undefined, so careful calling replace on it.
+        var res = inp && parseFloat(inp.replace(',', '.'));
+        // apply sign while we're at it
+        return (isNaN(res) ? 0 : res) * sign;
+    }
+
+    function positiveMomentsDifference(base, other) {
+        var res = {milliseconds: 0, months: 0};
+
+        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 absRound (number) {
+        if (number < 0) {
+            return Math.round(-1 * number) * -1;
+        } else {
+            return Math.round(number);
+        }
+    }
+
+    // TODO: remove 'name' arg after deprecation is removed
+    function createAdder(direction, name) {
+        return function (val, period) {
+            var dur, tmp;
+            //invert the arguments, but complain about it
+            if (period !== null && !isNaN(+period)) {
+                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
+                tmp = val; val = period; period = tmp;
+            }
+
+            val = typeof val === 'string' ? +val : val;
+            dur = create__createDuration(val, period);
+            add_subtract__addSubtract(this, dur, direction);
+            return this;
+        };
+    }
+
+    function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
+        var milliseconds = duration._milliseconds,
+            days = absRound(duration._days),
+            months = absRound(duration._months);
+
+        if (!mom.isValid()) {
+            // No op
+            return;
+        }
+
+        updateOffset = updateOffset == null ? true : updateOffset;
+
+        if (milliseconds) {
+            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
+        }
+        if (days) {
+            get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
+        }
+        if (months) {
+            setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
+        }
+        if (updateOffset) {
+            utils_hooks__hooks.updateOffset(mom, days || months);
+        }
+    }
+
+    var add_subtract__add      = createAdder(1, 'add');
+    var add_subtract__subtract = createAdder(-1, 'subtract');
+
+    function moment_calendar__calendar (time, formats) {
+        // We want to compare the start of today, vs this.
+        // Getting start-of-today depends on whether we're local/utc/offset or not.
+        var now = time || local__createLocal(),
+            sod = cloneWithOffset(now, this).startOf('day'),
+            diff = this.diff(sod, 'days', true),
+            format = diff < -6 ? 'sameElse' :
+                diff < -1 ? 'lastWeek' :
+                diff < 0 ? 'lastDay' :
+                diff < 1 ? 'sameDay' :
+                diff < 2 ? 'nextDay' :
+                diff < 7 ? 'nextWeek' : 'sameElse';
+
+        var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]);
+
+        return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
+    }
+
+    function clone () {
+        return new Moment(this);
+    }
+
+    function isAfter (input, units) {
+        var localInput = isMoment(input) ? input : local__createLocal(input);
+        if (!(this.isValid() && localInput.isValid())) {
+            return false;
+        }
+        units = normalizeUnits(!isUndefined(units) ? 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 : local__createLocal(input);
+        if (!(this.isValid() && localInput.isValid())) {
+            return false;
+        }
+        units = normalizeUnits(!isUndefined(units) ? 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) {
+        inclusivity = inclusivity || '()';
+        return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
+            (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
+    }
+
+    function isSame (input, units) {
+        var localInput = isMoment(input) ? input : local__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,
+            delta, output;
+
+        if (!this.isValid()) {
+            return NaN;
+        }
+
+        that = cloneWithOffset(input, this);
+
+        if (!that.isValid()) {
+            return NaN;
+        }
+
+        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
+
+        units = normalizeUnits(units);
+
+        if (units === 'year' || units === 'month' || units === 'quarter') {
+            output = monthDiff(this, that);
+            if (units === 'quarter') {
+                output = output / 3;
+            } else if (units === 'year') {
+                output = output / 12;
+            }
+        } else {
+            delta = this - that;
+            output = units === 'second' ? delta / 1e3 : // 1000
+                units === 'minute' ? delta / 6e4 : // 1000 * 60
+                units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
+                units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
+                units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
+                delta;
+        }
+        return asFloat ? output : absFloor(output);
+    }
+
+    function monthDiff (a, b) {
+        // difference in months
+        var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
+            // b is in (anchor - 1 month, anchor + 1 month)
+            anchor = a.clone().add(wholeMonthDiff, 'months'),
+            anchor2, adjust;
+
+        if (b - anchor < 0) {
+            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
+            // linear across the month
+            adjust = (b - anchor) / (anchor - anchor2);
+        } else {
+            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
+            // linear across the month
+            adjust = (b - anchor) / (anchor2 - anchor);
+        }
+
+        //check for negative zero, return zero if negative zero
+        return -(wholeMonthDiff + adjust) || 0;
+    }
+
+    utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
+    utils_hooks__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 moment_format__toISOString () {
+        var m = this.clone().utc();
+        if (0 < m.year() && m.year() <= 9999) {
+            if (isFunction(Date.prototype.toISOString)) {
+                // native implementation is ~50x faster, use it when we can
+                return this.toDate().toISOString();
+            } else {
+                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+            }
+        } else {
+            return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+        }
+    }
+
+    function format (inputString) {
+        if (!inputString) {
+            inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat;
+        }
+        var output = formatMoment(this, inputString);
+        return this.localeData().postformat(output);
+    }
+
+    function from (time, withoutSuffix) {
+        if (this.isValid() &&
+                ((isMoment(time) && time.isValid()) ||
+                 local__createLocal(time).isValid())) {
+            return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
+        } else {
+            return this.localeData().invalidDate();
+        }
+    }
+
+    function fromNow (withoutSuffix) {
+        return this.from(local__createLocal(), withoutSuffix);
+    }
+
+    function to (time, withoutSuffix) {
+        if (this.isValid() &&
+                ((isMoment(time) && time.isValid()) ||
+                 local__createLocal(time).isValid())) {
+            return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
+        } else {
+            return this.localeData().invalidDate();
+        }
+    }
+
+    function toNow (withoutSuffix) {
+        return this.to(local__createLocal(), withoutSuffix);
+    }
+
+    // If passed a locale key, it will set the locale for this
+    // instance.  Otherwise, it will return the locale configuration
+    // variables for this instance.
+    function locale (key) {
+        var newLocaleData;
+
+        if (key === undefined) {
+            return this._locale._abbr;
+        } else {
+            newLocaleData = locale_locales__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;
+    }
+
+    function startOf (units) {
+        units = normalizeUnits(units);
+        // the following switch intentionally omits break keywords
+        // to utilize falling through the cases.
+        switch (units) {
+        case 'year':
+            this.month(0);
+            /* falls through */
+        case 'quarter':
+        case 'month':
+            this.date(1);
+            /* falls through */
+        case 'week':
+        case 'isoWeek':
+        case 'day':
+        case 'date':
+            this.hours(0);
+            /* falls through */
+        case 'hour':
+            this.minutes(0);
+            /* falls through */
+        case 'minute':
+            this.seconds(0);
+            /* falls through */
+        case 'second':
+            this.milliseconds(0);
+        }
+
+        // weeks are a special case
+        if (units === 'week') {
+            this.weekday(0);
+        }
+        if (units === 'isoWeek') {
+            this.isoWeekday(1);
+        }
+
+        // quarters are also special
+        if (units === 'quarter') {
+            this.month(Math.floor(this.month() / 3) * 3);
+        }
+
+        return this;
+    }
+
+    function endOf (units) {
+        units = normalizeUnits(units);
+        if (units === undefined || units === 'millisecond') {
+            return this;
+        }
+
+        // 'date' is an alias for 'day', so it should be considered as such.
+        if (units === 'date') {
+            units = 'day';
+        }
+
+        return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
+    }
+
+    function to_type__valueOf () {
+        return this._d.valueOf() - ((this._offset || 0) * 60000);
+    }
+
+    function unix () {
+        return Math.floor(this.valueOf() / 1000);
+    }
+
+    function toDate () {
+        return this._offset ? new Date(this.valueOf()) : this._d;
+    }
+
+    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 () {
+        // new Date(NaN).toJSON() === null
+        return this.isValid() ? this.toISOString() : null;
+    }
+
+    function moment_valid__isValid () {
+        return valid__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
+        };
+    }
+
+    // FORMATTING
+
+    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');
+
+    // ALIASES
+
+    addUnitAlias('weekYear', 'gg');
+    addUnitAlias('isoWeekYear', 'GG');
+
+    // PARSING
+
+    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] = utils_hooks__hooks.parseTwoDigitYear(input);
+    });
+
+    // MOMENTS
+
+    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;
+    }
+
+    // FORMATTING
+
+    addFormatToken('Q', 0, 'Qo', 'quarter');
+
+    // ALIASES
+
+    addUnitAlias('quarter', 'Q');
+
+    // PARSING
+
+    addRegexToken('Q', match1);
+    addParseToken('Q', function (input, array) {
+        array[MONTH] = (toInt(input) - 1) * 3;
+    });
+
+    // MOMENTS
+
+    function getSetQuarter (input) {
+        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
+    }
+
+    // FORMATTING
+
+    addFormatToken('w', ['ww', 2], 'wo', 'week');
+    addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
+
+    // ALIASES
+
+    addUnitAlias('week', 'w');
+    addUnitAlias('isoWeek', 'W');
+
+    // PARSING
+
+    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);
+    });
+
+    // HELPERS
+
+    // LOCALES
+
+    function localeWeek (mom) {
+        return weekOfYear(mom, this._week.dow, this._week.doy).week;
+    }
+
+    var defaultLocaleWeek = {
+        dow : 0, // Sunday is the first day of the week.
+        doy : 6  // The week that contains Jan 1st is the first week of the year.
+    };
+
+    function localeFirstDayOfWeek () {
+        return this._week.dow;
+    }
+
+    function localeFirstDayOfYear () {
+        return this._week.doy;
+    }
+
+    // MOMENTS
+
+    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');
+    }
+
+    // FORMATTING
+
+    addFormatToken('D', ['DD', 2], 'Do', 'date');
+
+    // ALIASES
+
+    addUnitAlias('date', 'D');
+
+    // PARSING
+
+    addRegexToken('D',  match1to2);
+    addRegexToken('DD', match1to2, match2);
+    addRegexToken('Do', function (isStrict, locale) {
+        return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
+    });
+
+    addParseToken(['D', 'DD'], DATE);
+    addParseToken('Do', function (input, array) {
+        array[DATE] = toInt(input.match(match1to2)[0], 10);
+    });
+
+    // MOMENTS
+
+    var getSetDayOfMonth = makeGetSet('Date', true);
+
+    // FORMATTING
+
+    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');
+
+    // ALIASES
+
+    addUnitAlias('day', 'd');
+    addUnitAlias('weekday', 'e');
+    addUnitAlias('isoWeekday', 'E');
+
+    // PARSING
+
+    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 we didn't get a weekday name, mark the date as invalid
+        if (weekday != null) {
+            week.d = weekday;
+        } else {
+            getParsingFlags(config).invalidWeekday = input;
+        }
+    });
+
+    addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
+        week[token] = toInt(input);
+    });
+
+    // HELPERS
+
+    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;
+    }
+
+    // LOCALES
+
+    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
+    function localeWeekdays (m, format) {
+        return isArray(this._weekdays) ? this._weekdays[m.day()] :
+            this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
+    }
+
+    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
+    function localeWeekdaysShort (m) {
+        return this._weekdaysShort[m.day()];
+    }
+
+    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
+    function localeWeekdaysMin (m) {
+        return this._weekdaysMin[m.day()];
+    }
+
+    function day_of_week__handleStrictParse(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 = create_utc__createUTC([2000, 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 day_of_week__handleStrictParse.call(this, weekdayName, format, strict);
+        }
+
+        if (!this._weekdaysParse) {
+            this._weekdaysParse = [];
+            this._minWeekdaysParse = [];
+            this._shortWeekdaysParse = [];
+            this._fullWeekdaysParse = [];
+        }
+
+        for (i = 0; i < 7; i++) {
+            // make the regex if we don't have it already
+
+            mom = create_utc__createUTC([2000, 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');
+            }
+            // test the regex
+            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;
+            }
+        }
+    }
+
+    // MOMENTS
+
+    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;
+        }
+        // behaves the same as moment#day except
+        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
+        // as a setter, sunday should belong to the previous week.
+        return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 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 {
+            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 {
+            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 {
+            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++) {
+            // make the regex if we don't have it already
+            mom = create_utc__createUTC([2000, 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);
+        }
+        // Sorting makes sure if one weekday (or abbr) is a prefix of another it
+        // will match the longer piece.
+        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');
+    }
+
+    // FORMATTING
+
+    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
+
+    // ALIASES
+
+    addUnitAlias('dayOfYear', 'DDD');
+
+    // PARSING
+
+    addRegexToken('DDD',  match1to3);
+    addRegexToken('DDDD', match3);
+    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
+        config._dayOfYear = toInt(input);
+    });
+
+    // HELPERS
+
+    // MOMENTS
+
+    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');
+    }
+
+    // FORMATTING
+
+    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);
+
+    // ALIASES
+
+    addUnitAlias('hour', 'h');
+
+    // PARSING
+
+    function matchMeridiem (isStrict, locale) {
+        return locale._meridiemParse;
+    }
+
+    addRegexToken('a',  matchMeridiem);
+    addRegexToken('A',  matchMeridiem);
+    addRegexToken('H',  match1to2);
+    addRegexToken('h',  match1to2);
+    addRegexToken('HH', match1to2, match2);
+    addRegexToken('hh', match1to2, match2);
+
+    addRegexToken('hmm', match3to4);
+    addRegexToken('hmmss', match5to6);
+    addRegexToken('Hmm', match3to4);
+    addRegexToken('Hmmss', match5to6);
+
+    addParseToken(['H', 'HH'], HOUR);
+    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));
+    });
+
+    // LOCALES
+
+    function localeIsPM (input) {
+        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
+        // Using charAt should be more compatible.
+        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';
+        }
+    }
+
+
+    // MOMENTS
+
+    // Setting the hour should keep the time, because the user explicitly
+    // specified which hour he wants. So trying to maintain the same hour (in
+    // a new timezone) makes sense. Adding/subtracting hours does not follow
+    // this rule.
+    var getSetHour = makeGetSet('Hours', true);
+
+    // FORMATTING
+
+    addFormatToken('m', ['mm', 2], 0, 'minute');
+
+    // ALIASES
+
+    addUnitAlias('minute', 'm');
+
+    // PARSING
+
+    addRegexToken('m',  match1to2);
+    addRegexToken('mm', match1to2, match2);
+    addParseToken(['m', 'mm'], MINUTE);
+
+    // MOMENTS
+
+    var getSetMinute = makeGetSet('Minutes', false);
+
+    // FORMATTING
+
+    addFormatToken('s', ['ss', 2], 0, 'second');
+
+    // ALIASES
+
+    addUnitAlias('second', 's');
+
+    // PARSING
+
+    addRegexToken('s',  match1to2);
+    addRegexToken('ss', match1to2, match2);
+    addParseToken(['s', 'ss'], SECOND);
+
+    // MOMENTS
+
+    var getSetSecond = makeGetSet('Seconds', false);
+
+    // FORMATTING
+
+    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() * 1000;
+    });
+    addFormatToken(0, ['SSSSSSS', 7], 0, function () {
+        return this.millisecond() * 10000;
+    });
+    addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
+        return this.millisecond() * 100000;
+    });
+    addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
+        return this.millisecond() * 1000000;
+    });
+
+
+    // ALIASES
+
+    addUnitAlias('millisecond', 'ms');
+
+    // PARSING
+
+    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) * 1000);
+    }
+
+    for (token = 'S'; token.length <= 9; token += 'S') {
+        addParseToken(token, parseMs);
+    }
+    // MOMENTS
+
+    var getSetMillisecond = makeGetSet('Milliseconds', false);
+
+    // FORMATTING
+
+    addFormatToken('z',  0, 0, 'zoneAbbr');
+    addFormatToken('zz', 0, 0, 'zoneName');
+
+    // MOMENTS
+
+    function getZoneAbbr () {
+        return this._isUTC ? 'UTC' : '';
+    }
+
+    function getZoneName () {
+        return this._isUTC ? 'Coordinated Universal Time' : '';
+    }
+
+    var momentPrototype__proto = Moment.prototype;
+
+    momentPrototype__proto.add               = add_subtract__add;
+    momentPrototype__proto.calendar          = moment_calendar__calendar;
+    momentPrototype__proto.clone             = clone;
+    momentPrototype__proto.diff              = diff;
+    momentPrototype__proto.endOf             = endOf;
+    momentPrototype__proto.format            = format;
+    momentPrototype__proto.from              = from;
+    momentPrototype__proto.fromNow           = fromNow;
+    momentPrototype__proto.to                = to;
+    momentPrototype__proto.toNow             = toNow;
+    momentPrototype__proto.get               = getSet;
+    momentPrototype__proto.invalidAt         = invalidAt;
+    momentPrototype__proto.isAfter           = isAfter;
+    momentPrototype__proto.isBefore          = isBefore;
+    momentPrototype__proto.isBetween         = isBetween;
+    momentPrototype__proto.isSame            = isSame;
+    momentPrototype__proto.isSameOrAfter     = isSameOrAfter;
+    momentPrototype__proto.isSameOrBefore    = isSameOrBefore;
+    momentPrototype__proto.isValid           = moment_valid__isValid;
+    momentPrototype__proto.lang              = lang;
+    momentPrototype__proto.locale            = locale;
+    momentPrototype__proto.localeData        = localeData;
+    momentPrototype__proto.max               = prototypeMax;
+    momentPrototype__proto.min               = prototypeMin;
+    momentPrototype__proto.parsingFlags      = parsingFlags;
+    momentPrototype__proto.set               = getSet;
+    momentPrototype__proto.startOf           = startOf;
+    momentPrototype__proto.subtract          = add_subtract__subtract;
+    momentPrototype__proto.toArray           = toArray;
+    momentPrototype__proto.toObject          = toObject;
+    momentPrototype__proto.toDate            = toDate;
+    momentPrototype__proto.toISOString       = moment_format__toISOString;
+    momentPrototype__proto.toJSON            = toJSON;
+    momentPrototype__proto.toString          = toString;
+    momentPrototype__proto.unix              = unix;
+    momentPrototype__proto.valueOf           = to_type__valueOf;
+    momentPrototype__proto.creationData      = creationData;
+
+    // Year
+    momentPrototype__proto.year       = getSetYear;
+    momentPrototype__proto.isLeapYear = getIsLeapYear;
+
+    // Week Year
+    momentPrototype__proto.weekYear    = getSetWeekYear;
+    momentPrototype__proto.isoWeekYear = getSetISOWeekYear;
+
+    // Quarter
+    momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;
+
+    // Month
+    momentPrototype__proto.month       = getSetMonth;
+    momentPrototype__proto.daysInMonth = getDaysInMonth;
+
+    // Week
+    momentPrototype__proto.week           = momentPrototype__proto.weeks        = getSetWeek;
+    momentPrototype__proto.isoWeek        = momentPrototype__proto.isoWeeks     = getSetISOWeek;
+    momentPrototype__proto.weeksInYear    = getWeeksInYear;
+    momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;
+
+    // Day
+    momentPrototype__proto.date       = getSetDayOfMonth;
+    momentPrototype__proto.day        = momentPrototype__proto.days             = getSetDayOfWeek;
+    momentPrototype__proto.weekday    = getSetLocaleDayOfWeek;
+    momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
+    momentPrototype__proto.dayOfYear  = getSetDayOfYear;
+
+    // Hour
+    momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;
+
+    // Minute
+    momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;
+
+    // Second
+    momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;
+
+    // Millisecond
+    momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;
+
+    // Offset
+    momentPrototype__proto.utcOffset            = getSetOffset;
+    momentPrototype__proto.utc                  = setOffsetToUTC;
+    momentPrototype__proto.local                = setOffsetToLocal;
+    momentPrototype__proto.parseZone            = setOffsetToParsedOffset;
+    momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
+    momentPrototype__proto.isDST                = isDaylightSavingTime;
+    momentPrototype__proto.isDSTShifted         = isDaylightSavingTimeShifted;
+    momentPrototype__proto.isLocal              = isLocal;
+    momentPrototype__proto.isUtcOffset          = isUtcOffset;
+    momentPrototype__proto.isUtc                = isUtc;
+    momentPrototype__proto.isUTC                = isUtc;
+
+    // Timezone
+    momentPrototype__proto.zoneAbbr = getZoneAbbr;
+    momentPrototype__proto.zoneName = getZoneName;
+
+    // Deprecations
+    momentPrototype__proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
+    momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
+    momentPrototype__proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
+    momentPrototype__proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);
+
+    var momentPrototype = momentPrototype__proto;
+
+    function moment__createUnix (input) {
+        return local__createLocal(input * 1000);
+    }
+
+    function moment__createInZone () {
+        return local__createLocal.apply(null, arguments).parseZone();
+    }
+
+    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 locale_calendar__calendar (key, mom, now) {
+        var output = this._calendar[key];
+        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 defaultOrdinalParse = /\d{1,2}/;
+
+    function ordinal (number) {
+        return this._ordinal.replace('%d', number);
+    }
+
+    function preParsePostFormat (string) {
+        return string;
+    }
+
+    var defaultRelativeTime = {
+        future : 'in %s',
+        past   : '%s ago',
+        s  : 'a few 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 relative__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 prototype__proto = Locale.prototype;
+
+    prototype__proto._calendar       = defaultCalendar;
+    prototype__proto.calendar        = locale_calendar__calendar;
+    prototype__proto._longDateFormat = defaultLongDateFormat;
+    prototype__proto.longDateFormat  = longDateFormat;
+    prototype__proto._invalidDate    = defaultInvalidDate;
+    prototype__proto.invalidDate     = invalidDate;
+    prototype__proto._ordinal        = defaultOrdinal;
+    prototype__proto.ordinal         = ordinal;
+    prototype__proto._ordinalParse   = defaultOrdinalParse;
+    prototype__proto.preparse        = preParsePostFormat;
+    prototype__proto.postformat      = preParsePostFormat;
+    prototype__proto._relativeTime   = defaultRelativeTime;
+    prototype__proto.relativeTime    = relative__relativeTime;
+    prototype__proto.pastFuture      = pastFuture;
+    prototype__proto.set             = locale_set__set;
+
+    // Month
+    prototype__proto.months            =        localeMonths;
+    prototype__proto._months           = defaultLocaleMonths;
+    prototype__proto.monthsShort       =        localeMonthsShort;
+    prototype__proto._monthsShort      = defaultLocaleMonthsShort;
+    prototype__proto.monthsParse       =        localeMonthsParse;
+    prototype__proto._monthsRegex      = defaultMonthsRegex;
+    prototype__proto.monthsRegex       = monthsRegex;
+    prototype__proto._monthsShortRegex = defaultMonthsShortRegex;
+    prototype__proto.monthsShortRegex  = monthsShortRegex;
+
+    // Week
+    prototype__proto.week = localeWeek;
+    prototype__proto._week = defaultLocaleWeek;
+    prototype__proto.firstDayOfYear = localeFirstDayOfYear;
+    prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;
+
+    // Day of Week
+    prototype__proto.weekdays       =        localeWeekdays;
+    prototype__proto._weekdays      = defaultLocaleWeekdays;
+    prototype__proto.weekdaysMin    =        localeWeekdaysMin;
+    prototype__proto._weekdaysMin   = defaultLocaleWeekdaysMin;
+    prototype__proto.weekdaysShort  =        localeWeekdaysShort;
+    prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;
+    prototype__proto.weekdaysParse  =        localeWeekdaysParse;
+
+    prototype__proto._weekdaysRegex      = defaultWeekdaysRegex;
+    prototype__proto.weekdaysRegex       =        weekdaysRegex;
+    prototype__proto._weekdaysShortRegex = defaultWeekdaysShortRegex;
+    prototype__proto.weekdaysShortRegex  =        weekdaysShortRegex;
+    prototype__proto._weekdaysMinRegex   = defaultWeekdaysMinRegex;
+    prototype__proto.weekdaysMinRegex    =        weekdaysMinRegex;
+
+    // Hours
+    prototype__proto.isPM = localeIsPM;
+    prototype__proto._meridiemParse = defaultLocaleMeridiemParse;
+    prototype__proto.meridiem = localeMeridiem;
+
+    function lists__get (format, index, field, setter) {
+        var locale = locale_locales__getLocale();
+        var utc = create_utc__createUTC().set(setter, index);
+        return locale[field](utc, format);
+    }
+
+    function listMonthsImpl (format, index, field) {
+        if (typeof format === 'number') {
+            index = format;
+            format = undefined;
+        }
+
+        format = format || '';
+
+        if (index != null) {
+            return lists__get(format, index, field, 'month');
+        }
+
+        var i;
+        var out = [];
+        for (i = 0; i < 12; i++) {
+            out[i] = lists__get(format, i, field, 'month');
+        }
+        return out;
+    }
+
+    // ()
+    // (5)
+    // (fmt, 5)
+    // (fmt)
+    // (true)
+    // (true, 5)
+    // (true, fmt, 5)
+    // (true, fmt)
+    function listWeekdaysImpl (localeSorted, format, index, field) {
+        if (typeof localeSorted === 'boolean') {
+            if (typeof format === 'number') {
+                index = format;
+                format = undefined;
+            }
+
+            format = format || '';
+        } else {
+            format = localeSorted;
+            index = format;
+            localeSorted = false;
+
+            if (typeof format === 'number') {
+                index = format;
+                format = undefined;
+            }
+
+            format = format || '';
+        }
+
+        var locale = locale_locales__getLocale(),
+            shift = localeSorted ? locale._week.dow : 0;
+
+        if (index != null) {
+            return lists__get(format, (index + shift) % 7, field, 'day');
+        }
+
+        var i;
+        var out = [];
+        for (i = 0; i < 7; i++) {
+            out[i] = lists__get(format, (i + shift) % 7, field, 'day');
+        }
+        return out;
+    }
+
+    function lists__listMonths (format, index) {
+        return listMonthsImpl(format, index, 'months');
+    }
+
+    function lists__listMonthsShort (format, index) {
+        return listMonthsImpl(format, index, 'monthsShort');
+    }
+
+    function lists__listWeekdays (localeSorted, format, index) {
+        return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
+    }
+
+    function lists__listWeekdaysShort (localeSorted, format, index) {
+        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
+    }
+
+    function lists__listWeekdaysMin (localeSorted, format, index) {
+        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
+    }
+
+    locale_locales__getSetGlobalLocale('en', {
+        ordinalParse: /\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;
+        }
+    });
+
+    // Side effect imports
+    utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);
+    utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);
+
+    var mathAbs = Math.abs;
+
+    function duration_abs__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 duration_add_subtract__addSubtract (duration, input, value, direction) {
+        var other = create__createDuration(input, value);
+
+        duration._milliseconds += direction * other._milliseconds;
+        duration._days         += direction * other._days;
+        duration._months       += direction * other._months;
+
+        return duration._bubble();
+    }
+
+    // supports only 2.0-style add(1, 's') or add(duration)
+    function duration_add_subtract__add (input, value) {
+        return duration_add_subtract__addSubtract(this, input, value, 1);
+    }
+
+    // supports only 2.0-style subtract(1, 's') or subtract(duration)
+    function duration_add_subtract__subtract (input, value) {
+        return duration_add_subtract__addSubtract(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 we have a mix of positive and negative values, bubble down first
+        // check: https://github.com/moment/moment/issues/2166
+        if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
+                (milliseconds <= 0 && days <= 0 && months <= 0))) {
+            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
+            days = 0;
+            months = 0;
+        }
+
+        // The following code bubbles up values, see the tests for
+        // examples of what that means.
+        data.milliseconds = milliseconds % 1000;
+
+        seconds           = absFloor(milliseconds / 1000);
+        data.seconds      = seconds % 60;
+
+        minutes           = absFloor(seconds / 60);
+        data.minutes      = minutes % 60;
+
+        hours             = absFloor(minutes / 60);
+        data.hours        = hours % 24;
+
+        days += absFloor(hours / 24);
+
+        // convert days to months
+        monthsFromDays = absFloor(daysToMonths(days));
+        months += monthsFromDays;
+        days -= absCeil(monthsToDays(monthsFromDays));
+
+        // 12 months -> 1 year
+        years = absFloor(months / 12);
+        months %= 12;
+
+        data.days   = days;
+        data.months = months;
+        data.years  = years;
+
+        return this;
+    }
+
+    function daysToMonths (days) {
+        // 400 years have 146097 days (taking into account leap year rules)
+        // 400 years have 12 months === 4800
+        return days * 4800 / 146097;
+    }
+
+    function monthsToDays (months) {
+        // the reverse of daysToMonths
+        return months * 146097 / 4800;
+    }
+
+    function as (units) {
+        var days;
+        var months;
+        var milliseconds = this._milliseconds;
+
+        units = normalizeUnits(units);
+
+        if (units === 'month' || units === 'year') {
+            days   = this._days   + milliseconds / 864e5;
+            months = this._months + daysToMonths(days);
+            return units === 'month' ? months : months / 12;
+        } else {
+            // handle milliseconds separately because of floating point math errors (issue #1867)
+            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 / 1000;
+                // Math.floor prevents floating point math errors here
+                case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
+                default: throw new Error('Unknown unit ' + units);
+            }
+        }
+    }
+
+    // TODO: Use this.as('ms')?
+    function duration_as__valueOf () {
+        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 asYears        = makeAs('y');
+
+    function duration_get__get (units) {
+        units = normalizeUnits(units);
+        return this[units + 's']();
+    }
+
+    function makeGetter(name) {
+        return function () {
+            return this._data[name];
+        };
+    }
+
+    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 = {
+        s: 45,  // seconds to minute
+        m: 45,  // minutes to hour
+        h: 22,  // hours to day
+        d: 26,  // days to month
+        M: 11   // months to year
+    };
+
+    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
+    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
+        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+    }
+
+    function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {
+        var duration = create__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.s && ['s', 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);
+    }
+
+    // This function allows you to set a threshold for relative time strings
+    function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {
+        if (thresholds[threshold] === undefined) {
+            return false;
+        }
+        if (limit === undefined) {
+            return thresholds[threshold];
+        }
+        thresholds[threshold] = limit;
+        return true;
+    }
+
+    function humanize (withSuffix) {
+        var locale = this.localeData();
+        var output = duration_humanize__relativeTime(this, !withSuffix, locale);
+
+        if (withSuffix) {
+            output = locale.pastFuture(+this, output);
+        }
+
+        return locale.postformat(output);
+    }
+
+    var iso_string__abs = Math.abs;
+
+    function iso_string__toISOString() {
+        // for ISO strings we do not use the normal bubbling rules:
+        //  * milliseconds bubble up until they become hours
+        //  * days do not bubble at all
+        //  * months bubble up until they become years
+        // This is because there is no context-free conversion between hours and days
+        // (think of clock changes)
+        // and also not between days and months (28-31 days per month)
+        var seconds = iso_string__abs(this._milliseconds) / 1000;
+        var days         = iso_string__abs(this._days);
+        var months       = iso_string__abs(this._months);
+        var minutes, hours, years;
+
+        // 3600 seconds -> 60 minutes -> 1 hour
+        minutes           = absFloor(seconds / 60);
+        hours             = absFloor(minutes / 60);
+        seconds %= 60;
+        minutes %= 60;
+
+        // 12 months -> 1 year
+        years  = absFloor(months / 12);
+        months %= 12;
+
+
+        // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
+        var Y = years;
+        var M = months;
+        var D = days;
+        var h = hours;
+        var m = minutes;
+        var s = seconds;
+        var total = this.asSeconds();
+
+        if (!total) {
+            // this is the same as C#'s (Noda) and python (isodate)...
+            // but not other JS (goog.date)
+            return 'P0D';
+        }
+
+        return (total < 0 ? '-' : '') +
+            'P' +
+            (Y ? Y + 'Y' : '') +
+            (M ? M + 'M' : '') +
+            (D ? D + 'D' : '') +
+            ((h || m || s) ? 'T' : '') +
+            (h ? h + 'H' : '') +
+            (m ? m + 'M' : '') +
+            (s ? s + 'S' : '');
+    }
+
+    var duration_prototype__proto = Duration.prototype;
+
+    duration_prototype__proto.abs            = duration_abs__abs;
+    duration_prototype__proto.add            = duration_add_subtract__add;
+    duration_prototype__proto.subtract       = duration_add_subtract__subtract;
+    duration_prototype__proto.as             = as;
+    duration_prototype__proto.asMilliseconds = asMilliseconds;
+    duration_prototype__proto.asSeconds      = asSeconds;
+    duration_prototype__proto.asMinutes      = asMinutes;
+    duration_prototype__proto.asHours        = asHours;
+    duration_prototype__proto.asDays         = asDays;
+    duration_prototype__proto.asWeeks        = asWeeks;
+    duration_prototype__proto.asMonths       = asMonths;
+    duration_prototype__proto.asYears        = asYears;
+    duration_prototype__proto.valueOf        = duration_as__valueOf;
+    duration_prototype__proto._bubble        = bubble;
+    duration_prototype__proto.get            = duration_get__get;
+    duration_prototype__proto.milliseconds   = milliseconds;
+    duration_prototype__proto.seconds        = seconds;
+    duration_prototype__proto.minutes        = minutes;
+    duration_prototype__proto.hours          = hours;
+    duration_prototype__proto.days           = days;
+    duration_prototype__proto.weeks          = weeks;
+    duration_prototype__proto.months         = months;
+    duration_prototype__proto.years          = years;
+    duration_prototype__proto.humanize       = humanize;
+    duration_prototype__proto.toISOString    = iso_string__toISOString;
+    duration_prototype__proto.toString       = iso_string__toISOString;
+    duration_prototype__proto.toJSON         = iso_string__toISOString;
+    duration_prototype__proto.locale         = locale;
+    duration_prototype__proto.localeData     = localeData;
+
+    // Deprecations
+    duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);
+    duration_prototype__proto.lang = lang;
+
+    // Side effect imports
+
+    // FORMATTING
+
+    addFormatToken('X', 0, 0, 'unix');
+    addFormatToken('x', 0, 0, 'valueOf');
+
+    // PARSING
+
+    addRegexToken('x', matchSigned);
+    addRegexToken('X', matchTimestamp);
+    addParseToken('X', function (input, array, config) {
+        config._d = new Date(parseFloat(input, 10) * 1000);
+    });
+    addParseToken('x', function (input, array, config) {
+        config._d = new Date(toInt(input));
+    });
+
+    // Side effect imports
+
+
+    utils_hooks__hooks.version = '2.13.0';
+
+    setHookCallback(local__createLocal);
+
+    utils_hooks__hooks.fn                    = momentPrototype;
+    utils_hooks__hooks.min                   = min;
+    utils_hooks__hooks.max                   = max;
+    utils_hooks__hooks.now                   = now;
+    utils_hooks__hooks.utc                   = create_utc__createUTC;
+    utils_hooks__hooks.unix                  = moment__createUnix;
+    utils_hooks__hooks.months                = lists__listMonths;
+    utils_hooks__hooks.isDate                = isDate;
+    utils_hooks__hooks.locale                = locale_locales__getSetGlobalLocale;
+    utils_hooks__hooks.invalid               = valid__createInvalid;
+    utils_hooks__hooks.duration              = create__createDuration;
+    utils_hooks__hooks.isMoment              = isMoment;
+    utils_hooks__hooks.weekdays              = lists__listWeekdays;
+    utils_hooks__hooks.parseZone             = moment__createInZone;
+    utils_hooks__hooks.localeData            = locale_locales__getLocale;
+    utils_hooks__hooks.isDuration            = isDuration;
+    utils_hooks__hooks.monthsShort           = lists__listMonthsShort;
+    utils_hooks__hooks.weekdaysMin           = lists__listWeekdaysMin;
+    utils_hooks__hooks.defineLocale          = defineLocale;
+    utils_hooks__hooks.updateLocale          = updateLocale;
+    utils_hooks__hooks.locales               = locale_locales__listLocales;
+    utils_hooks__hooks.weekdaysShort         = lists__listWeekdaysShort;
+    utils_hooks__hooks.normalizeUnits        = normalizeUnits;
+    utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
+    utils_hooks__hooks.prototype             = momentPrototype;
+
+    var _moment = utils_hooks__hooks;
+
+    return _moment;
+
+}));;/**
+ * Parse a text request to a json query object tree
+ *
+ * @param  {String} string The string to parse
+ * @return {Object} The json query tree
+ */
+function parseStringToObject(string) {
+
+var arrayExtend = function () {
+  var j, i, newlist = [], list_list = arguments;
+  for (j = 0; j < list_list.length; j += 1) {
+    for (i = 0; i < list_list[j].length; i += 1) {
+      newlist.push(list_list[j][i]);
+    }
+  }
+  return newlist;
+
+}, mkSimpleQuery = function (key, value, operator) {
+  var object = {"type": "simple", "key": key, "value": value};
+  if (operator !== undefined) {
+    object.operator = operator;
+  }
+  return object;
+
+}, mkNotQuery = function (query) {
+  if (query.operator === "NOT") {
+    return query.query_list[0];
+  }
+  return {"type": "complex", "operator": "NOT", "query_list": [query]};
+
+}, mkComplexQuery = function (operator, query_list) {
+  var i, query_list2 = [];
+  for (i = 0; i < query_list.length; i += 1) {
+    if (query_list[i].operator === operator) {
+      query_list2 = arrayExtend(query_list2, query_list[i].query_list);
+    } else {
+      query_list2.push(query_list[i]);
+    }
+  }
+  return {type:"complex",operator:operator,query_list:query_list2};
+
+}, simpleQuerySetKey = function (query, key) {
+  var i;
+  if (query.type === "complex") {
+    for (i = 0; i < query.query_list.length; ++i) {
+      simpleQuerySetKey (query.query_list[i],key);
+    }
+    return true;
+  }
+  if (query.type === "simple" && !query.key) {
+    query.key = key;
+    return true;
+  }
+  return false;
+},
+  error_offsets = [],
+  error_lookaheads = [],
+  error_count = 0,
+  result;
+;/* parser generated by jison 0.4.16 */
+/*
+  Returns a Parser object of the following structure:
+
+  Parser: {
+    yy: {}
+  }
+
+  Parser.prototype: {
+    yy: {},
+    trace: function(),
+    symbols_: {associative list: name ==> number},
+    terminals_: {associative list: number ==> name},
+    productions_: [...],
+    performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
+    table: [...],
+    defaultActions: {...},
+    parseError: function(str, hash),
+    parse: function(input),
+
+    lexer: {
+        EOF: 1,
+        parseError: function(str, hash),
+        setInput: function(input),
+        input: function(),
+        unput: function(str),
+        more: function(),
+        less: function(n),
+        pastInput: function(),
+        upcomingInput: function(),
+        showPosition: function(),
+        test_match: function(regex_match_array, rule_index),
+        next: function(),
+        lex: function(),
+        begin: function(condition),
+        popState: function(),
+        _currentRules: function(),
+        topState: function(),
+        pushState: function(condition),
+
+        options: {
+            ranges: boolean           (optional: true ==> token location info will include a .range[] member)
+            flex: boolean             (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
+            backtrack_lexer: boolean  (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
+        },
+
+        performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
+        rules: [...],
+        conditions: {associative list: name ==> set},
+    }
+  }
+
+
+  token location info (@$, _$, etc.): {
+    first_line: n,
+    last_line: n,
+    first_column: n,
+    last_column: n,
+    range: [start_number, end_number]       (where the numbers are indexes into the input string, regular zero-based)
+  }
+
+
+  the parseError function receives a 'hash' object with these members for lexer and parser errors: {
+    text:        (matched text)
+    token:       (the produced terminal token, if any)
+    line:        (yylineno)
+  }
+  while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
+    loc:         (yylloc)
+    expected:    (string describing the set of expected tokens)
+    recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
+  }
+*/
+var parser = (function(){
+var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,7],$V2=[1,8],$V3=[1,10],$V4=[1,12],$V5=[1,6,7,15],$V6=[1,6,7,9,12,14,15,16,19,21],$V7=[1,6,7,9,11,12,14,15,16,19,21],$V8=[2,17];
+var parser = {trace: function trace() { },
+yy: {},
+symbols_: {"error":2,"begin":3,"search_text":4,"end":5,"EOF":6,"NEWLINE":7,"and_expression":8,"OR":9,"boolean_expression":10,"AND":11,"NOT":12,"expression":13,"LEFT_PARENTHESE":14,"RIGHT_PARENTHESE":15,"WORD":16,"DEFINITION":17,"value":18,"OPERATOR":19,"string":20,"QUOTE":21,"QUOTED_STRING":22,"$accept":0,"$end":1},
+terminals_: {2:"error",6:"EOF",7:"NEWLINE",9:"OR",11:"AND",12:"NOT",14:"LEFT_PARENTHESE",15:"RIGHT_PARENTHESE",16:"WORD",17:"DEFINITION",19:"OPERATOR",21:"QUOTE",22:"QUOTED_STRING"},
+productions_: [0,[3,2],[5,0],[5,1],[5,1],[4,1],[4,2],[4,3],[8,1],[8,3],[10,2],[10,1],[13,3],[13,3],[13,1],[18,2],[18,1],[20,1],[20,3]],
+performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
+/* this == yyval */
+
+var $0 = $$.length - 1;
+switch (yystate) {
+case 1:
+ return $$[$0-1]; 
+break;
+case 5: case 8: case 11: case 14: case 16:
+ this.$ = $$[$0]; 
+break;
+case 6:
+ this.$ = mkComplexQuery('OR', [$$[$0-1], $$[$0]]); 
+break;
+case 7:
+ this.$ = mkComplexQuery('OR', [$$[$0-2], $$[$0]]); 
+break;
+case 9:
+ this.$ = mkComplexQuery('AND', [$$[$0-2], $$[$0]]); 
+break;
+case 10:
+ this.$ = mkNotQuery($$[$0]); 
+break;
+case 12:
+ this.$ = $$[$0-1]; 
+break;
+case 13:
+ simpleQuerySetKey($$[$0], $$[$0-2]); this.$ = $$[$0]; 
+break;
+case 15:
+ $$[$0].operator = $$[$0-1] ; this.$ = $$[$0]; 
+break;
+case 17:
+ this.$ = mkSimpleQuery('', $$[$0]); 
+break;
+case 18:
+ this.$ = mkSimpleQuery('', $$[$0-1]); 
+break;
+}
+},
+table: [{3:1,4:2,8:3,10:4,12:$V0,13:6,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},{1:[3]},{1:[2,2],5:13,6:[1,14],7:[1,15]},o($V5,[2,5],{8:3,10:4,13:6,18:9,20:11,4:16,9:[1,17],12:$V0,14:$V1,16:$V2,19:$V3,21:$V4}),o($V6,[2,8],{11:[1,18]}),{13:19,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},o($V7,[2,11]),{4:20,8:3,10:4,12:$V0,13:6,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},o($V7,$V8,{17:[1,21]}),o($V7,[2,14]),{16:[1,23],20:22,21:$V4},o($V7,[2,16]),{22:[1,24]},{1:[2,1]},{1:[2,3]},{1:[2,4]},o($V5,[2,6]),{4:25,8:3,10:4,12:$V0,13:6,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},{8:26,10:4,12:$V0,13:6,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},o($V7,[2,10]),{15:[1,27]},{13:28,14:$V1,16:$V2,18:9,19:$V3,20:11,21:$V4},o($V7,[2,15]),o($V7,$V8),{21:[1,29]},o($V5,[2,7]),o($V6,[2,9]),o($V7,[2,12]),o($V7,[2,13]),o($V7,[2,18])],
+defaultActions: {13:[2,1],14:[2,3],15:[2,4]},
+parseError: function parseError(str, hash) {
+    if (hash.recoverable) {
+        this.trace(str);
+    } else {
+        function _parseError (msg, hash) {
+            this.message = msg;
+            this.hash = hash;
+        }
+        _parseError.prototype = new Error();
+
+        throw new _parseError(str, hash);
+    }
+},
+parse: function parse(input) {
+    var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
+    var args = lstack.slice.call(arguments, 1);
+    var lexer = Object.create(this.lexer);
+    var sharedState = { yy: {} };
+    for (var k in this.yy) {
+        if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
+            sharedState.yy[k] = this.yy[k];
+        }
+    }
+    lexer.setInput(input, sharedState.yy);
+    sharedState.yy.lexer = lexer;
+    sharedState.yy.parser = this;
+    if (typeof lexer.yylloc == 'undefined') {
+        lexer.yylloc = {};
+    }
+    var yyloc = lexer.yylloc;
+    lstack.push(yyloc);
+    var ranges = lexer.options && lexer.options.ranges;
+    if (typeof sharedState.yy.parseError === 'function') {
+        this.parseError = sharedState.yy.parseError;
+    } else {
+        this.parseError = Object.getPrototypeOf(this).parseError;
+    }
+    function popStack(n) {
+        stack.length = stack.length - 2 * n;
+        vstack.length = vstack.length - n;
+        lstack.length = lstack.length - n;
+    }
+    _token_stack:
+        var lex = function () {
+            var token;
+            token = lexer.lex() || EOF;
+            if (typeof token !== 'number') {
+                token = self.symbols_[token] || token;
+            }
+            return token;
+        };
+    var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
+    while (true) {
+        state = stack[stack.length - 1];
+        if (this.defaultActions[state]) {
+            action = this.defaultActions[state];
+        } else {
+            if (symbol === null || typeof symbol == 'undefined') {
+                symbol = lex();
+            }
+            action = table[state] && table[state][symbol];
+        }
+                    if (typeof action === 'undefined' || !action.length || !action[0]) {
+                var errStr = '';
+                expected = [];
+                for (p in table[state]) {
+                    if (this.terminals_[p] && p > TERROR) {
+                        expected.push('\'' + this.terminals_[p] + '\'');
+                    }
+                }
+                if (lexer.showPosition) {
+                    errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
+                } else {
+                    errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
+                }
+                this.parseError(errStr, {
+                    text: lexer.match,
+                    token: this.terminals_[symbol] || symbol,
+                    line: lexer.yylineno,
+                    loc: yyloc,
+                    expected: expected
+                });
+            }
+        if (action[0] instanceof Array && action.length > 1) {
+            throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
+        }
+        switch (action[0]) {
+        case 1:
+            stack.push(symbol);
+            vstack.push(lexer.yytext);
+            lstack.push(lexer.yylloc);
+            stack.push(action[1]);
+            symbol = null;
+            if (!preErrorSymbol) {
+                yyleng = lexer.yyleng;
+                yytext = lexer.yytext;
+                yylineno = lexer.yylineno;
+                yyloc = lexer.yylloc;
+                if (recovering > 0) {
+                    recovering--;
+                }
+            } else {
+                symbol = preErrorSymbol;
+                preErrorSymbol = null;
+            }
+            break;
+        case 2:
+            len = this.productions_[action[1]][1];
+            yyval.$ = vstack[vstack.length - len];
+            yyval._$ = {
+                first_line: lstack[lstack.length - (len || 1)].first_line,
+                last_line: lstack[lstack.length - 1].last_line,
+                first_column: lstack[lstack.length - (len || 1)].first_column,
+                last_column: lstack[lstack.length - 1].last_column
+            };
+            if (ranges) {
+                yyval._$.range = [
+                    lstack[lstack.length - (len || 1)].range[0],
+                    lstack[lstack.length - 1].range[1]
+                ];
+            }
+            r = this.performAction.apply(yyval, [
+                yytext,
+                yyleng,
+                yylineno,
+                sharedState.yy,
+                action[1],
+                vstack,
+                lstack
+            ].concat(args));
+            if (typeof r !== 'undefined') {
+                return r;
+            }
+            if (len) {
+                stack = stack.slice(0, -1 * len * 2);
+                vstack = vstack.slice(0, -1 * len);
+                lstack = lstack.slice(0, -1 * len);
+            }
+            stack.push(this.productions_[action[1]][0]);
+            vstack.push(yyval.$);
+            lstack.push(yyval._$);
+            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
+            stack.push(newState);
+            break;
+        case 3:
+            return true;
+        }
+    }
+    return true;
+}};
+/* generated by jison-lex 0.3.4 */
+var lexer = (function(){
+var lexer = ({
+
+EOF:1,
+
+parseError:function parseError(str, hash) {
+        if (this.yy.parser) {
+            this.yy.parser.parseError(str, hash);
+        } else {
+            throw new Error(str);
+        }
+    },
+
+// resets the lexer, sets new input
+setInput:function (input, yy) {
+        this.yy = yy || this.yy || {};
+        this._input = input;
+        this._more = this._backtrack = this.done = false;
+        this.yylineno = this.yyleng = 0;
+        this.yytext = this.matched = this.match = '';
+        this.conditionStack = ['INITIAL'];
+        this.yylloc = {
+            first_line: 1,
+            first_column: 0,
+            last_line: 1,
+            last_column: 0
+        };
+        if (this.options.ranges) {
+            this.yylloc.range = [0,0];
+        }
+        this.offset = 0;
+        return this;
+    },
+
+// consumes and returns one char from the input
+input:function () {
+        var ch = this._input[0];
+        this.yytext += ch;
+        this.yyleng++;
+        this.offset++;
+        this.match += ch;
+        this.matched += ch;
+        var lines = ch.match(/(?:\r\n?|\n).*/g);
+        if (lines) {
+            this.yylineno++;
+            this.yylloc.last_line++;
+        } else {
+            this.yylloc.last_column++;
+        }
+        if (this.options.ranges) {
+            this.yylloc.range[1]++;
+        }
+
+        this._input = this._input.slice(1);
+        return ch;
+    },
+
+// unshifts one char (or a string) into the input
+unput:function (ch) {
+        var len = ch.length;
+        var lines = ch.split(/(?:\r\n?|\n)/g);
+
+        this._input = ch + this._input;
+        this.yytext = this.yytext.substr(0, this.yytext.length - len);
+        //this.yyleng -= len;
+        this.offset -= len;
+        var oldLines = this.match.split(/(?:\r\n?|\n)/g);
+        this.match = this.match.substr(0, this.match.length - 1);
+        this.matched = this.matched.substr(0, this.matched.length - 1);
+
+        if (lines.length - 1) {
+            this.yylineno -= lines.length - 1;
+        }
+        var r = this.yylloc.range;
+
+        this.yylloc = {
+            first_line: this.yylloc.first_line,
+            last_line: this.yylineno + 1,
+            first_column: this.yylloc.first_column,
+            last_column: lines ?
+                (lines.length === oldLines.length ? this.yylloc.first_column : 0)
+                 + oldLines[oldLines.length - lines.length].length - lines[0].length :
+              this.yylloc.first_column - len
+        };
+
+        if (this.options.ranges) {
+            this.yylloc.range = [r[0], r[0] + this.yyleng - len];
+        }
+        this.yyleng = this.yytext.length;
+        return this;
+    },
+
+// When called from action, caches matched text and appends it on next action
+more:function () {
+        this._more = true;
+        return this;
+    },
+
+// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
+reject:function () {
+        if (this.options.backtrack_lexer) {
+            this._backtrack = true;
+        } else {
+            return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
+                text: "",
+                token: null,
+                line: this.yylineno
+            });
+
+        }
+        return this;
+    },
+
+// retain first n characters of the match
+less:function (n) {
+        this.unput(this.match.slice(n));
+    },
+
+// displays already matched input, i.e. for error messages
+pastInput:function () {
+        var past = this.matched.substr(0, this.matched.length - this.match.length);
+        return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
+    },
+
+// displays upcoming input, i.e. for error messages
+upcomingInput:function () {
+        var next = this.match;
+        if (next.length < 20) {
+            next += this._input.substr(0, 20-next.length);
+        }
+        return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
+    },
+
+// displays the character position where the lexing error occurred, i.e. for error messages
+showPosition:function () {
+        var pre = this.pastInput();
+        var c = new Array(pre.length + 1).join("-");
+        return pre + this.upcomingInput() + "\n" + c + "^";
+    },
+
+// test the lexed token: return FALSE when not a match, otherwise return token
+test_match:function (match, indexed_rule) {
+        var token,
+            lines,
+            backup;
+
+        if (this.options.backtrack_lexer) {
+            // save context
+            backup = {
+                yylineno: this.yylineno,
+                yylloc: {
+                    first_line: this.yylloc.first_line,
+                    last_line: this.last_line,
+                    first_column: this.yylloc.first_column,
+                    last_column: this.yylloc.last_column
+                },
+                yytext: this.yytext,
+                match: this.match,
+                matches: this.matches,
+                matched: this.matched,
+                yyleng: this.yyleng,
+                offset: this.offset,
+                _more: this._more,
+                _input: this._input,
+                yy: this.yy,
+                conditionStack: this.conditionStack.slice(0),
+                done: this.done
+            };
+            if (this.options.ranges) {
+                backup.yylloc.range = this.yylloc.range.slice(0);
+            }
+        }
+
+        lines = match[0].match(/(?:\r\n?|\n).*/g);
+        if (lines) {
+            this.yylineno += lines.length;
+        }
+        this.yylloc = {
+            first_line: this.yylloc.last_line,
+            last_line: this.yylineno + 1,
+            first_column: this.yylloc.last_column,
+            last_column: lines ?
+                         lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
+                         this.yylloc.last_column + match[0].length
+        };
+        this.yytext += match[0];
+        this.match += match[0];
+        this.matches = match;
+        this.yyleng = this.yytext.length;
+        if (this.options.ranges) {
+            this.yylloc.range = [this.offset, this.offset += this.yyleng];
+        }
+        this._more = false;
+        this._backtrack = false;
+        this._input = this._input.slice(match[0].length);
+        this.matched += match[0];
+        token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
+        if (this.done && this._input) {
+            this.done = false;
+        }
+        if (token) {
+            return token;
+        } else if (this._backtrack) {
+            // recover context
+            for (var k in backup) {
+                this[k] = backup[k];
+            }
+            return false; // rule action called reject() implying the next rule should be tested instead.
+        }
+        return false;
+    },
+
+// return next match in input
+next:function () {
+        if (this.done) {
+            return this.EOF;
+        }
+        if (!this._input) {
+            this.done = true;
+        }
+
+        var token,
+            match,
+            tempMatch,
+            index;
+        if (!this._more) {
+            this.yytext = '';
+            this.match = '';
+        }
+        var rules = this._currentRules();
+        for (var i = 0; i < rules.length; i++) {
+            tempMatch = this._input.match(this.rules[rules[i]]);
+            if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
+                match = tempMatch;
+                index = i;
+                if (this.options.backtrack_lexer) {
+                    token = this.test_match(tempMatch, rules[i]);
+                    if (token !== false) {
+                        return token;
+                    } else if (this._backtrack) {
+                        match = false;
+                        continue; // rule action called reject() implying a rule MISmatch.
+                    } else {
+                        // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
+                        return false;
+                    }
+                } else if (!this.options.flex) {
+                    break;
+                }
+            }
+        }
+        if (match) {
+            token = this.test_match(match, rules[index]);
+            if (token !== false) {
+                return token;
+            }
+            // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
+            return false;
+        }
+        if (this._input === "") {
+            return this.EOF;
+        } else {
+            return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
+                text: "",
+                token: null,
+                line: this.yylineno
+            });
+        }
+    },
+
+// return next match that has a token
+lex:function lex() {
+        var r = this.next();
+        if (r) {
+            return r;
+        } else {
+            return this.lex();
+        }
+    },
+
+// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
+begin:function begin(condition) {
+        this.conditionStack.push(condition);
+    },
+
+// pop the previously active lexer condition state off the condition stack
+popState:function popState() {
+        var n = this.conditionStack.length - 1;
+        if (n > 0) {
+            return this.conditionStack.pop();
+        } else {
+            return this.conditionStack[0];
+        }
+    },
+
+// produce the lexer rule set which is active for the currently active lexer condition state
+_currentRules:function _currentRules() {
+        if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
+            return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
+        } else {
+            return this.conditions["INITIAL"].rules;
+        }
+    },
+
+// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
+topState:function topState(n) {
+        n = this.conditionStack.length - 1 - Math.abs(n || 0);
+        if (n >= 0) {
+            return this.conditionStack[n];
+        } else {
+            return "INITIAL";
+        }
+    },
+
+// alias for begin(condition)
+pushState:function pushState(condition) {
+        this.begin(condition);
+    },
+
+// return the number of states currently on the stack
+stateStackSize:function stateStackSize() {
+        return this.conditionStack.length;
+    },
+options: {},
+performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
+var YYSTATE=YY_START;
+switch($avoiding_name_collisions) {
+case 0:this.begin("letsquote"); return "QUOTE";
+break;
+case 1:this.popState(); this.begin("endquote"); return "QUOTED_STRING";
+break;
+case 2:this.popState(); return "QUOTE";
+break;
+case 3:/* skip whitespace */
+break;
+case 4:return "LEFT_PARENTHESE";
+break;
+case 5:return "RIGHT_PARENTHESE";
+break;
+case 6:return "AND";
+break;
+case 7:return "OR";
+break;
+case 8:return "NOT";
+break;
+case 9:return "DEFINITION";
+break;
+case 10:return 19;
+break;
+case 11:return 16;
+break;
+case 12:return 6;
+break;
+}
+},
+rules: [/^(?:")/,/^(?:(\\"|[^"])*)/,/^(?:")/,/^(?:[^\S]+)/,/^(?:\()/,/^(?:\))/,/^(?:AND\b)/,/^(?:OR\b)/,/^(?:NOT\b)/,/^(?::)/,/^(?:(!?=|<=?|>=?))/,/^(?:[^\s\n"():><!=]+)/,/^(?:$)/],
+conditions: {"endquote":{"rules":[2],"inclusive":false},"letsquote":{"rules":[1],"inclusive":false},"INITIAL":{"rules":[0,3,4,5,6,7,8,9,10,11,12],"inclusive":true}}
+});
+return lexer;
+})();
+parser.lexer = lexer;
+function Parser () {
+  this.yy = {};
+}
+Parser.prototype = parser;parser.Parser = Parser;
+return new Parser;
+})();;  return parser.parse(string);
+} // parseStringToObject
+
+;/*global RSVP, window, parseStringToObject*/
+/*jslint nomen: true, maxlen: 90*/
+(function (RSVP, window, parseStringToObject) {
+  "use strict";
+
+  var query_class_dict = {},
+    regexp_escape = /[\-\[\]{}()*+?.,\\\^$|#\s]/g,
+    regexp_percent = /%/g,
+    regexp_underscore = /_/g,
+    regexp_operator = /^(?:AND|OR|NOT)$/i,
+    regexp_comparaison = /^(?:!?=|<=?|>=?)$/i;
+
+  /**
+   * Convert metadata values to array of strings. ex:
+   *
+   *     "a" -> ["a"],
+   *     {"content": "a"} -> ["a"]
+   *
+   * @param  {Any} value The metadata value
+   * @return {Array} The value in string array format
+   */
+  function metadataValueToStringArray(value) {
+    var i, new_value = [];
+    if (value === undefined) {
+      return undefined;
+    }
+    if (!Array.isArray(value)) {
+      value = [value];
+    }
+    for (i = 0; i < value.length; i += 1) {
+      if (typeof value[i] === 'object') {
+        new_value[i] = value[i].content;
+      } else {
+        new_value[i] = value[i];
+      }
+    }
+    return new_value;
+  }
+
+  /**
+   * A sort function to sort items by key
+   *
+   * @param  {String} key The key to sort on
+   * @param  {String} [way="ascending"] 'ascending' or 'descending'
+   * @return {Function} The sort function
+   */
+  function sortFunction(key, way) {
+    var result;
+    if (way === 'descending') {
+      result = 1;
+    } else if (way === 'ascending') {
+      result = -1;
+    } else {
+      throw new TypeError("Query.sortFunction(): " +
+                          "Argument 2 must be 'ascending' or 'descending'");
+    }
+    return function (a, b) {
+      // this comparison is 5 times faster than json comparison
+      var i, l;
+      a = metadataValueToStringArray(a[key]) || [];
+      b = metadataValueToStringArray(b[key]) || [];
+      l = a.length > b.length ? a.length : b.length;
+      for (i = 0; i < l; i += 1) {
+        if (a[i] === undefined) {
+          return result;
+        }
+        if (b[i] === undefined) {
+          return -result;
+        }
+        if (a[i] > b[i]) {
+          return -result;
+        }
+        if (a[i] < b[i]) {
+          return result;
+        }
+      }
+      return 0;
+    };
+  }
+
+  /**
+   * Sort a list of items, according to keys and directions.
+   *
+   * @param  {Array} sort_on_option List of couples [key, direction]
+   * @param  {Array} list The item list to sort
+   * @return {Array} The filtered list
+   */
+  function sortOn(sort_on_option, list) {
+    var sort_index;
+    if (!Array.isArray(sort_on_option)) {
+      throw new TypeError("jioquery.sortOn(): " +
+                          "Argument 1 is not of type 'array'");
+    }
+    for (sort_index = sort_on_option.length - 1; sort_index >= 0;
+         sort_index -= 1) {
+      list.sort(sortFunction(
+        sort_on_option[sort_index][0],
+        sort_on_option[sort_index][1]
+      ));
+    }
+    return list;
+  }
+
+  /**
+   * Limit a list of items, according to index and length.
+   *
+   * @param  {Array} limit_option A couple [from, length]
+   * @param  {Array} list The item list to limit
+   * @return {Array} The filtered list
+   */
+  function limit(limit_option, list) {
+    if (!Array.isArray(limit_option)) {
+      throw new TypeError("jioquery.limit(): " +
+                          "Argument 1 is not of type 'array'");
+    }
+    if (!Array.isArray(list)) {
+      throw new TypeError("jioquery.limit(): " +
+                          "Argument 2 is not of type 'array'");
+    }
+    list.splice(0, limit_option[0]);
+    if (limit_option[1]) {
+      list.splice(limit_option[1]);
+    }
+    return list;
+  }
+
+  /**
+   * Filter a list of items, modifying them to select only wanted keys.
+   *
+   * @param  {Array} select_option Key list to keep
+   * @param  {Array} list The item list to filter
+   * @return {Array} The filtered list
+   */
+  function select(select_option, list) {
+    var i, j, new_item;
+    if (!Array.isArray(select_option)) {
+      throw new TypeError("jioquery.select(): " +
+                          "Argument 1 is not of type Array");
+    }
+    if (!Array.isArray(list)) {
+      throw new TypeError("jioquery.select(): " +
+                          "Argument 2 is not of type Array");
+    }
+    for (i = 0; i < list.length; i += 1) {
+      new_item = {};
+      for (j = 0; j < select_option.length; j += 1) {
+        if (list[i].hasOwnProperty([select_option[j]])) {
+          new_item[select_option[j]] = list[i][select_option[j]];
+        }
+      }
+      for (j in new_item) {
+        if (new_item.hasOwnProperty(j)) {
+          list[i] = new_item;
+          break;
+        }
+      }
+    }
+    return list;
+  }
+
+  /**
+   * The query to use to filter a list of objects.
+   * This is an abstract class.
+   *
+   * @class Query
+   * @constructor
+   */
+  function Query() {
+
+    /**
+     * Called before parsing the query. Must be overridden!
+     *
+     * @method onParseStart
+     * @param  {Object} object The object shared in the parse process
+     * @param  {Object} option Some option gave in parse()
+     */
+  //   this.onParseStart = emptyFunction;
+
+    /**
+     * Called when parsing a simple query. Must be overridden!
+     *
+     * @method onParseSimpleQuery
+     * @param  {Object} object The object shared in the parse process
+     * @param  {Object} option Some option gave in parse()
+     */
+  //   this.onParseSimpleQuery = emptyFunction;
+
+    /**
+     * Called when parsing a complex query. Must be overridden!
+     *
+     * @method onParseComplexQuery
+     * @param  {Object} object The object shared in the parse process
+     * @param  {Object} option Some option gave in parse()
+     */
+  //   this.onParseComplexQuery = emptyFunction;
+
+    /**
+     * Called after parsing the query. Must be overridden!
+     *
+     * @method onParseEnd
+     * @param  {Object} object The object shared in the parse process
+     * @param  {Object} option Some option gave in parse()
+     */
+  //   this.onParseEnd = emptyFunction;
+
+    return;
+  }
+
+  /**
+   * Filter the item list with matching item only
+   *
+   * @method exec
+   * @param  {Array} item_list The list of object
+   * @param  {Object} [option] Some operation option
+   * @param  {Array} [option.select_list] A object keys to retrieve
+   * @param  {Array} [option.sort_on] Couples of object keys and "ascending"
+   *                 or "descending"
+   * @param  {Array} [option.limit] Couple of integer, first is an index and
+   *                 second is the length.
+   */
+  Query.prototype.exec = function (item_list, option) {
+    if (!Array.isArray(item_list)) {
+      throw new TypeError("Query().exec(): Argument 1 is not of type 'array'");
+    }
+    if (option === undefined) {
+      option = {};
+    }
+    if (typeof option !== 'object') {
+      throw new TypeError("Query().exec(): " +
+                          "Optional argument 2 is not of type 'object'");
+    }
+    var context = this,
+      i;
+    for (i = item_list.length - 1; i >= 0; i -= 1) {
+      if (!context.match(item_list[i])) {
+        item_list.splice(i, 1);
+      }
+    }
+
+    if (option.sort_on) {
+      sortOn(option.sort_on, item_list);
+    }
+
+    if (option.limit) {
+      limit(option.limit, item_list);
+    }
+
+    select(option.select_list || [], item_list);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return item_list;
+      });
+  };
+
+  /**
+   * Test if an item matches this query
+   *
+   * @method match
+   * @param  {Object} item The object to test
+   * @return {Boolean} true if match, false otherwise
+   */
+  Query.prototype.match = function () {
+    return true;
+  };
+
+  /**
+   * Browse the Query in deep calling parser method in each step.
+   *
+   * `onParseStart` is called first, on end `onParseEnd` is called.
+   * It starts from the simple queries at the bottom of the tree calling the
+   * parser method `onParseSimpleQuery`, and go up calling the
+   * `onParseComplexQuery` method.
+   *
+   * @method parse
+   * @param  {Object} option Any options you want (except 'parsed')
+   * @return {Any} The parse result
+   */
+  Query.prototype.parse = function (option) {
+    var that = this,
+      object;
+    /**
+     * The recursive parser.
+     *
+     * @param  {Object} object The object shared in the parse process
+     * @param  {Object} options Some options usable in the parseMethods
+     * @return {Any} The parser result
+     */
+    function recParse(object, option) {
+      var query = object.parsed,
+        queue = new RSVP.Queue(),
+        i;
+
+      function enqueue(j) {
+        queue
+          .push(function () {
+            object.parsed = query.query_list[j];
+            return recParse(object, option);
+          })
+          .push(function () {
+            query.query_list[j] = object.parsed;
+          });
+      }
+
+      if (query.type === "complex") {
+
+
+        for (i = 0; i < query.query_list.length; i += 1) {
+          enqueue(i);
+        }
+
+        return queue
+          .push(function () {
+            object.parsed = query;
+            return that.onParseComplexQuery(object, option);
+          });
+
+      }
+      if (query.type === "simple") {
+        return that.onParseSimpleQuery(object, option);
+      }
+    }
+    object = {
+      parsed: JSON.parse(JSON.stringify(that.serialized()))
+    };
+    return new RSVP.Queue()
+      .push(function () {
+        return that.onParseStart(object, option);
+      })
+      .push(function () {
+        return recParse(object, option);
+      })
+      .push(function () {
+        return that.onParseEnd(object, option);
+      })
+      .push(function () {
+        return object.parsed;
+      });
+
+  };
+
+  /**
+   * Convert this query to a parsable string.
+   *
+   * @method toString
+   * @return {String} The string version of this query
+   */
+  Query.prototype.toString = function () {
+    return "";
+  };
+
+  /**
+   * Convert this query to an jsonable object in order to be remake thanks to
+   * QueryFactory class.
+   *
+   * @method serialized
+   * @return {Object} The jsonable object
+   */
+  Query.prototype.serialized = function () {
+    return undefined;
+  };
+
+  /**
+   * Provides static methods to create Query object
+   *
+   * @class QueryFactory
+   */
+  function QueryFactory() {
+    return;
+  }
+
+  /**
+   * Escapes regexp special chars from a string.
+   *
+   * @param  {String} string The string to escape
+   * @return {String} The escaped string
+   */
+  function stringEscapeRegexpCharacters(string) {
+    return string.replace(regexp_escape, "\\$&");
+  }
+
+  /**
+   * Inherits the prototype methods from one constructor into another. The
+   * prototype of `constructor` will be set to a new object created from
+   * `superConstructor`.
+   *
+   * @param  {Function} constructor The constructor which inherits the super one
+   * @param  {Function} superConstructor The super constructor
+   */
+  function inherits(constructor, superConstructor) {
+    constructor.super_ = superConstructor;
+    constructor.prototype = Object.create(superConstructor.prototype, {
+      "constructor": {
+        "configurable": true,
+        "enumerable": false,
+        "writable": true,
+        "value": constructor
+      }
+    });
+  }
+
+  /**
+   * Convert a search text to a regexp.
+   *
+   * @param  {String} string The string to convert
+   * @param  {Boolean} [use_wildcard_character=true] Use wildcard "%" and "_"
+   * @return {RegExp} The search text regexp
+   */
+  function searchTextToRegExp(string, use_wildcard_characters) {
+    if (typeof string !== 'string') {
+      throw new TypeError("jioquery.searchTextToRegExp(): " +
+                          "Argument 1 is not of type 'string'");
+    }
+    if (use_wildcard_characters === false) {
+      return new RegExp("^" + stringEscapeRegexpCharacters(string) + "$");
+    }
+    return new RegExp("^" + stringEscapeRegexpCharacters(string)
+      .replace(regexp_percent, '.*')
+      .replace(regexp_underscore, '.') + "$");
+  }
+
+  /**
+   * The ComplexQuery inherits from Query, and compares one or several metadata
+   * values.
+   *
+   * @class ComplexQuery
+   * @extends Query
+   * @param  {Object} [spec={}] The specifications
+   * @param  {String} [spec.operator="AND"] The compare method to use
+   * @param  {String} spec.key The metadata key
+   * @param  {String} spec.value The value of the metadata to compare
+   */
+  function ComplexQuery(spec, key_schema) {
+    Query.call(this);
+
+    /**
+     * Logical operator to use to compare object values
+     *
+     * @attribute operator
+     * @type String
+     * @default "AND"
+     * @optional
+     */
+    this.operator = spec.operator;
+
+    /**
+     * The sub Query list which are used to query an item.
+     *
+     * @attribute query_list
+     * @type Array
+     * @default []
+     * @optional
+     */
+    this.query_list = spec.query_list || [];
+    this.query_list = this.query_list.map(
+      // decorate the map to avoid sending the index as key_schema argument
+      function (o) { return QueryFactory.create(o, key_schema); }
+    );
+
+  }
+  inherits(ComplexQuery, Query);
+
+  ComplexQuery.prototype.operator = "AND";
+  ComplexQuery.prototype.type = "complex";
+
+  /**
+   * #crossLink "Query/match:method"
+   */
+  ComplexQuery.prototype.match = function (item) {
+    var operator = this.operator;
+    if (!(regexp_operator.test(operator))) {
+      operator = "AND";
+    }
+    return this[operator.toUpperCase()](item);
+  };
+
+  /**
+   * #crossLink "Query/toString:method"
+   */
+  ComplexQuery.prototype.toString = function () {
+    var str_list = [], this_operator = this.operator;
+    if (this.operator === "NOT") {
+      str_list.push("NOT (");
+      str_list.push(this.query_list[0].toString());
+      str_list.push(")");
+      return str_list.join(" ");
+    }
+    this.query_list.forEach(function (query) {
+      str_list.push("(");
+      str_list.push(query.toString());
+      str_list.push(")");
+      str_list.push(this_operator);
+    });
+    str_list.length -= 1;
+    return str_list.join(" ");
+  };
+
+  /**
+   * #crossLink "Query/serialized:method"
+   */
+  ComplexQuery.prototype.serialized = function () {
+    var s = {
+      "type": "complex",
+      "operator": this.operator,
+      "query_list": []
+    };
+    this.query_list.forEach(function (query) {
+      s.query_list.push(
+        typeof query.toJSON === "function" ? query.toJSON() : query
+      );
+    });
+    return s;
+  };
+  ComplexQuery.prototype.toJSON = ComplexQuery.prototype.serialized;
+
+  /**
+   * Comparison operator, test if all sub queries match the
+   * item value
+   *
+   * @method AND
+   * @param  {Object} item The item to match
+   * @return {Boolean} true if all match, false otherwise
+   */
+  ComplexQuery.prototype.AND = function (item) {
+    var result = true,
+      i = 0;
+
+    while (result && (i !== this.query_list.length)) {
+      result = this.query_list[i].match(item);
+      i += 1;
+    }
+    return result;
+
+  };
+
+  /**
+   * Comparison operator, test if one of the sub queries matches the
+   * item value
+   *
+   * @method OR
+   * @param  {Object} item The item to match
+   * @return {Boolean} true if one match, false otherwise
+   */
+  ComplexQuery.prototype.OR = function (item) {
+    var result = false,
+      i = 0;
+
+    while ((!result) && (i !== this.query_list.length)) {
+      result = this.query_list[i].match(item);
+      i += 1;
+    }
+
+    return result;
+  };
+
+  /**
+   * Comparison operator, test if the sub query does not match the
+   * item value
+   *
+   * @method NOT
+   * @param  {Object} item The item to match
+   * @return {Boolean} true if one match, false otherwise
+   */
+  ComplexQuery.prototype.NOT = function (item) {
+    return !this.query_list[0].match(item);
+  };
+
+  /**
+   * Creates Query object from a search text string or a serialized version
+   * of a Query.
+   *
+   * @method create
+   * @static
+   * @param  {Object,String} object The search text or the serialized version
+   *         of a Query
+   * @return {Query} A Query object
+   */
+  QueryFactory.create = function (object, key_schema) {
+    if (object === "") {
+      return new Query();
+    }
+    if (typeof object === "string") {
+      object = parseStringToObject(object);
+    }
+    if (typeof (object || {}).type === "string" &&
+        query_class_dict[object.type]) {
+      return new query_class_dict[object.type](object, key_schema);
+    }
+    throw new TypeError("QueryFactory.create(): " +
+                        "Argument 1 is not a search text or a parsable object");
+  };
+
+  function objectToSearchText(query) {
+    var str_list = [];
+    if (query.type === "complex") {
+      str_list.push("(");
+      (query.query_list || []).forEach(function (sub_query) {
+        str_list.push(objectToSearchText(sub_query));
+        str_list.push(query.operator);
+      });
+      str_list.length -= 1;
+      str_list.push(")");
+      return str_list.join(" ");
+    }
+    if (query.type === "simple") {
+      return (query.key ? query.key + ": " : "") +
+        (query.operator || "") + ' "' + query.value + '"';
+    }
+    throw new TypeError("This object is not a query");
+  }
+
+  function checkKeySchema(key_schema) {
+    var prop;
+
+    if (key_schema !== undefined) {
+      if (typeof key_schema !== 'object') {
+        throw new TypeError("SimpleQuery().create(): " +
+                            "key_schema is not of type 'object'");
+      }
+      // key_set is mandatory
+      if (key_schema.key_set === undefined) {
+        throw new TypeError("SimpleQuery().create(): " +
+                            "key_schema has no 'key_set' property");
+      }
+      for (prop in key_schema) {
+        if (key_schema.hasOwnProperty(prop)) {
+          switch (prop) {
+          case 'key_set':
+          case 'cast_lookup':
+          case 'match_lookup':
+            break;
+          default:
+            throw new TypeError("SimpleQuery().create(): " +
+                               "key_schema has unknown property '" + prop + "'");
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * The SimpleQuery inherits from Query, and compares one metadata value
+   *
+   * @class SimpleQuery
+   * @extends Query
+   * @param  {Object} [spec={}] The specifications
+   * @param  {String} [spec.operator="="] The compare method to use
+   * @param  {String} spec.key The metadata key
+   * @param  {String} spec.value The value of the metadata to compare
+   */
+  function SimpleQuery(spec, key_schema) {
+    Query.call(this);
+
+    checkKeySchema(key_schema);
+
+    this._key_schema = key_schema || {};
+
+    /**
+     * Operator to use to compare object values
+     *
+     * @attribute operator
+     * @type String
+     * @optional
+     */
+    this.operator = spec.operator;
+
+    /**
+     * Key of the object which refers to the value to compare
+     *
+     * @attribute key
+     * @type String
+     */
+    this.key = spec.key;
+
+    /**
+     * Value is used to do the comparison with the object value
+     *
+     * @attribute value
+     * @type String
+     */
+    this.value = spec.value;
+
+  }
+  inherits(SimpleQuery, Query);
+
+  SimpleQuery.prototype.type = "simple";
+
+  function checkKey(key) {
+    var prop;
+
+    if (key.read_from === undefined) {
+      throw new TypeError("Custom key is missing the read_from property");
+    }
+
+    for (prop in key) {
+      if (key.hasOwnProperty(prop)) {
+        switch (prop) {
+        case 'read_from':
+        case 'cast_to':
+        case 'equal_match':
+          break;
+        default:
+          throw new TypeError("Custom key has unknown property '" +
+                              prop + "'");
+        }
+      }
+    }
+  }
+
+  /**
+   * #crossLink "Query/match:method"
+   */
+  SimpleQuery.prototype.match = function (item) {
+    var object_value = null,
+      equal_match = null,
+      cast_to = null,
+      matchMethod = null,
+      operator = this.operator,
+      value = null,
+      key = this.key;
+
+    if (!(regexp_comparaison.test(operator))) {
+      // `operator` is not correct, we have to change it to "like" or "="
+      if (regexp_percent.test(this.value)) {
+        // `value` contains a non escaped `%`
+        operator = "like";
+      } else {
+        // `value` does not contain non escaped `%`
+        operator = "=";
+      }
+    }
+
+    matchMethod = this[operator];
+
+    if (this._key_schema.key_set && this._key_schema.key_set[key] !== undefined) {
+      key = this._key_schema.key_set[key];
+    }
+
+    if (typeof key === 'object') {
+      checkKey(key);
+      object_value = item[key.read_from];
+
+      equal_match = key.equal_match;
+
+      // equal_match can be a string
+      if (typeof equal_match === 'string') {
+        // XXX raise error if equal_match not in match_lookup
+        equal_match = this._key_schema.match_lookup[equal_match];
+      }
+
+      // equal_match overrides the default '=' operator
+      if (equal_match !== undefined) {
+        matchMethod = (operator === "=" || operator === "like" ?
+                       equal_match : matchMethod);
+      }
+
+      value = this.value;
+      cast_to = key.cast_to;
+      if (cast_to) {
+        // cast_to can be a string
+        if (typeof cast_to === 'string') {
+          // XXX raise error if cast_to not in cast_lookup
+          cast_to = this._key_schema.cast_lookup[cast_to];
+        }
+
+        try {
+          value = cast_to(value);
+        } catch (e) {
+          value = undefined;
+        }
+
+        try {
+          object_value = cast_to(object_value);
+        } catch (e) {
+          object_value = undefined;
+        }
+      }
+    } else {
+      object_value = item[key];
+      value = this.value;
+    }
+    if (object_value === undefined || value === undefined) {
+      return false;
+    }
+    return matchMethod(object_value, value);
+  };
+
+  /**
+   * #crossLink "Query/toString:method"
+   */
+  SimpleQuery.prototype.toString = function () {
+    return (this.key ? this.key + ":" : "") +
+      (this.operator ? " " + this.operator : "") + ' "' + this.value + '"';
+  };
+
+  /**
+   * #crossLink "Query/serialized:method"
+   */
+  SimpleQuery.prototype.serialized = function () {
+    var object = {
+      "type": "simple",
+      "key": this.key,
+      "value": this.value
+    };
+    if (this.operator !== undefined) {
+      object.operator = this.operator;
+    }
+    return object;
+  };
+  SimpleQuery.prototype.toJSON = SimpleQuery.prototype.serialized;
+
+  /**
+   * Comparison operator, test if this query value matches the item value
+   *
+   * @method =
+   * @param  {String} object_value The value to compare
+   * @param  {String} comparison_value The comparison value
+   * @return {Boolean} true if match, false otherwise
+   */
+  SimpleQuery.prototype["="] = function (object_value, comparison_value) {
+    var value, i;
+    if (!Array.isArray(object_value)) {
+      object_value = [object_value];
+    }
+    for (i = 0; i < object_value.length; i += 1) {
+      value = object_value[i];
+      if (typeof value === 'object' && value.hasOwnProperty('content')) {
+        value = value.content;
+      }
+      if (typeof value.cmp === "function") {
+        return (value.cmp(comparison_value) === 0);
+      }
+      if (comparison_value.toString() === value.toString()) {
+        return true;
+      }
+    }
+    return false;
+  };
+
+  /**
+   * Comparison operator, test if this query value matches the item value
+   *
+   * @method like
+   * @param  {String} object_value The value to compare
+   * @param  {String} comparison_value The comparison value
+   * @return {Boolean} true if match, false otherwise
+   */
+  SimpleQuery.prototype.like = function (object_value, comparison_value) {
+    var value, i;
+    if (!Array.isArray(object_value)) {
+      object_value = [object_value];
+    }
+    for (i = 0; i < object_value.length; i += 1) {
+      value = object_value[i];
+      if (typeof value === 'object' && value.hasOwnProperty('content')) {
+        value = value.content;
+      }
+      if (typeof value.cmp === "function") {
+        return (value.cmp(comparison_value) === 0);
+      }
+      if (
+        searchTextToRegExp(comparison_value.toString()).test(value.toString())
+      ) {
+        return true;
+      }
+    }
+    return false;
+  };
+
+  /**
+   * Comparison operator, test if this query value does not match the item value
+   *
+   * @method !=
+   * @param  {String} object_value The value to compare
+   * @param  {String} comparison_value The comparison value
+   * @return {Boolean} true if not match, false otherwise
+   */
+  SimpleQuery.prototype["!="] = function (object_value, comparison_value) {
+    var value, i;
+    if (!Array.isArray(object_value)) {
+      object_value = [object_value];
+    }
+    for (i = 0; i < object_value.length; i += 1) {
+      value = object_value[i];
+      if (typeof value === 'object' && value.hasOwnProperty('content')) {
+        value = value.content;
+      }
+      if (typeof value.cmp === "function") {
+        return (value.cmp(comparison_value) !== 0);
+      }
+      if (comparison_value.toString() === value.toString()) {
+        return false;
+      }
+    }
+    return true;
+  };
+
+  /**
+   * Comparison operator, test if this query value is lower than the item value
+   *
+   * @method <
+   * @param  {Number, String} object_value The value to compare
+   * @param  {Number, String} comparison_value The comparison value
+   * @return {Boolean} true if lower, false otherwise
+   */
+  SimpleQuery.prototype["<"] = function (object_value, comparison_value) {
+    var value;
+    if (!Array.isArray(object_value)) {
+      object_value = [object_value];
+    }
+    value = object_value[0];
+    if (typeof value === 'object' && value.hasOwnProperty('content')) {
+      value = value.content;
+    }
+    if (typeof value.cmp === "function") {
+      return (value.cmp(comparison_value) < 0);
+    }
+    return (value < comparison_value);
+  };
+
+  /**
+   * Comparison operator, test if this query value is equal or lower than the
+   * item value
+   *
+   * @method <=
+   * @param  {Number, String} object_value The value to compare
+   * @param  {Number, String} comparison_value The comparison value
+   * @return {Boolean} true if equal or lower, false otherwise
+   */
+  SimpleQuery.prototype["<="] = function (object_value, comparison_value) {
+    var value;
+    if (!Array.isArray(object_value)) {
+      object_value = [object_value];
+    }
+    value = object_value[0];
+    if (typeof value === 'object' && value.hasOwnProperty('content')) {
+      value = value.content;
+    }
+    if (typeof value.cmp === "function") {
+      return (value.cmp(comparison_value) <= 0);
+    }
+    return (value <= comparison_value);
+  };
+
+  /**
+   * Comparison operator, test if this query value is greater than the item
+   * value
+   *
+   * @method >
+   * @param  {Number, String} object_value The value to compare
+   * @param  {Number, String} comparison_value The comparison value
+   * @return {Boolean} true if greater, false otherwise
+   */
+  SimpleQuery.prototype[">"] = function (object_value, comparison_value) {
+    var value;
+    if (!Array.isArray(object_value)) {
+      object_value = [object_value];
+    }
+    value = object_value[0];
+    if (typeof value === 'object' && value.hasOwnProperty('content')) {
+      value = value.content;
+    }
+    if (typeof value.cmp === "function") {
+      return (value.cmp(comparison_value) > 0);
+    }
+    return (value > comparison_value);
+  };
+
+  /**
+   * Comparison operator, test if this query value is equal or greater than the
+   * item value
+   *
+   * @method >=
+   * @param  {Number, String} object_value The value to compare
+   * @param  {Number, String} comparison_value The comparison value
+   * @return {Boolean} true if equal or greater, false otherwise
+   */
+  SimpleQuery.prototype[">="] = function (object_value, comparison_value) {
+    var value;
+    if (!Array.isArray(object_value)) {
+      object_value = [object_value];
+    }
+    value = object_value[0];
+    if (typeof value === 'object' && value.hasOwnProperty('content')) {
+      value = value.content;
+    }
+    if (typeof value.cmp === "function") {
+      return (value.cmp(comparison_value) >= 0);
+    }
+    return (value >= comparison_value);
+  };
+
+  query_class_dict.simple = SimpleQuery;
+  query_class_dict.complex = ComplexQuery;
+
+  Query.parseStringToObject = parseStringToObject;
+  Query.objectToSearchText = objectToSearchText;
+
+  window.Query = Query;
+  window.SimpleQuery = SimpleQuery;
+  window.ComplexQuery = ComplexQuery;
+  window.QueryFactory = QueryFactory;
+
+}(RSVP, window, parseStringToObject));
+;/*global window, moment */
+/*jslint nomen: true, maxlen: 200*/
+(function (window, moment) {
+  "use strict";
+
+//   /**
+//    * Add a secured (write permission denied) property to an object.
+//    *
+//    * @param  {Object} object The object to fill
+//    * @param  {String} key The object key where to store the property
+//    * @param  {Any} value The value to store
+//    */
+//   function _export(key, value) {
+//     Object.defineProperty(to_export, key, {
+//       "configurable": false,
+//       "enumerable": true,
+//       "writable": false,
+//       "value": value
+//     });
+//   }
+
+  var YEAR = 'year',
+    MONTH = 'month',
+    DAY = 'day',
+    HOUR = 'hour',
+    MIN = 'minute',
+    SEC = 'second',
+    MSEC = 'millisecond',
+    precision_grade = {
+      'year': 0,
+      'month': 1,
+      'day': 2,
+      'hour': 3,
+      'minute': 4,
+      'second': 5,
+      'millisecond': 6
+    },
+    lesserPrecision = function (p1, p2) {
+      return (precision_grade[p1] < precision_grade[p2]) ? p1 : p2;
+    },
+    JIODate;
+
+
+  JIODate = function (str) {
+    // in case of forgotten 'new'
+    if (!(this instanceof JIODate)) {
+      return new JIODate(str);
+    }
+
+    if (str instanceof JIODate) {
+      this.mom = str.mom.clone();
+      this._precision = str._precision;
+      return;
+    }
+
+    if (str === undefined) {
+      this.mom = moment();
+      this.setPrecision(MSEC);
+      return;
+    }
+
+    this.mom = null;
+    this._str = str;
+
+    // http://www.w3.org/TR/NOTE-datetime
+    // http://dotat.at/tmp/ISO_8601-2004_E.pdf
+
+    // XXX these regexps fail to detect many invalid dates.
+
+    if (str.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+\-][0-2]\d:[0-5]\d|Z)/)
+          || str.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d/)) {
+      // ISO, milliseconds
+      this.mom = moment(str);
+      this.setPrecision(MSEC);
+    } else if (str.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+\-][0-2]\d:[0-5]\d|Z)/)
+          || str.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/)) {
+      // ISO, seconds
+      this.mom = moment(str);
+      this.setPrecision(SEC);
+    } else if (str.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+\-][0-2]\d:[0-5]\d|Z)/)
+          || str.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d/)) {
+      // ISO, minutes
+      this.mom = moment(str);
+      this.setPrecision(MIN);
+    } else if (str.match(/\d\d\d\d-\d\d-\d\d \d\d/)) {
+      this.mom = moment(str);
+      this.setPrecision(HOUR);
+    } else if (str.match(/\d\d\d\d-\d\d-\d\d/)) {
+      this.mom = moment(str);
+      this.setPrecision(DAY);
+    } else if (str.match(/\d\d\d\d-\d\d/)) {
+      this.mom = moment(str);
+      this.setPrecision(MONTH);
+    } else if (str.match(/\d\d\d\d/)) {
+      // Creating a moment with only the year will show this deprecation
+      // warning:
+      //
+      // Deprecation warning: moment construction falls back to js Date. This is
+      // discouraged and will be removed in upcoming major release. Please refer
+      // to https://github.com/moment/moment/issues/1407 for more info.
+      //
+      // TL;DR: parsing year-only strings with momentjs falls back to native
+      // Date and it won't correctly represent the year in local time if UTF
+      // offset is negative.
+      //
+      // The solution is to use the format parameter, so momentjs won't fall
+      // back to the native Date and we will have the correct year in local
+      // time.
+      //
+      this.mom = moment(str, 'YYYY');
+      this.setPrecision(YEAR);
+    }
+
+    if (!this.mom) {
+      throw new Error("Cannot parse: " + str);
+    }
+
+  };
+
+
+  JIODate.prototype.setPrecision = function (prec) {
+    this._precision = prec;
+  };
+
+
+  JIODate.prototype.getPrecision = function () {
+    return this._precision;
+  };
+
+
+  JIODate.prototype.cmp = function (other) {
+    var m1 = this.mom,
+      m2 = other.mom,
+      p = lesserPrecision(this._precision, other._precision);
+    return m1.isBefore(m2, p) ? -1 : (m1.isSame(m2, p) ? 0 : +1);
+  };
+
+
+  JIODate.prototype.toPrecisionString = function (precision) {
+    var fmt;
+
+    precision = precision || this._precision;
+
+    fmt = {
+      'millisecond': 'YYYY-MM-DD HH:mm:ss.SSS',
+      'second': 'YYYY-MM-DD HH:mm:ss',
+      'minute': 'YYYY-MM-DD HH:mm',
+      'hour': 'YYYY-MM-DD HH',
+      'day': 'YYYY-MM-DD',
+      'month': 'YYYY-MM',
+      'year': 'YYYY'
+    }[precision];
+
+    if (!fmt) {
+      throw new TypeError("Unsupported precision value '" + precision + "'");
+    }
+
+    return this.mom.format(fmt);
+  };
+
+
+  JIODate.prototype.toString = function () {
+    return this._str;
+  };
+
+
+//   _export('JIODate', JIODate);
+// 
+//   _export('YEAR', YEAR);
+//   _export('MONTH', MONTH);
+//   _export('DAY', DAY);
+//   _export('HOUR', HOUR);
+//   _export('MIN', MIN);
+//   _export('SEC', SEC);
+//   _export('MSEC', MSEC);
+
+  window.jiodate = {
+    JIODate: JIODate,
+    YEAR: YEAR,
+    MONTH: MONTH,
+    DAY: DAY,
+    HOUR: HOUR,
+    MIN: MIN,
+    SEC: SEC,
+    MSEC: MSEC
+  };
+}(window, moment));
+;/*global window, RSVP, Blob, XMLHttpRequest, QueryFactory, Query, atob,
+  FileReader, ArrayBuffer, Uint8Array */
+(function (window, RSVP, Blob, QueryFactory, Query, atob,
+           FileReader, ArrayBuffer, Uint8Array) {
+  "use strict";
+
+  var util = {},
+    jIO;
+
+  function jIOError(message, status_code) {
+    if ((message !== undefined) && (typeof message !== "string")) {
+      throw new TypeError('You must pass a string.');
+    }
+    this.message = message || "Default Message";
+    this.status_code = status_code || 500;
+  }
+  jIOError.prototype = new Error();
+  jIOError.prototype.constructor = jIOError;
+  util.jIOError = jIOError;
+
+  /**
+   * Send request with XHR and return a promise. xhr.onload: The promise is
+   * resolved when the status code is lower than 400 with the xhr object as
+   * first parameter. xhr.onerror: reject with xhr object as first
+   * parameter. xhr.onprogress: notifies the xhr object.
+   *
+   * @param  {Object} param The parameters
+   * @param  {String} [param.type="GET"] The request method
+   * @param  {String} [param.dataType=""] The data type to retrieve
+   * @param  {String} param.url The url
+   * @param  {Any} [param.data] The data to send
+   * @param  {Function} [param.beforeSend] A function called just before the
+   *    send request. The first parameter of this function is the XHR object.
+   * @return {Promise} The promise
+   */
+  function ajax(param) {
+    var xhr = new XMLHttpRequest();
+    return new RSVP.Promise(function (resolve, reject, notify) {
+      var k;
+      xhr.open(param.type || "GET", param.url, true);
+      xhr.responseType = param.dataType || "";
+      if (typeof param.headers === 'object' && param.headers !== null) {
+        for (k in param.headers) {
+          if (param.headers.hasOwnProperty(k)) {
+            xhr.setRequestHeader(k, param.headers[k]);
+          }
+        }
+      }
+      xhr.addEventListener("load", function (e) {
+        if (e.target.status >= 400) {
+          return reject(e);
+        }
+        resolve(e);
+      });
+      xhr.addEventListener("error", reject);
+      xhr.addEventListener("progress", notify);
+      if (typeof param.xhrFields === 'object' && param.xhrFields !== null) {
+        for (k in param.xhrFields) {
+          if (param.xhrFields.hasOwnProperty(k)) {
+            xhr[k] = param.xhrFields[k];
+          }
+        }
+      }
+      if (typeof param.beforeSend === 'function') {
+        param.beforeSend(xhr);
+      }
+      xhr.send(param.data);
+    }, function () {
+      xhr.abort();
+    });
+  }
+  util.ajax = ajax;
+
+  function readBlobAsText(blob, encoding) {
+    var fr = new FileReader();
+    return new RSVP.Promise(function (resolve, reject, notify) {
+      fr.addEventListener("load", resolve);
+      fr.addEventListener("error", reject);
+      fr.addEventListener("progress", notify);
+      fr.readAsText(blob, encoding);
+    }, function () {
+      fr.abort();
+    });
+  }
+  util.readBlobAsText = readBlobAsText;
+
+  function readBlobAsArrayBuffer(blob) {
+    var fr = new FileReader();
+    return new RSVP.Promise(function (resolve, reject, notify) {
+      fr.addEventListener("load", resolve);
+      fr.addEventListener("error", reject);
+      fr.addEventListener("progress", notify);
+      fr.readAsArrayBuffer(blob);
+    }, function () {
+      fr.abort();
+    });
+  }
+  util.readBlobAsArrayBuffer = readBlobAsArrayBuffer;
+
+  function readBlobAsDataURL(blob) {
+    var fr = new FileReader();
+    return new RSVP.Promise(function (resolve, reject, notify) {
+      fr.addEventListener("load", resolve);
+      fr.addEventListener("error", reject);
+      fr.addEventListener("progress", notify);
+      fr.readAsDataURL(blob);
+    }, function () {
+      fr.abort();
+    });
+  }
+  util.readBlobAsDataURL = readBlobAsDataURL;
+
+  // https://gist.github.com/davoclavo/4424731
+  function dataURItoBlob(dataURI) {
+    // convert base64 to raw binary data held in a string
+    var byteString = atob(dataURI.split(',')[1]),
+    // separate out the mime component
+      mimeString = dataURI.split(',')[0].split(':')[1],
+    // write the bytes of the string to an ArrayBuffer
+      arrayBuffer = new ArrayBuffer(byteString.length),
+      _ia = new Uint8Array(arrayBuffer),
+      i;
+    mimeString = mimeString.slice(0, mimeString.length - ";base64".length);
+    for (i = 0; i < byteString.length; i += 1) {
+      _ia[i] = byteString.charCodeAt(i);
+    }
+    return new Blob([arrayBuffer], {type: mimeString});
+  }
+
+  util.dataURItoBlob = dataURItoBlob;
+
+  // tools
+  function checkId(argument_list, storage, method_name) {
+    if (typeof argument_list[0] !== 'string' || argument_list[0] === '') {
+      throw new jIO.util.jIOError(
+        "Document id must be a non empty string on '" + storage.__type +
+          "." + method_name + "'.",
+        400
+      );
+    }
+  }
+
+  function checkAttachmentId(argument_list, storage, method_name) {
+    if (typeof argument_list[1] !== 'string' || argument_list[1] === '') {
+      throw new jIO.util.jIOError(
+        "Attachment id must be a non empty string on '" + storage.__type +
+          "." + method_name + "'.",
+        400
+      );
+    }
+  }
+
+  function declareMethod(klass, name, precondition_function, post_function) {
+    klass.prototype[name] = function () {
+      var argument_list = arguments,
+        context = this,
+        precondition_result;
+
+      return new RSVP.Queue()
+        .push(function () {
+          if (precondition_function !== undefined) {
+            return precondition_function.apply(
+              context.__storage,
+              [argument_list, context, name]
+            );
+          }
+        })
+        .push(function (result) {
+          var storage_method = context.__storage[name];
+          precondition_result = result;
+          if (storage_method === undefined) {
+            throw new jIO.util.jIOError(
+              "Capacity '" + name + "' is not implemented on '" +
+                context.__type + "'",
+              501
+            );
+          }
+          return storage_method.apply(
+            context.__storage,
+            argument_list
+          );
+        })
+        .push(function (result) {
+          if (post_function !== undefined) {
+            return post_function.call(
+              context,
+              argument_list,
+              result,
+              precondition_result
+            );
+          }
+          return result;
+        });
+    };
+    // Allow chain
+    return this;
+  }
+
+
+
+
+  /////////////////////////////////////////////////////////////////
+  // jIO Storage Proxy
+  /////////////////////////////////////////////////////////////////
+  function JioProxyStorage(type, storage) {
+    if (!(this instanceof JioProxyStorage)) {
+      return new JioProxyStorage();
+    }
+    this.__type = type;
+    this.__storage = storage;
+  }
+
+  declareMethod(JioProxyStorage, "put", checkId, function (argument_list) {
+    return argument_list[0];
+  });
+  declareMethod(JioProxyStorage, "get", checkId);
+  declareMethod(JioProxyStorage, "bulk");
+  declareMethod(JioProxyStorage, "remove", checkId, function (argument_list) {
+    return argument_list[0];
+  });
+
+  JioProxyStorage.prototype.post = function () {
+    var context = this,
+      argument_list = arguments;
+    return new RSVP.Queue()
+      .push(function () {
+        var storage_method = context.__storage.post;
+        if (storage_method === undefined) {
+          throw new jIO.util.jIOError(
+            "Capacity 'post' is not implemented on '" + context.__type + "'",
+            501
+          );
+        }
+        return context.__storage.post.apply(context.__storage, argument_list);
+      });
+  };
+
+  declareMethod(JioProxyStorage, 'putAttachment', function (argument_list,
+                                                            storage,
+                                                            method_name) {
+    checkId(argument_list, storage, method_name);
+    checkAttachmentId(argument_list, storage, method_name);
+
+    var options = argument_list[3] || {};
+
+    if (typeof argument_list[2] === 'string') {
+      argument_list[2] = new Blob([argument_list[2]], {
+        "type": options._content_type || options._mimetype ||
+                "text/plain;charset=utf-8"
+      });
+    } else if (!(argument_list[2] instanceof Blob)) {
+      throw new jIO.util.jIOError(
+        'Attachment content is not a blob',
+        400
+      );
+    }
+  });
+
+  declareMethod(JioProxyStorage, 'removeAttachment', function (argument_list,
+                                                               storage,
+                                                               method_name) {
+    checkId(argument_list, storage, method_name);
+    checkAttachmentId(argument_list, storage, method_name);
+  });
+
+  declareMethod(JioProxyStorage, 'getAttachment', function (argument_list,
+                                                            storage,
+                                                            method_name) {
+    var result = "blob";
+//     if (param.storage_spec.type !== "indexeddb" &&
+//         param.storage_spec.type !== "dav" &&
+//         (param.kwargs._start !== undefined
+//          || param.kwargs._end !== undefined)) {
+//       restCommandRejecter(param, [
+//         'bad_request',
+//         'unsupport',
+//         '_start, _end not support'
+//       ]);
+//       return false;
+//     }
+    checkId(argument_list, storage, method_name);
+    checkAttachmentId(argument_list, storage, method_name);
+    // Drop optional parameters, which are only used in postfunction
+    if (argument_list[2] !== undefined) {
+      result = argument_list[2].format || result;
+      delete argument_list[2].format;
+    }
+    return result;
+  }, function (argument_list, blob, convert) {
+    var result;
+    if (!(blob instanceof Blob)) {
+      throw new jIO.util.jIOError(
+        "'getAttachment' (" + argument_list[0] + " , " +
+          argument_list[1] + ") on '" + this.__type +
+          "' does not return a Blob.",
+        501
+      );
+    }
+    if (convert === "blob") {
+      result = blob;
+    } else if (convert === "data_url") {
+      result = new RSVP.Queue()
+        .push(function () {
+          return jIO.util.readBlobAsDataURL(blob);
+        })
+        .push(function (evt) {
+          return evt.target.result;
+        });
+    } else if (convert === "array_buffer") {
+      result = new RSVP.Queue()
+        .push(function () {
+          return jIO.util.readBlobAsArrayBuffer(blob);
+        })
+        .push(function (evt) {
+          return evt.target.result;
+        });
+    } else if (convert === "text") {
+      result = new RSVP.Queue()
+        .push(function () {
+          return jIO.util.readBlobAsText(blob);
+        })
+        .push(function (evt) {
+          return evt.target.result;
+        });
+    } else if (convert === "json") {
+      result = new RSVP.Queue()
+        .push(function () {
+          return jIO.util.readBlobAsText(blob);
+        })
+        .push(function (evt) {
+          return JSON.parse(evt.target.result);
+        });
+    } else {
+      throw new jIO.util.jIOError(
+        this.__type + ".getAttachment format: '" + convert +
+          "' is not supported",
+        400
+      );
+    }
+    return result;
+  });
+
+  JioProxyStorage.prototype.buildQuery = function () {
+    var storage_method = this.__storage.buildQuery,
+      context = this,
+      argument_list = arguments;
+    if (storage_method === undefined) {
+      throw new jIO.util.jIOError(
+        "Capacity 'buildQuery' is not implemented on '" + this.__type + "'",
+        501
+      );
+    }
+    return new RSVP.Queue()
+      .push(function () {
+        return storage_method.apply(
+          context.__storage,
+          argument_list
+        );
+      });
+  };
+
+  JioProxyStorage.prototype.hasCapacity = function (name) {
+    var storage_method = this.__storage.hasCapacity,
+      capacity_method = this.__storage[name];
+    if (capacity_method !== undefined) {
+      return true;
+    }
+    if ((storage_method === undefined) ||
+        !storage_method.apply(this.__storage, arguments)) {
+      throw new jIO.util.jIOError(
+        "Capacity '" + name + "' is not implemented on '" + this.__type + "'",
+        501
+      );
+    }
+    return true;
+  };
+
+  JioProxyStorage.prototype.allDocs = function (options) {
+    var context = this;
+    if (options === undefined) {
+      options = {};
+    }
+    return new RSVP.Queue()
+      .push(function () {
+        if (context.hasCapacity("list") &&
+            ((options.query === undefined) || context.hasCapacity("query")) &&
+            ((options.sort_on === undefined) || context.hasCapacity("sort")) &&
+            ((options.select_list === undefined) ||
+             context.hasCapacity("select")) &&
+            ((options.include_docs === undefined) ||
+             context.hasCapacity("include")) &&
+            ((options.limit === undefined) || context.hasCapacity("limit"))) {
+          return context.buildQuery(options);
+        }
+      })
+      .push(function (result) {
+        return {
+          data: {
+            rows: result,
+            total_rows: result.length
+          }
+        };
+      });
+  };
+
+  declareMethod(JioProxyStorage, "allAttachments", checkId);
+  declareMethod(JioProxyStorage, "repair");
+
+  JioProxyStorage.prototype.repair = function () {
+    var context = this,
+      argument_list = arguments;
+    return new RSVP.Queue()
+      .push(function () {
+        var storage_method = context.__storage.repair;
+        if (storage_method !== undefined) {
+          return context.__storage.repair.apply(context.__storage,
+                                                argument_list);
+        }
+      });
+  };
+
+  /////////////////////////////////////////////////////////////////
+  // Storage builder
+  /////////////////////////////////////////////////////////////////
+  function JioBuilder() {
+    if (!(this instanceof JioBuilder)) {
+      return new JioBuilder();
+    }
+    this.__storage_types = {};
+  }
+
+  JioBuilder.prototype.createJIO = function (storage_spec, util) {
+
+    if (typeof storage_spec.type !== 'string') {
+      throw new TypeError("Invalid storage description");
+    }
+    if (!this.__storage_types[storage_spec.type]) {
+      throw new TypeError("Unknown storage '" + storage_spec.type + "'");
+    }
+
+    return new JioProxyStorage(
+      storage_spec.type,
+      new this.__storage_types[storage_spec.type](storage_spec, util)
+    );
+
+  };
+
+  JioBuilder.prototype.addStorage = function (type, Constructor) {
+    if (typeof type !== 'string') {
+      throw new TypeError(
+        "jIO.addStorage(): Argument 1 is not of type 'string'"
+      );
+    }
+    if (typeof Constructor !== 'function') {
+      throw new TypeError("jIO.addStorage(): " +
+                          "Argument 2 is not of type 'function'");
+    }
+    if (this.__storage_types[type] !== undefined) {
+      throw new TypeError("jIO.addStorage(): Storage type already exists");
+    }
+    this.__storage_types[type] = Constructor;
+  };
+
+  JioBuilder.prototype.util = util;
+  JioBuilder.prototype.QueryFactory = QueryFactory;
+  JioBuilder.prototype.Query = Query;
+
+  /////////////////////////////////////////////////////////////////
+  // global
+  /////////////////////////////////////////////////////////////////
+  jIO = new JioBuilder();
+  window.jIO = jIO;
+
+}(window, RSVP, Blob, QueryFactory, Query, atob,
+  FileReader, ArrayBuffer, Uint8Array));
+;/*
+ * Rusha, a JavaScript implementation of the Secure Hash Algorithm, SHA-1,
+ * as defined in FIPS PUB 180-1, tuned for high performance with large inputs.
+ * (http://github.com/srijs/rusha)
+ *
+ * Inspired by Paul Johnstons implementation (http://pajhome.org.uk/crypt/md5).
+ *
+ * Copyright (c) 2013 Sam Rijs (http://awesam.de).
+ * Released under the terms of the MIT license as follows:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+(function () {
+    // If we'e running in Node.JS, export a module.
+    if (typeof module !== 'undefined') {
+        module.exports = Rusha;
+    } else if (typeof window !== 'undefined') {
+        window.Rusha = Rusha;
+    }
+    // If we're running in a webworker, accept
+    // messages containing a jobid and a buffer
+    // or blob object, and return the hash result.
+    if (typeof FileReaderSync !== 'undefined') {
+        var reader = new FileReaderSync(), hasher = new Rusha(4 * 1024 * 1024);
+        self.onmessage = function onMessage(event) {
+            var hash, data = event.data.data;
+            try {
+                hash = hasher.digest(data);
+                self.postMessage({
+                    id: event.data.id,
+                    hash: hash
+                });
+            } catch (e) {
+                self.postMessage({
+                    id: event.data.id,
+                    error: e.name
+                });
+            }
+        };
+    }
+    var util = {
+            getDataType: function (data) {
+                if (typeof data === 'string') {
+                    return 'string';
+                }
+                if (data instanceof Array) {
+                    return 'array';
+                }
+                if (typeof global !== 'undefined' && global.Buffer && global.Buffer.isBuffer(data)) {
+                    return 'buffer';
+                }
+                if (data instanceof ArrayBuffer) {
+                    return 'arraybuffer';
+                }
+                if (data.buffer instanceof ArrayBuffer) {
+                    return 'view';
+                }
+                if (data instanceof Blob) {
+                    return 'blob';
+                }
+                throw new Error('Unsupported data type.');
+            }
+        };
+    // The Rusha object is a wrapper around the low-level RushaCore.
+    // It provides means of converting different inputs to the
+    // format accepted by RushaCore as well as other utility methods.
+    function Rusha(chunkSize) {
+        'use strict';
+        // Private object structure.
+        var self$2 = { fill: 0 };
+        // Calculate the length of buffer that the sha1 routine uses
+        // including the padding.
+        var padlen = function (len) {
+            for (len += 9; len % 64 > 0; len += 1);
+            return len;
+        };
+        var padZeroes = function (bin, len) {
+            for (var i = len >> 2; i < bin.length; i++)
+                bin[i] = 0;
+        };
+        var padData = function (bin, chunkLen, msgLen) {
+            bin[chunkLen >> 2] |= 128 << 24 - (chunkLen % 4 << 3);
+            bin[((chunkLen >> 2) + 2 & ~15) + 14] = msgLen >> 29;
+            bin[((chunkLen >> 2) + 2 & ~15) + 15] = msgLen << 3;
+        };
+        // Convert a binary string and write it to the heap.
+        // A binary string is expected to only contain char codes < 256.
+        var convStr = function (H8, H32, start, len, off) {
+            var str = this, i, om = off % 4, lm = len % 4, j = len - lm;
+            if (j > 0) {
+                switch (om) {
+                case 0:
+                    H8[off + 3 | 0] = str.charCodeAt(start);
+                case 1:
+                    H8[off + 2 | 0] = str.charCodeAt(start + 1);
+                case 2:
+                    H8[off + 1 | 0] = str.charCodeAt(start + 2);
+                case 3:
+                    H8[off | 0] = str.charCodeAt(start + 3);
+                }
+            }
+            for (i = om; i < j; i = i + 4 | 0) {
+                H32[off + i >> 2] = str.charCodeAt(start + i) << 24 | str.charCodeAt(start + i + 1) << 16 | str.charCodeAt(start + i + 2) << 8 | str.charCodeAt(start + i + 3);
+            }
+            switch (lm) {
+            case 3:
+                H8[off + j + 1 | 0] = str.charCodeAt(start + j + 2);
+            case 2:
+                H8[off + j + 2 | 0] = str.charCodeAt(start + j + 1);
+            case 1:
+                H8[off + j + 3 | 0] = str.charCodeAt(start + j);
+            }
+        };
+        // Convert a buffer or array and write it to the heap.
+        // The buffer or array is expected to only contain elements < 256.
+        var convBuf = function (H8, H32, start, len, off) {
+            var buf = this, i, om = off % 4, lm = len % 4, j = len - lm;
+            if (j > 0) {
+                switch (om) {
+                case 0:
+                    H8[off + 3 | 0] = buf[start];
+                case 1:
+                    H8[off + 2 | 0] = buf[start + 1];
+                case 2:
+                    H8[off + 1 | 0] = buf[start + 2];
+                case 3:
+                    H8[off | 0] = buf[start + 3];
+                }
+            }
+            for (i = 4 - om; i < j; i = i += 4 | 0) {
+                H32[off + i >> 2] = buf[start + i] << 24 | buf[start + i + 1] << 16 | buf[start + i + 2] << 8 | buf[start + i + 3];
+            }
+            switch (lm) {
+            case 3:
+                H8[off + j + 1 | 0] = buf[start + j + 2];
+            case 2:
+                H8[off + j + 2 | 0] = buf[start + j + 1];
+            case 1:
+                H8[off + j + 3 | 0] = buf[start + j];
+            }
+        };
+        var convBlob = function (H8, H32, start, len, off) {
+            var blob = this, i, om = off % 4, lm = len % 4, j = len - lm;
+            var buf = new Uint8Array(reader.readAsArrayBuffer(blob.slice(start, start + len)));
+            if (j > 0) {
+                switch (om) {
+                case 0:
+                    H8[off + 3 | 0] = buf[0];
+                case 1:
+                    H8[off + 2 | 0] = buf[1];
+                case 2:
+                    H8[off + 1 | 0] = buf[2];
+                case 3:
+                    H8[off | 0] = buf[3];
+                }
+            }
+            for (i = 4 - om; i < j; i = i += 4 | 0) {
+                H32[off + i >> 2] = buf[i] << 24 | buf[i + 1] << 16 | buf[i + 2] << 8 | buf[i + 3];
+            }
+            switch (lm) {
+            case 3:
+                H8[off + j + 1 | 0] = buf[j + 2];
+            case 2:
+                H8[off + j + 2 | 0] = buf[j + 1];
+            case 1:
+                H8[off + j + 3 | 0] = buf[j];
+            }
+        };
+        var convFn = function (data) {
+            switch (util.getDataType(data)) {
+            case 'string':
+                return convStr.bind(data);
+            case 'array':
+                return convBuf.bind(data);
+            case 'buffer':
+                return convBuf.bind(data);
+            case 'arraybuffer':
+                return convBuf.bind(new Uint8Array(data));
+            case 'view':
+                return convBuf.bind(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
+            case 'blob':
+                return convBlob.bind(data);
+            }
+        };
+        var slice = function (data, offset) {
+            switch (util.getDataType(data)) {
+            case 'string':
+                return data.slice(offset);
+            case 'array':
+                return data.slice(offset);
+            case 'buffer':
+                return data.slice(offset);
+            case 'arraybuffer':
+                return data.slice(offset);
+            case 'view':
+                return data.buffer.slice(offset);
+            }
+        };
+        // Convert an ArrayBuffer into its hexadecimal string representation.
+        var hex = function (arrayBuffer) {
+            var i, x, hex_tab = '0123456789abcdef', res = [], binarray = new Uint8Array(arrayBuffer);
+            for (i = 0; i < binarray.length; i++) {
+                x = binarray[i];
+                res[i] = hex_tab.charAt(x >> 4 & 15) + hex_tab.charAt(x >> 0 & 15);
+            }
+            return res.join('');
+        };
+        var ceilHeapSize = function (v) {
+            // The asm.js spec says:
+            // The heap object's byteLength must be either
+            // 2^n for n in [12, 24) or 2^24 * n for n ≥ 1.
+            // Also, byteLengths smaller than 2^16 are deprecated.
+            var p;
+            // If v is smaller than 2^16, the smallest possible solution
+            // is 2^16.
+            if (v <= 65536)
+                return 65536;
+            // If v < 2^24, we round up to 2^n,
+            // otherwise we round up to 2^24 * n.
+            if (v < 16777216) {
+                for (p = 1; p < v; p = p << 1);
+            } else {
+                for (p = 16777216; p < v; p += 16777216);
+            }
+            return p;
+        };
+        // Initialize the internal data structures to a new capacity.
+        var init = function (size) {
+            if (size % 64 > 0) {
+                throw new Error('Chunk size must be a multiple of 128 bit');
+            }
+            self$2.maxChunkLen = size;
+            self$2.padMaxChunkLen = padlen(size);
+            // The size of the heap is the sum of:
+            // 1. The padded input message size
+            // 2. The extended space the algorithm needs (320 byte)
+            // 3. The 160 bit state the algoritm uses
+            self$2.heap = new ArrayBuffer(ceilHeapSize(self$2.padMaxChunkLen + 320 + 20));
+            self$2.h32 = new Int32Array(self$2.heap);
+            self$2.h8 = new Int8Array(self$2.heap);
+            self$2.core = RushaCore({
+                Int32Array: Int32Array,
+                DataView: DataView
+            }, {}, self$2.heap);
+            self$2.buffer = null;
+        };
+        // Iinitializethe datastructures according
+        // to a chunk siyze.
+        init(chunkSize || 64 * 1024);
+        var initState = function (heap, padMsgLen) {
+            var io = new Int32Array(heap, padMsgLen + 320, 5);
+            io[0] = 1732584193;
+            io[1] = -271733879;
+            io[2] = -1732584194;
+            io[3] = 271733878;
+            io[4] = -1009589776;
+        };
+        var padChunk = function (chunkLen, msgLen) {
+            var padChunkLen = padlen(chunkLen);
+            var view = new Int32Array(self$2.heap, 0, padChunkLen >> 2);
+            padZeroes(view, chunkLen);
+            padData(view, chunkLen, msgLen);
+            return padChunkLen;
+        };
+        // Write data to the heap.
+        var write = function (data, chunkOffset, chunkLen) {
+            convFn(data)(self$2.h8, self$2.h32, chunkOffset, chunkLen, 0);
+        };
+        // Initialize and call the RushaCore,
+        // assuming an input buffer of length len * 4.
+        var coreCall = function (data, chunkOffset, chunkLen, msgLen, finalize) {
+            var padChunkLen = chunkLen;
+            if (finalize) {
+                padChunkLen = padChunk(chunkLen, msgLen);
+            }
+            write(data, chunkOffset, chunkLen);
+            self$2.core.hash(padChunkLen, self$2.padMaxChunkLen);
+        };
+        var getRawDigest = function (heap, padMaxChunkLen) {
+            var io = new Int32Array(heap, padMaxChunkLen + 320, 5);
+            var out = new Int32Array(5);
+            var arr = new DataView(out.buffer);
+            arr.setInt32(0, io[0], false);
+            arr.setInt32(4, io[1], false);
+            arr.setInt32(8, io[2], false);
+            arr.setInt32(12, io[3], false);
+            arr.setInt32(16, io[4], false);
+            return out;
+        };
+        // Calculate the hash digest as an array of 5 32bit integers.
+        var rawDigest = this.rawDigest = function (str) {
+                var msgLen = str.byteLength || str.length || str.size || 0;
+                initState(self$2.heap, self$2.padMaxChunkLen);
+                var chunkOffset = 0, chunkLen = self$2.maxChunkLen, last;
+                for (chunkOffset = 0; msgLen > chunkOffset + chunkLen; chunkOffset += chunkLen) {
+                    coreCall(str, chunkOffset, chunkLen, msgLen, false);
+                }
+                coreCall(str, chunkOffset, msgLen - chunkOffset, msgLen, true);
+                return getRawDigest(self$2.heap, self$2.padMaxChunkLen);
+            };
+        // The digest and digestFrom* interface returns the hash digest
+        // as a hex string.
+        this.digest = this.digestFromString = this.digestFromBuffer = this.digestFromArrayBuffer = function (str) {
+            return hex(rawDigest(str).buffer);
+        };
+    }
+    ;
+    // The low-level RushCore module provides the heart of Rusha,
+    // a high-speed sha1 implementation working on an Int32Array heap.
+    // At first glance, the implementation seems complicated, however
+    // with the SHA1 spec at hand, it is obvious this almost a textbook
+    // implementation that has a few functions hand-inlined and a few loops
+    // hand-unrolled.
+    function RushaCore(stdlib, foreign, heap) {
+        'use asm';
+        var H = new stdlib.Int32Array(heap);
+        function hash(k, x) {
+            // k in bytes
+            k = k | 0;
+            x = x | 0;
+            var i = 0, j = 0, y0 = 0, z0 = 0, y1 = 0, z1 = 0, y2 = 0, z2 = 0, y3 = 0, z3 = 0, y4 = 0, z4 = 0, t0 = 0, t1 = 0;
+            y0 = H[x + 320 >> 2] | 0;
+            y1 = H[x + 324 >> 2] | 0;
+            y2 = H[x + 328 >> 2] | 0;
+            y3 = H[x + 332 >> 2] | 0;
+            y4 = H[x + 336 >> 2] | 0;
+            for (i = 0; (i | 0) < (k | 0); i = i + 64 | 0) {
+                z0 = y0;
+                z1 = y1;
+                z2 = y2;
+                z3 = y3;
+                z4 = y4;
+                for (j = 0; (j | 0) < 64; j = j + 4 | 0) {
+                    t1 = H[i + j >> 2] | 0;
+                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | ~y1 & y3) | 0) + ((t1 + y4 | 0) + 1518500249 | 0) | 0;
+                    y4 = y3;
+                    y3 = y2;
+                    y2 = y1 << 30 | y1 >>> 2;
+                    y1 = y0;
+                    y0 = t0;
+                    ;
+                    H[k + j >> 2] = t1;
+                }
+                for (j = k + 64 | 0; (j | 0) < (k + 80 | 0); j = j + 4 | 0) {
+                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
+                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | ~y1 & y3) | 0) + ((t1 + y4 | 0) + 1518500249 | 0) | 0;
+                    y4 = y3;
+                    y3 = y2;
+                    y2 = y1 << 30 | y1 >>> 2;
+                    y1 = y0;
+                    y0 = t0;
+                    ;
+                    H[j >> 2] = t1;
+                }
+                for (j = k + 80 | 0; (j | 0) < (k + 160 | 0); j = j + 4 | 0) {
+                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
+                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 ^ y2 ^ y3) | 0) + ((t1 + y4 | 0) + 1859775393 | 0) | 0;
+                    y4 = y3;
+                    y3 = y2;
+                    y2 = y1 << 30 | y1 >>> 2;
+                    y1 = y0;
+                    y0 = t0;
+                    ;
+                    H[j >> 2] = t1;
+                }
+                for (j = k + 160 | 0; (j | 0) < (k + 240 | 0); j = j + 4 | 0) {
+                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
+                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | y1 & y3 | y2 & y3) | 0) + ((t1 + y4 | 0) - 1894007588 | 0) | 0;
+                    y4 = y3;
+                    y3 = y2;
+                    y2 = y1 << 30 | y1 >>> 2;
+                    y1 = y0;
+                    y0 = t0;
+                    ;
+                    H[j >> 2] = t1;
+                }
+                for (j = k + 240 | 0; (j | 0) < (k + 320 | 0); j = j + 4 | 0) {
+                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
+                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 ^ y2 ^ y3) | 0) + ((t1 + y4 | 0) - 899497514 | 0) | 0;
+                    y4 = y3;
+                    y3 = y2;
+                    y2 = y1 << 30 | y1 >>> 2;
+                    y1 = y0;
+                    y0 = t0;
+                    ;
+                    H[j >> 2] = t1;
+                }
+                y0 = y0 + z0 | 0;
+                y1 = y1 + z1 | 0;
+                y2 = y2 + z2 | 0;
+                y3 = y3 + z3 | 0;
+                y4 = y4 + z4 | 0;
+            }
+            H[x + 320 >> 2] = y0;
+            H[x + 324 >> 2] = y1;
+            H[x + 328 >> 2] = y2;
+            H[x + 332 >> 2] = y3;
+            H[x + 336 >> 2] = y4;
+        }
+        return { hash: hash };
+    }
+}());;/*
+ * JIO extension for resource replication.
+ * Copyright (C) 2013, 2015  Nexedi SA
+ *
+ *   This library is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*jslint nomen: true*/
+/*global jIO, RSVP, Rusha*/
+
+(function (jIO, RSVP, Rusha) {
+  "use strict";
+
+  var rusha = new Rusha(),
+    CONFLICT_THROW = 0,
+    CONFLICT_KEEP_LOCAL = 1,
+    CONFLICT_KEEP_REMOTE = 2,
+    CONFLICT_CONTINUE = 3;
+
+  /****************************************************
+   Use a local jIO to read/write/search documents
+   Synchronize in background those document with a remote jIO.
+   Synchronization status is stored for each document as an local attachment.
+  ****************************************************/
+
+  function generateHash(content) {
+    // XXX Improve performance by moving calculation to WebWorker
+    return rusha.digestFromString(content);
+  }
+
+  function ReplicateStorage(spec) {
+    this._query_options = spec.query || {};
+
+    this._local_sub_storage = jIO.createJIO(spec.local_sub_storage);
+    this._remote_sub_storage = jIO.createJIO(spec.remote_sub_storage);
+
+    this._signature_hash = "_replicate_" + generateHash(
+      JSON.stringify(spec.local_sub_storage) +
+        JSON.stringify(spec.remote_sub_storage) +
+        JSON.stringify(this._query_options)
+    );
+    this._signature_sub_storage = jIO.createJIO({
+      type: "document",
+      document_id: this._signature_hash,
+      sub_storage: spec.local_sub_storage
+    });
+
+    this._use_remote_post = spec.use_remote_post || false;
+
+    this._conflict_handling = spec.conflict_handling || 0;
+    // 0: no resolution (ie, throw an Error)
+    // 1: keep the local state
+    //    (overwrites the remote document with local content)
+    //    (delete remote document if local is deleted)
+    // 2: keep the remote state
+    //    (overwrites the local document with remote content)
+    //    (delete local document if remote is deleted)
+    // 3: keep both copies (leave documents untouched, no signature update)
+    if ((this._conflict_handling !== CONFLICT_THROW) &&
+        (this._conflict_handling !== CONFLICT_KEEP_LOCAL) &&
+        (this._conflict_handling !== CONFLICT_KEEP_REMOTE) &&
+        (this._conflict_handling !== CONFLICT_CONTINUE)) {
+      throw new jIO.util.jIOError("Unsupported conflict handling: " +
+                                  this._conflict_handling, 400);
+    }
+
+    this._check_local_modification = spec.check_local_modification;
+    if (this._check_local_modification === undefined) {
+      this._check_local_modification = true;
+    }
+    this._check_local_creation = spec.check_local_creation;
+    if (this._check_local_creation === undefined) {
+      this._check_local_creation = true;
+    }
+    this._check_local_deletion = spec.check_local_deletion;
+    if (this._check_local_deletion === undefined) {
+      this._check_local_deletion = true;
+    }
+    this._check_remote_modification = spec.check_remote_modification;
+    if (this._check_remote_modification === undefined) {
+      this._check_remote_modification = true;
+    }
+    this._check_remote_creation = spec.check_remote_creation;
+    if (this._check_remote_creation === undefined) {
+      this._check_remote_creation = true;
+    }
+    this._check_remote_deletion = spec.check_remote_deletion;
+    if (this._check_remote_deletion === undefined) {
+      this._check_remote_deletion = true;
+    }
+  }
+
+  ReplicateStorage.prototype.remove = function (id) {
+    if (id === this._signature_hash) {
+      throw new jIO.util.jIOError(this._signature_hash + " is frozen",
+                                  403);
+    }
+    return this._local_sub_storage.remove.apply(this._local_sub_storage,
+                                                arguments);
+  };
+  ReplicateStorage.prototype.post = function () {
+    return this._local_sub_storage.post.apply(this._local_sub_storage,
+                                              arguments);
+  };
+  ReplicateStorage.prototype.put = function (id) {
+    if (id === this._signature_hash) {
+      throw new jIO.util.jIOError(this._signature_hash + " is frozen",
+                                  403);
+    }
+    return this._local_sub_storage.put.apply(this._local_sub_storage,
+                                             arguments);
+  };
+  ReplicateStorage.prototype.get = function () {
+    return this._local_sub_storage.get.apply(this._local_sub_storage,
+                                             arguments);
+  };
+  ReplicateStorage.prototype.hasCapacity = function () {
+    return this._local_sub_storage.hasCapacity.apply(this._local_sub_storage,
+                                                     arguments);
+  };
+  ReplicateStorage.prototype.buildQuery = function () {
+    // XXX Remove signature document?
+    return this._local_sub_storage.buildQuery.apply(this._local_sub_storage,
+                                                    arguments);
+  };
+
+  ReplicateStorage.prototype.repair = function () {
+    var context = this,
+      argument_list = arguments,
+      skip_document_dict = {};
+
+    // Do not sync the signature document
+    skip_document_dict[context._signature_hash] = null;
+
+    function propagateModification(source, destination, doc, hash, id,
+                                   options) {
+      var result,
+        post_id,
+        to_skip = true;
+      if (options === undefined) {
+        options = {};
+      }
+      if (options.use_post) {
+        result = destination.post(doc)
+          .push(function (new_id) {
+            to_skip = false;
+            post_id = new_id;
+            return source.put(post_id, doc);
+          })
+          .push(function () {
+            return source.remove(id);
+          })
+          .push(function () {
+            return context._signature_sub_storage.remove(id);
+          })
+          .push(function () {
+            to_skip = true;
+            return context._signature_sub_storage.put(post_id, {
+              "hash": hash
+            });
+          })
+          .push(function () {
+            skip_document_dict[post_id] = null;
+          });
+      } else {
+        result = destination.put(id, doc)
+          .push(function () {
+            return context._signature_sub_storage.put(id, {
+              "hash": hash
+            });
+          });
+      }
+      return result
+        .push(function () {
+          if (to_skip) {
+            skip_document_dict[id] = null;
+          }
+        });
+    }
+
+    function checkLocalCreation(queue, source, destination, id, options,
+                                getMethod) {
+      var remote_doc;
+      queue
+        .push(function () {
+          return destination.get(id);
+        })
+        .push(function (doc) {
+          remote_doc = doc;
+        }, function (error) {
+          if ((error instanceof jIO.util.jIOError) &&
+              (error.status_code === 404)) {
+            // This document was never synced.
+            // Push it to the remote storage and store sync information
+            return;
+          }
+          throw error;
+        })
+        .push(function () {
+          // This document was never synced.
+          // Push it to the remote storage and store sync information
+          return getMethod(id);
+        })
+        .push(function (doc) {
+          var local_hash = generateHash(JSON.stringify(doc)),
+            remote_hash;
+          if (remote_doc === undefined) {
+            return propagateModification(source, destination, doc, local_hash,
+                                         id, options);
+          }
+
+          remote_hash = generateHash(JSON.stringify(remote_doc));
+          if (local_hash === remote_hash) {
+            // Same document
+            return context._signature_sub_storage.put(id, {
+              "hash": local_hash
+            })
+              .push(function () {
+                skip_document_dict[id] = null;
+              });
+          }
+          if (options.conflict_ignore === true) {
+            return;
+          }
+          if (options.conflict_force === true) {
+            return propagateModification(source, destination, doc, local_hash,
+                                         id, options);
+          }
+          // Already exists on destination
+          throw new jIO.util.jIOError("Conflict on '" + id + "': " +
+                                      JSON.stringify(doc) + " !== " +
+                                      JSON.stringify(remote_doc),
+                                      409);
+        });
+    }
+
+    function checkBulkLocalCreation(queue, source, destination, id_list,
+                                    options) {
+      queue
+        .push(function () {
+          return source.bulk(id_list);
+        })
+        .push(function (result_list) {
+          var i,
+            sub_queue = new RSVP.Queue();
+
+          function getResult(j) {
+            return function (id) {
+              if (id !== id_list[j].parameter_list[0]) {
+                throw new Error("Does not access expected ID " + id);
+              }
+              return result_list[j];
+            };
+          }
+
+          for (i = 0; i < result_list.length; i += 1) {
+            checkLocalCreation(sub_queue, source, destination,
+                               id_list[i].parameter_list[0],
+                               options, getResult(i));
+          }
+          return sub_queue;
+        });
+    }
+
+    function checkLocalDeletion(queue, destination, id, source) {
+      var status_hash;
+      queue
+        .push(function () {
+          return context._signature_sub_storage.get(id);
+        })
+        .push(function (result) {
+          status_hash = result.hash;
+          return destination.get(id)
+            .push(function (doc) {
+              var remote_hash = generateHash(JSON.stringify(doc));
+              if (remote_hash === status_hash) {
+                return destination.remove(id)
+                  .push(function () {
+                    return context._signature_sub_storage.remove(id);
+                  })
+                  .push(function () {
+                    skip_document_dict[id] = null;
+                  });
+              }
+              // Modifications on remote side
+              // Push them locally
+              return propagateModification(destination, source, doc,
+                                           remote_hash, id);
+            }, function (error) {
+              if ((error instanceof jIO.util.jIOError) &&
+                  (error.status_code === 404)) {
+                return context._signature_sub_storage.remove(id)
+                  .push(function () {
+                    skip_document_dict[id] = null;
+                  });
+              }
+              throw error;
+            });
+        });
+    }
+
+    function checkSignatureDifference(queue, source, destination, id,
+                                      conflict_force, conflict_ignore,
+                                      getMethod) {
+      queue
+        .push(function () {
+          return RSVP.all([
+            getMethod(id),
+            context._signature_sub_storage.get(id)
+          ]);
+        })
+        .push(function (result_list) {
+          var doc = result_list[0],
+            local_hash = generateHash(JSON.stringify(doc)),
+            status_hash = result_list[1].hash;
+
+          if (local_hash !== status_hash) {
+            // Local modifications
+            return destination.get(id)
+              .push(function (remote_doc) {
+                var remote_hash = generateHash(JSON.stringify(remote_doc));
+                if (remote_hash !== status_hash) {
+                  // Modifications on both sides
+                  if (local_hash === remote_hash) {
+                    // Same modifications on both side \o/
+                    return context._signature_sub_storage.put(id, {
+                      "hash": local_hash
+                    })
+                      .push(function () {
+                        skip_document_dict[id] = null;
+                      });
+                  }
+                  if (conflict_ignore === true) {
+                    return;
+                  }
+                  if (conflict_force !== true) {
+                    throw new jIO.util.jIOError("Conflict on '" + id + "': " +
+                                                JSON.stringify(doc) + " !== " +
+                                                JSON.stringify(remote_doc),
+                                                409);
+                  }
+                }
+                return propagateModification(source, destination, doc,
+                                             local_hash, id);
+              }, function (error) {
+                if ((error instanceof jIO.util.jIOError) &&
+                    (error.status_code === 404)) {
+                  // Document has been deleted remotely
+                  return propagateModification(source, destination, doc,
+                                               local_hash, id);
+                }
+                throw error;
+              });
+          }
+        });
+    }
+
+    function checkBulkSignatureDifference(queue, source, destination, id_list,
+                                          conflict_force, conflict_ignore) {
+      queue
+        .push(function () {
+          return source.bulk(id_list);
+        })
+        .push(function (result_list) {
+          var i,
+            sub_queue = new RSVP.Queue();
+
+          function getResult(j) {
+            return function (id) {
+              if (id !== id_list[j].parameter_list[0]) {
+                throw new Error("Does not access expected ID " + id);
+              }
+              return result_list[j];
+            };
+          }
+
+          for (i = 0; i < result_list.length; i += 1) {
+            checkSignatureDifference(sub_queue, source, destination,
+                               id_list[i].parameter_list[0],
+                               conflict_force, conflict_ignore,
+                               getResult(i));
+          }
+          return sub_queue;
+        });
+    }
+
+    function pushStorage(source, destination, options) {
+      var queue = new RSVP.Queue();
+      if (!options.hasOwnProperty("use_post")) {
+        options.use_post = false;
+      }
+      return queue
+        .push(function () {
+          return RSVP.all([
+            source.allDocs(context._query_options),
+            context._signature_sub_storage.allDocs()
+          ]);
+        })
+        .push(function (result_list) {
+          var i,
+            local_dict = {},
+            new_list = [],
+            change_list = [],
+            signature_dict = {},
+            key;
+          for (i = 0; i < result_list[0].data.total_rows; i += 1) {
+            if (!skip_document_dict.hasOwnProperty(
+                result_list[0].data.rows[i].id
+              )) {
+              local_dict[result_list[0].data.rows[i].id] = i;
+            }
+          }
+          for (i = 0; i < result_list[1].data.total_rows; i += 1) {
+            if (!skip_document_dict.hasOwnProperty(
+                result_list[1].data.rows[i].id
+              )) {
+              signature_dict[result_list[1].data.rows[i].id] = i;
+            }
+          }
+
+          if (options.check_creation === true) {
+            for (key in local_dict) {
+              if (local_dict.hasOwnProperty(key)) {
+                if (!signature_dict.hasOwnProperty(key)) {
+                  if (options.use_bulk_get === true) {
+                    new_list.push({
+                      method: "get",
+                      parameter_list: [key]
+                    });
+                  } else {
+                    checkLocalCreation(queue, source, destination, key,
+                                       options, source.get.bind(source));
+                  }
+                }
+              }
+            }
+            if ((options.use_bulk_get === true) && (new_list.length !== 0)) {
+              checkBulkLocalCreation(queue, source, destination, new_list,
+                                     options);
+            }
+          }
+          for (key in signature_dict) {
+            if (signature_dict.hasOwnProperty(key)) {
+              if (local_dict.hasOwnProperty(key)) {
+                if (options.check_modification === true) {
+                  if (options.use_bulk_get === true) {
+                    change_list.push({
+                      method: "get",
+                      parameter_list: [key]
+                    });
+                  } else {
+                    checkSignatureDifference(queue, source, destination, key,
+                                             options.conflict_force,
+                                             options.conflict_ignore,
+                                             source.get.bind(source));
+                  }
+                }
+              } else {
+                if (options.check_deletion === true) {
+                  checkLocalDeletion(queue, destination, key, source);
+                }
+              }
+            }
+          }
+          if ((options.use_bulk_get === true) && (change_list.length !== 0)) {
+            checkBulkSignatureDifference(queue, source, destination,
+                                         change_list,
+                                         options.conflict_force,
+                                         options.conflict_ignore);
+          }
+        });
+    }
+
+    return new RSVP.Queue()
+      .push(function () {
+        // Ensure that the document storage is usable
+        return context._signature_sub_storage.__storage._sub_storage.get(
+          context._signature_hash
+        );
+      })
+      .push(undefined, function (error) {
+        if ((error instanceof jIO.util.jIOError) &&
+            (error.status_code === 404)) {
+          return context._signature_sub_storage.__storage._sub_storage.put(
+            context._signature_hash,
+            {}
+          );
+        }
+        throw error;
+      })
+
+      .push(function () {
+        return RSVP.all([
+// Don't repair local_sub_storage twice
+//           context._signature_sub_storage.repair.apply(
+//             context._signature_sub_storage,
+//             argument_list
+//           ),
+          context._local_sub_storage.repair.apply(
+            context._local_sub_storage,
+            argument_list
+          ),
+          context._remote_sub_storage.repair.apply(
+            context._remote_sub_storage,
+            argument_list
+          )
+        ]);
+      })
+
+      .push(function () {
+        if (context._check_local_modification ||
+            context._check_local_creation ||
+            context._check_local_deletion) {
+          return pushStorage(context._local_sub_storage,
+                             context._remote_sub_storage,
+                             {
+              use_post: context._use_remote_post,
+              conflict_force: (context._conflict_handling ===
+                               CONFLICT_KEEP_LOCAL),
+              conflict_ignore: ((context._conflict_handling ===
+                                 CONFLICT_CONTINUE) ||
+                                (context._conflict_handling ===
+                                 CONFLICT_KEEP_REMOTE)),
+              check_modification: context._check_local_modification,
+              check_creation: context._check_local_creation,
+              check_deletion: context._check_local_deletion
+            });
+        }
+      })
+      .push(function () {
+        // Autoactivate bulk if substorage implements it
+        // Keep it like this until the bulk API is stabilized
+        var use_bulk_get = false;
+        try {
+          use_bulk_get = context._remote_sub_storage.hasCapacity("bulk");
+        } catch (error) {
+          if (!((error instanceof jIO.util.jIOError) &&
+               (error.status_code === 501))) {
+            throw error;
+          }
+        }
+        if (context._check_remote_modification ||
+            context._check_remote_creation ||
+            context._check_remote_deletion) {
+          return pushStorage(context._remote_sub_storage,
+                             context._local_sub_storage, {
+              use_bulk_get: use_bulk_get,
+              conflict_force: (context._conflict_handling ===
+                               CONFLICT_KEEP_REMOTE),
+              conflict_ignore: (context._conflict_handling ===
+                                CONFLICT_CONTINUE),
+              check_modification: context._check_remote_modification,
+              check_creation: context._check_remote_creation,
+              check_deletion: context._check_remote_deletion
+            });
+        }
+      });
+  };
+
+  jIO.addStorage('replicate', ReplicateStorage);
+
+}(jIO, RSVP, Rusha));
+;/*
+ * Copyright 2015, Nexedi SA
+ * Released under the LGPL license.
+ * http://www.gnu.org/licenses/lgpl.html
+ */
+
+/*jslint nomen: true*/
+/*global Rusha*/
+
+/**
+ * JIO Sha Storage. Type = 'sha'.
+ */
+
+(function (Rusha) {
+  "use strict";
+
+  var rusha = new Rusha();
+
+  function ShaStorage(spec) {
+    this._sub_storage = jIO.createJIO(spec.sub_storage);
+  }
+
+  ShaStorage.prototype.post = function (param) {
+    return this._sub_storage.put(
+      rusha.digestFromString(JSON.stringify(param)),
+      param
+    );
+  };
+
+  ShaStorage.prototype.get = function () {
+    return this._sub_storage.get.apply(this._sub_storage, arguments);
+  };
+  ShaStorage.prototype.remove = function () {
+    return this._sub_storage.remove.apply(this._sub_storage, arguments);
+  };
+  ShaStorage.prototype.hasCapacity = function () {
+    return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments);
+  };
+  ShaStorage.prototype.buildQuery = function () {
+    return this._sub_storage.buildQuery.apply(this._sub_storage, arguments);
+  };
+  ShaStorage.prototype.getAttachment = function () {
+    return this._sub_storage.getAttachment.apply(this._sub_storage, arguments);
+  };
+  ShaStorage.prototype.putAttachment = function () {
+    return this._sub_storage.putAttachment.apply(this._sub_storage, arguments);
+  };
+  ShaStorage.prototype.removeAttachment = function () {
+    return this._sub_storage.removeAttachment.apply(this._sub_storage,
+                                                    arguments);
+  };
+  ShaStorage.prototype.allAttachments = function () {
+    return this._sub_storage.allAttachments.apply(this._sub_storage, arguments);
+  };
+  ShaStorage.prototype.repair = function () {
+    return this._sub_storage.repair.apply(this._sub_storage, arguments);
+  };
+
+  jIO.addStorage('sha', ShaStorage);
+
+}(Rusha));
+;/*jslint nomen: true*/
+(function (jIO) {
+  "use strict";
+
+  /**
+   * The jIO UUIDStorage extension
+   *
+   * @class UUIDStorage
+   * @constructor
+   */
+  function UUIDStorage(spec) {
+    this._sub_storage = jIO.createJIO(spec.sub_storage);
+  }
+
+  UUIDStorage.prototype.get = function () {
+    return this._sub_storage.get.apply(this._sub_storage, arguments);
+  };
+  UUIDStorage.prototype.allAttachments = function () {
+    return this._sub_storage.allAttachments.apply(this._sub_storage, arguments);
+  };
+  UUIDStorage.prototype.post = function (param) {
+
+    function S4() {
+      return ('0000' + Math.floor(
+        Math.random() * 0x10000 /* 65536 */
+      ).toString(16)).slice(-4);
+    }
+
+    var id = S4() + S4() + "-" +
+      S4() + "-" +
+      S4() + "-" +
+      S4() + "-" +
+      S4() + S4() + S4();
+
+    return this.put(id, param);
+  };
+  UUIDStorage.prototype.put = function () {
+    return this._sub_storage.put.apply(this._sub_storage, arguments);
+  };
+  UUIDStorage.prototype.remove = function () {
+    return this._sub_storage.remove.apply(this._sub_storage, arguments);
+  };
+  UUIDStorage.prototype.getAttachment = function () {
+    return this._sub_storage.getAttachment.apply(this._sub_storage, arguments);
+  };
+  UUIDStorage.prototype.putAttachment = function () {
+    return this._sub_storage.putAttachment.apply(this._sub_storage, arguments);
+  };
+  UUIDStorage.prototype.removeAttachment = function () {
+    return this._sub_storage.removeAttachment.apply(this._sub_storage,
+                                                    arguments);
+  };
+  UUIDStorage.prototype.repair = function () {
+    return this._sub_storage.repair.apply(this._sub_storage, arguments);
+  };
+  UUIDStorage.prototype.hasCapacity = function (name) {
+    return this._sub_storage.hasCapacity(name);
+  };
+  UUIDStorage.prototype.buildQuery = function () {
+    return this._sub_storage.buildQuery.apply(this._sub_storage,
+                                              arguments);
+  };
+
+  jIO.addStorage('uuid', UUIDStorage);
+
+}(jIO));
+;/*
+ * Copyright 2013, Nexedi SA
+ * Released under the LGPL license.
+ * http://www.gnu.org/licenses/lgpl.html
+ */
+
+/*jslint nomen: true*/
+/*global jIO, RSVP*/
+
+/**
+ * JIO Memory Storage. Type = 'memory'.
+ * Memory browser "database" storage.
+ *
+ * Storage Description:
+ *
+ *     {
+ *       "type": "memory"
+ *     }
+ *
+ * @class MemoryStorage
+ */
+
+(function (jIO, JSON, RSVP) {
+  "use strict";
+
+  /**
+   * The JIO MemoryStorage extension
+   *
+   * @class MemoryStorage
+   * @constructor
+   */
+  function MemoryStorage() {
+    this._database = {};
+  }
+
+  MemoryStorage.prototype.put = function (id, metadata) {
+    if (!this._database.hasOwnProperty(id)) {
+      this._database[id] = {
+        attachments: {}
+      };
+    }
+    this._database[id].doc = JSON.stringify(metadata);
+    return id;
+  };
+
+  MemoryStorage.prototype.get = function (id) {
+    try {
+      return JSON.parse(this._database[id].doc);
+    } catch (error) {
+      if (error instanceof TypeError) {
+        throw new jIO.util.jIOError(
+          "Cannot find document: " + id,
+          404
+        );
+      }
+      throw error;
+    }
+  };
+
+  MemoryStorage.prototype.allAttachments = function (id) {
+    var key,
+      attachments = {};
+    try {
+      for (key in this._database[id].attachments) {
+        if (this._database[id].attachments.hasOwnProperty(key)) {
+          attachments[key] = {};
+        }
+      }
+    } catch (error) {
+      if (error instanceof TypeError) {
+        throw new jIO.util.jIOError(
+          "Cannot find document: " + id,
+          404
+        );
+      }
+      throw error;
+    }
+    return attachments;
+  };
+
+  MemoryStorage.prototype.remove = function (id) {
+    delete this._database[id];
+    return id;
+  };
+
+  MemoryStorage.prototype.getAttachment = function (id, name) {
+    try {
+      var result = this._database[id].attachments[name];
+      if (result === undefined) {
+        throw new jIO.util.jIOError(
+          "Cannot find attachment: " + id + " , " + name,
+          404
+        );
+      }
+      return jIO.util.dataURItoBlob(result);
+    } catch (error) {
+      if (error instanceof TypeError) {
+        throw new jIO.util.jIOError(
+          "Cannot find attachment: " + id + " , " + name,
+          404
+        );
+      }
+      throw error;
+    }
+  };
+
+  MemoryStorage.prototype.putAttachment = function (id, name, blob) {
+    var attachment_dict;
+    try {
+      attachment_dict = this._database[id].attachments;
+    } catch (error) {
+      if (error instanceof TypeError) {
+        throw new jIO.util.jIOError("Cannot find document: " + id, 404);
+      }
+      throw error;
+    }
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.readBlobAsDataURL(blob);
+      })
+      .push(function (evt) {
+        attachment_dict[name] = evt.target.result;
+      });
+  };
+
+  MemoryStorage.prototype.removeAttachment = function (id, name) {
+    try {
+      delete this._database[id].attachments[name];
+    } catch (error) {
+      if (error instanceof TypeError) {
+        throw new jIO.util.jIOError(
+          "Cannot find document: " + id,
+          404
+        );
+      }
+      throw error;
+    }
+  };
+
+
+  MemoryStorage.prototype.hasCapacity = function (name) {
+    return ((name === "list") || (name === "include"));
+  };
+
+  MemoryStorage.prototype.buildQuery = function (options) {
+    var rows = [],
+      i;
+    for (i in this._database) {
+      if (this._database.hasOwnProperty(i)) {
+        if (options.include_docs === true) {
+          rows.push({
+            id: i,
+            value: {},
+            doc: JSON.parse(this._database[i].doc)
+          });
+        } else {
+          rows.push({
+            id: i,
+            value: {}
+          });
+        }
+
+      }
+    }
+    return rows;
+  };
+
+  jIO.addStorage('memory', MemoryStorage);
+
+}(jIO, JSON, RSVP));
+;/*jslint nomen: true*/
+/*global RSVP, Blob, LZString, DOMException*/
+(function (RSVP, Blob, LZString, DOMException) {
+  "use strict";
+
+  /**
+   * The jIO ZipStorage extension
+   *
+   * @class ZipStorage
+   * @constructor
+   */
+
+  var MIME_TYPE = "application/x-jio-utf16_lz_string";
+
+  function ZipStorage(spec) {
+    this._sub_storage = jIO.createJIO(spec.sub_storage);
+  }
+
+  ZipStorage.prototype.get = function () {
+    return this._sub_storage.get.apply(this._sub_storage,
+                                        arguments);
+  };
+
+  ZipStorage.prototype.post = function () {
+    return this._sub_storage.post.apply(this._sub_storage,
+                                        arguments);
+  };
+
+  ZipStorage.prototype.put = function () {
+    return this._sub_storage.put.apply(this._sub_storage,
+                                       arguments);
+  };
+
+  ZipStorage.prototype.remove = function () {
+    return this._sub_storage.remove.apply(this._sub_storage,
+                                          arguments);
+  };
+
+  ZipStorage.prototype.hasCapacity = function () {
+    return this._sub_storage.hasCapacity.apply(this._sub_storage,
+                                               arguments);
+  };
+
+  ZipStorage.prototype.buildQuery = function () {
+    return this._sub_storage.buildQuery.apply(this._sub_storage,
+                                              arguments);
+  };
+
+  ZipStorage.prototype.getAttachment = function (id, name) {
+    var that = this;
+    return that._sub_storage.getAttachment(id, name)
+      .push(function (blob) {
+        if (blob.type !== MIME_TYPE) {
+          return blob;
+        }
+        return new RSVP.Queue()
+          .push(function () {
+            return jIO.util.readBlobAsText(blob, 'utf16');
+          })
+          .push(function (evt) {
+            var result =
+              LZString.decompressFromUTF16(evt.target.result);
+            if (result === '') {
+              return blob;
+            }
+            try {
+              return jIO.util.dataURItoBlob(
+                result
+              );
+            } catch (error) {
+              if (error instanceof DOMException) {
+                return blob;
+              }
+              throw error;
+            }
+          });
+      });
+  };
+
+  function myEndsWith(str, query) {
+    return (str.indexOf(query) === str.length - query.length);
+  }
+
+  ZipStorage.prototype.putAttachment = function (id, name, blob) {
+    var that = this;
+    if ((blob.type.indexOf("text/") === 0) || myEndsWith(blob.type, "xml") ||
+        myEndsWith(blob.type, "json")) {
+      return new RSVP.Queue()
+        .push(function () {
+          return jIO.util.readBlobAsDataURL(blob);
+        })
+        .push(function (data) {
+          var result = LZString.compressToUTF16(data.target.result);
+          blob = new Blob([result],
+                          {type: MIME_TYPE});
+          return that._sub_storage.putAttachment(id, name, blob);
+        });
+    }
+    return this._sub_storage.putAttachment.apply(this._sub_storage,
+                                                 arguments);
+  };
+
+  ZipStorage.prototype.removeAttachment = function () {
+    return this._sub_storage.removeAttachment.apply(this._sub_storage,
+                                                    arguments);
+  };
+
+  ZipStorage.prototype.allAttachments = function () {
+    return this._sub_storage.allAttachments.apply(this._sub_storage,
+                                                  arguments);
+  };
+
+  jIO.addStorage('zip', ZipStorage);
+}(RSVP, Blob, LZString, DOMException));
+;/*
+ * Copyright 2013, Nexedi SA
+ * Released under the LGPL license.
+ * http://www.gnu.org/licenses/lgpl.html
+ */
+/**
+ * JIO Dropbox Storage. Type = "dropbox".
+ * Dropbox "database" storage.
+ */
+/*global Blob, jIO, RSVP, UriTemplate*/
+/*jslint nomen: true*/
+
+(function (jIO, RSVP, Blob, UriTemplate) {
+  "use strict";
+  var UPLOAD_URL = "https://content.dropboxapi.com/1/files_put/" +
+      "{+root}{+id}{+name}{?access_token}",
+    upload_template = UriTemplate.parse(UPLOAD_URL),
+    CREATE_DIR_URL = "https://api.dropboxapi.com/1/fileops/create_folder" +
+      "{?access_token,root,path}",
+    create_dir_template = UriTemplate.parse(CREATE_DIR_URL),
+    REMOVE_URL = "https://api.dropboxapi.com/1/fileops/delete/" +
+      "{?access_token,root,path}",
+    remote_template = UriTemplate.parse(REMOVE_URL),
+    GET_URL = "https://content.dropboxapi.com/1/files" +
+      "{/root,id}{+name}{?access_token}",
+    get_template = UriTemplate.parse(GET_URL),
+    //LIST_URL = 'https://api.dropboxapi.com/1/metadata/sandbox/';
+    METADATA_URL = "https://api.dropboxapi.com/1/metadata" +
+      "{/root}{+id}{?access_token}",
+    metadata_template = UriTemplate.parse(METADATA_URL);
+
+  function restrictDocumentId(id) {
+    if (id.indexOf("/") !== 0) {
+      throw new jIO.util.jIOError("id " + id + " is forbidden (no begin /)",
+                                  400);
+    }
+    if (id.lastIndexOf("/") !== (id.length - 1)) {
+      throw new jIO.util.jIOError("id " + id + " is forbidden (no end /)",
+                                  400);
+    }
+    return id;
+  }
+
+  function restrictAttachmentId(id) {
+    if (id.indexOf("/") !== -1) {
+      throw new jIO.util.jIOError("attachment " + id + " is forbidden",
+                                  400);
+    }
+  }
+
+  /**
+   * The JIO Dropbox Storage extension
+   *
+   * @class DropboxStorage
+   * @constructor
+   */
+  function DropboxStorage(spec) {
+    if (typeof spec.access_token !== 'string' || !spec.access_token) {
+      throw new TypeError("Access Token' must be a string " +
+                          "which contains more than one character.");
+    }
+    if (typeof spec.root !== 'string' || !spec.root ||
+        (spec.root !== "dropbox" && spec.root !== "sandbox")) {
+      throw new TypeError("root must be 'dropbox' or 'sandbox'");
+    }
+    this._access_token = spec.access_token;
+    this._root = spec.root;
+  }
+
+  DropboxStorage.prototype.put = function (id, param) {
+    var that = this;
+    id = restrictDocumentId(id);
+    if (Object.getOwnPropertyNames(param).length > 0) {
+      // Reject if param has some properties
+      throw new jIO.util.jIOError("Can not store properties: " +
+                                  Object.getOwnPropertyNames(param), 400);
+    }
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          type: "POST",
+          url: create_dir_template.expand({
+            access_token: that._access_token,
+            root: that._root,
+            path: id
+          })
+        });
+      })
+      .push(undefined, function (err) {
+        if ((err.target !== undefined) &&
+            (err.target.status === 405)) {
+          // Directory already exists, no need to fail
+          return;
+        }
+        throw err;
+      });
+  };
+
+  DropboxStorage.prototype.remove = function (id) {
+    id = restrictDocumentId(id);
+    return jIO.util.ajax({
+      type: "POST",
+      url: remote_template.expand({
+        access_token: this._access_token,
+        root: this._root,
+        path: id
+      })
+    });
+  };
+
+  DropboxStorage.prototype.get = function (id) {
+    var that = this;
+
+    if (id === "/") {
+      return {};
+    }
+    id = restrictDocumentId(id);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          type: "GET",
+          url: metadata_template.expand({
+            access_token: that._access_token,
+            root: that._root,
+            id: id
+          })
+        });
+      })
+      .push(function (evt) {
+        var obj = JSON.parse(evt.target.response ||
+                             evt.target.responseText);
+        if (obj.is_dir) {
+          return {};
+        }
+        throw new jIO.util.jIOError("Not a directory: " + id, 404);
+      }, function (error) {
+        if (error.target !== undefined && error.target.status === 404) {
+          throw new jIO.util.jIOError("Cannot find document: " + id, 404);
+        }
+        throw error;
+      });
+  };
+
+  DropboxStorage.prototype.allAttachments = function (id) {
+
+    var that = this;
+    id = restrictDocumentId(id);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          type: "GET",
+          url: metadata_template.expand({
+            access_token: that._access_token,
+            root: that._root,
+            id: id
+          })
+        });
+      })
+      .push(function (evt) {
+        var obj = JSON.parse(evt.target.response || evt.target.responseText),
+          i,
+          result = {};
+        if (!obj.is_dir) {
+          throw new jIO.util.jIOError("Not a directory: " + id, 404);
+        }
+        for (i = 0; i < obj.contents.length; i += 1) {
+          if (!obj.contents[i].is_dir) {
+            result[obj.contents[i].path.split("/").pop()] = {};
+          }
+        }
+        return result;
+      }, function (error) {
+        if (error.target !== undefined && error.target.status === 404) {
+          throw new jIO.util.jIOError("Cannot find document: " + id, 404);
+        }
+        throw error;
+      });
+  };
+
+  //currently, putAttachment will fail with files larger than 150MB,
+  //due to the Dropbox API. the API provides the "chunked_upload" method
+  //to pass this limit, but upload process becomes more complex to implement.
+  //
+  //putAttachment will also create a folder if you try to put an attachment
+  //to an inexisting foler.
+
+  DropboxStorage.prototype.putAttachment = function (id, name, blob) {
+    id = restrictDocumentId(id);
+    restrictAttachmentId(name);
+
+    return jIO.util.ajax({
+      type: "PUT",
+      url: upload_template.expand({
+        root: this._root,
+        id: id,
+        name: name,
+        access_token: this._access_token
+      }),
+      dataType: blob.type,
+      data: blob
+    });
+  };
+
+  DropboxStorage.prototype.getAttachment = function (id, name) {
+    var that = this;
+
+    id = restrictDocumentId(id);
+    restrictAttachmentId(name);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          type: "GET",
+          dataType: "blob",
+          url: get_template.expand({
+            root: that._root,
+            id: id,
+            name: name,
+            access_token: that._access_token
+          })
+        });
+      })
+      .push(function (evt) {
+        return new Blob(
+          [evt.target.response || evt.target.responseText],
+          {"type": evt.target.getResponseHeader('Content-Type') ||
+            "application/octet-stream"}
+        );
+      }, function (error) {
+        if (error.target !== undefined && error.target.status === 404) {
+          throw new jIO.util.jIOError("Cannot find attachment: " +
+                                      id + ", " + name, 404);
+        }
+        throw error;
+      });
+  };
+
+  //removeAttachment removes also directories.(due to Dropbox API)
+
+  DropboxStorage.prototype.removeAttachment = function (id, name) {
+    var that = this;
+    id = restrictDocumentId(id);
+    restrictAttachmentId(name);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          type: "POST",
+          url: remote_template.expand({
+            access_token: that._access_token,
+            root: that._root,
+            path: id + name
+          })
+        });
+      }).push(undefined, function (error) {
+        if (error.target !== undefined && error.target.status === 404) {
+          throw new jIO.util.jIOError("Cannot find attachment: " +
+                                      id + ", " + name, 404);
+        }
+        throw error;
+      });
+  };
+
+  jIO.addStorage('dropbox', DropboxStorage);
+
+}(jIO, RSVP, Blob, UriTemplate));
+;/*
+ * Copyright 2013, Nexedi SA
+ * Released under the LGPL license.
+ * http://www.gnu.org/licenses/lgpl.html
+ */
+
+/*jslint nomen: true*/
+/*global jIO, RSVP, DOMParser, Blob */
+
+// JIO Dav Storage Description :
+// {
+//   type: "dav",
+//   url: {string},
+//   basic_login: {string} // Basic authentication
+// }
+
+// NOTE: to get the authentication type ->
+// curl --verbose  -X OPTION http://domain/
+// In the headers: "WWW-Authenticate: Basic realm="DAV-upload"
+
+(function (jIO, RSVP, DOMParser, Blob) {
+  "use strict";
+
+  function ajax(storage, options) {
+    if (options === undefined) {
+      options = {};
+    }
+    if (storage._authorization !== undefined) {
+      if (options.headers === undefined) {
+        options.headers = {};
+      }
+      options.headers.Authorization = storage._authorization;
+    }
+
+    if (storage._with_credentials !== undefined) {
+      if (options.xhrFields === undefined) {
+        options.xhrFields = {};
+      }
+      options.xhrFields.withCredentials = storage._with_credentials;
+    }
+//       if (start !== undefined) {
+//         if (end !== undefined) {
+//           headers.Range = "bytes=" + start + "-" + end;
+//         } else {
+//           headers.Range = "bytes=" + start + "-";
+//         }
+//       }
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax(options);
+      });
+  }
+
+  function restrictDocumentId(id) {
+    if (id.indexOf("/") !== 0) {
+      throw new jIO.util.jIOError("id " + id + " is forbidden (no begin /)",
+                                  400);
+    }
+    if (id.lastIndexOf("/") !== (id.length - 1)) {
+      throw new jIO.util.jIOError("id " + id + " is forbidden (no end /)",
+                                  400);
+    }
+    return id;
+  }
+
+  function restrictAttachmentId(id) {
+    if (id.indexOf("/") !== -1) {
+      throw new jIO.util.jIOError("attachment " + id + " is forbidden",
+                                  400);
+    }
+  }
+
+  /**
+   * The JIO WebDAV Storage extension
+   *
+   * @class DavStorage
+   * @constructor
+   */
+  function DavStorage(spec) {
+    if (typeof spec.url !== 'string') {
+      throw new TypeError("DavStorage 'url' is not of type string");
+    }
+    this._url = spec.url;
+    // XXX digest login
+    if (typeof spec.basic_login === 'string') {
+      this._authorization = "Basic " + spec.basic_login;
+    }
+    this._with_credentials = spec.with_credentials;
+  }
+
+  DavStorage.prototype.put = function (id, param) {
+    var that = this;
+    id = restrictDocumentId(id);
+    if (Object.getOwnPropertyNames(param).length > 0) {
+      // Reject if param has some properties
+      throw new jIO.util.jIOError("Can not store properties: " +
+                                  Object.getOwnPropertyNames(param), 400);
+    }
+    return new RSVP.Queue()
+      .push(function () {
+        return ajax(that, {
+          type: "MKCOL",
+          url: that._url + id
+        });
+      })
+      .push(undefined, function (err) {
+        if ((err.target !== undefined) &&
+            (err.target.status === 405)) {
+          return;
+        }
+        throw err;
+      });
+  };
+
+  DavStorage.prototype.remove = function (id) {
+    id = restrictDocumentId(id);
+    return ajax(this, {
+      type: "DELETE",
+      url: this._url + id
+    });
+  };
+
+  DavStorage.prototype.get = function (id) {
+    var context = this;
+    id = restrictDocumentId(id);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return ajax(context, {
+          type: "PROPFIND",
+          url: context._url + id,
+          dataType: "text",
+          headers: {
+            // Increasing this value is a performance killer
+            Depth: "1"
+          }
+        });
+      })
+      .push(function () {
+        return {};
+      }, function (error) {
+        if ((error.target !== undefined) &&
+            (error.target.status === 404)) {
+          throw new jIO.util.jIOError("Cannot find document", 404);
+        }
+        throw error;
+      });
+  };
+
+  DavStorage.prototype.allAttachments = function (id) {
+
+    var context = this;
+    id = restrictDocumentId(id);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return ajax(context, {
+          type: "PROPFIND",
+          url: context._url + id,
+          dataType: "text",
+          headers: {
+            // Increasing this value is a performance killer
+            Depth: "1"
+          }
+        });
+      })
+
+
+      .push(function (response) {
+        // Extract all meta informations and return them to JSON
+
+        var i,
+          attachment = {},
+          id,
+          attachment_list = new DOMParser().parseFromString(
+            response.target.responseText,
+            "text/xml"
+          ).querySelectorAll(
+            "D\\:response, response"
+          );
+
+        // exclude parent folder and browse
+        for (i = 1; i < attachment_list.length; i += 1) {
+          // XXX Only get files for now
+          id = attachment_list[i].querySelector("D\\:href, href").
+            textContent.split('/').slice(-1)[0];
+          // XXX Ugly
+          if ((id !== undefined) && (id !== "")) {
+            attachment[id] = {};
+          }
+        }
+        return attachment;
+
+      }, function (error) {
+        if ((error.target !== undefined) &&
+            (error.target.status === 404)) {
+          throw new jIO.util.jIOError("Cannot find document", 404);
+        }
+        throw error;
+      });
+
+  };
+
+
+  DavStorage.prototype.putAttachment = function (id, name, blob) {
+    var that = this;
+    id = restrictDocumentId(id);
+    restrictAttachmentId(name);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return ajax(that, {
+          type: "PUT",
+          url: that._url + id + name,
+          data: blob
+        });
+      })
+      .push(undefined, function (error) {
+        if (error.target.status === 403 || error.target.status === 424) {
+          throw new jIO.util.jIOError("Cannot access subdocument", 404);
+        }
+        throw error;
+      });
+  };
+
+  DavStorage.prototype.getAttachment = function (id, name) {
+    var context = this;
+    id = restrictDocumentId(id);
+    restrictAttachmentId(name);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return ajax(context, {
+          type: "GET",
+          url: context._url + id + name,
+          dataType: "blob"
+        });
+      })
+      .push(function (response) {
+        return new Blob(
+          [response.target.response || response.target.responseText],
+          {"type": response.target.getResponseHeader('Content-Type') ||
+                   "application/octet-stream"}
+        );
+      }, function (error) {
+        if ((error.target !== undefined) &&
+            (error.target.status === 404)) {
+          throw new jIO.util.jIOError("Cannot find attachment: "
+                                      + id + " , " + name,
+                                      404);
+        }
+        throw error;
+      });
+
+  };
+
+  DavStorage.prototype.removeAttachment = function (id, name) {
+    var context = this;
+    id = restrictDocumentId(id);
+    restrictAttachmentId(name);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return ajax(context, {
+          type: "DELETE",
+          url: context._url + id + name
+        });
+      })
+      .push(undefined, function (error) {
+        if ((error.target !== undefined) &&
+            (error.target.status === 404)) {
+          throw new jIO.util.jIOError("Cannot find attachment: "
+                                      + id + " , " + name,
+                                      404);
+        }
+        throw error;
+      });
+  };
+
+  // JIO COMMANDS //
+
+  // wedDav methods rfc4918 (short summary)
+  // COPY     Reproduces single resources (files) and collections (directory
+  //          trees). Will overwrite files (if specified by request) but will
+  //          respond 209 (Conflict) if it would overwrite a tree
+  // DELETE   deletes files and directory trees
+  // GET      just the vanilla HTTP/1.1 behaviour
+  // HEAD     ditto
+  // LOCK     locks a resources
+  // MKCOL    creates a directory
+  // MOVE     Moves (rename or copy) a file or a directory tree. Will
+  //          'overwrite' files (if specified by the request) but will respond
+  //          209 (Conflict) if it would overwrite a tree.
+  // OPTIONS  If WebDAV is enabled and available for the path this reports the
+  //          WebDAV extension methods
+  // PROPFIND Retrieves the requested file characteristics, DAV lock status
+  //          and 'dead' properties for individual files, a directory and its
+  //          child files, or a directory tree
+  // PROPPATCHset and remove 'dead' meta-data properties
+  // PUT      Update or create resource or collections
+  // UNLOCK   unlocks a resource
+
+  // Notes: all Ajax requests should be CORS (cross-domain)
+  // adding custom headers triggers preflight OPTIONS request!
+  // http://remysharp.com/2011/04/21/getting-cors-working/
+
+  jIO.addStorage('dav', DavStorage);
+
+}(jIO, RSVP, DOMParser, Blob));
+;/*
+ * Copyright 2015, Nexedi SA
+ * Released under the LGPL license.
+ * http://www.gnu.org/licenses/lgpl.html
+ */
+/**
+ * JIO Google Drive Storage. Type = "gdrive".
+ * Google Drive "database" storage.
+ */
+/*global jIO, Blob, RSVP, UriTemplate, JSON*/
+/*jslint nomen: true*/
+
+(function (jIO, Blob, RSVP, UriTemplate, JSON) {
+  "use strict";
+
+  var UPLOAD_URL = "https://www.googleapis.com{/upload}/drive/v2/files{/id}" +
+      "{?uploadType,access_token}",
+    upload_template = UriTemplate.parse(UPLOAD_URL),
+    REMOVE_URL = "https://www.googleapis.com/drive/v2/" +
+      "files{/id,trash}{?access_token}",
+    remove_template = UriTemplate.parse(REMOVE_URL),
+    LIST_URL = "https://www.googleapis.com/drive/v2/files" +
+      "?prettyPrint=false{&pageToken}&q=trashed=false" +
+      "&fields=nextPageToken,items(id){&access_token}",
+    list_template = UriTemplate.parse(LIST_URL),
+    GET_URL = "https://www.googleapis.com/drive/v2/files{/id}{?alt}",
+    get_template = UriTemplate.parse(GET_URL);
+
+  function handleError(error, id) {
+    if (error.target.status === 404) {
+      throw new jIO.util.jIOError(
+        "Cannot find document: " + id,
+        404
+      );
+    }
+    throw error;
+  }
+
+  function listPage(result, token) {
+    var i,
+      obj;
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          "type": "GET",
+          "url": list_template.expand({
+            pageToken : (result.nextPageToken || ""),
+            access_token: token
+          })
+        });
+      })
+      .push(function (data) {
+        obj = JSON.parse(data.target.response || data.target.responseText);
+        for (i = 0; i < obj.items.length; i += 1) {
+          obj.items[i].value = {};
+          result.push(obj.items[i]);
+        }
+        result.nextPageToken = obj.nextPageToken;
+        return result;
+      }, handleError);
+  }
+
+  function checkName(name) {
+    if (name !== "enclosure") {
+      throw new jIO.util.jIOError("Only support 'enclosure' attachment", 400);
+    }
+  }
+
+  /**
+   * The JIO Google Drive Storage extension
+   *
+   * @class GdriveStorage
+   * @constructor
+   */
+  function GdriveStorage(spec) {
+    if (spec === undefined || spec.access_token === undefined ||
+        typeof spec.access_token !== 'string') {
+      throw new TypeError("Access Token must be a string " +
+                          "which contains more than one character.");
+    }
+    if (spec.trashing !== undefined &&
+        (spec.trashing !== true && spec.trashing !== false)) {
+      throw new TypeError("trashing parameter" +
+                          " must be a boolean (true or false)");
+    }
+    this._trashing = spec.trashing || true;
+    this._access_token = spec.access_token;
+    return;
+  }
+
+  function recursiveAllDocs(result, accessToken) {
+    return new RSVP.Queue()
+      .push(function () {
+        return listPage(result, accessToken);
+      })
+      .push(function () {
+        if (result.nextPageToken) {
+          return recursiveAllDocs(result, accessToken);
+        }
+        return result;
+      });
+  }
+
+  GdriveStorage.prototype.hasCapacity = function (name) {
+    return (name === "list");
+  };
+
+  GdriveStorage.prototype.buildQuery = function () {
+    return recursiveAllDocs([], this._access_token);
+  };
+
+  function sendMetaData(id, param, token) {
+    var boundary = "-------314159265358979323846";
+
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          "type": id ? "PUT" : "POST",
+          "url": upload_template.expand({
+            access_token: token,
+            id: id || [],
+            upload: id ? [] : "upload",
+            uploadType: "multipart"
+          }),
+          headers: {
+            "Content-Type" : 'multipart/related; boundary="' + boundary + '"'
+          },
+          data: '--' + boundary + '\n' +
+            'Content-Type: application/json; charset=UTF-8\n\n' +
+            JSON.stringify(param) + '\n\n--' + boundary + "--"
+        });
+      })
+      .push(function (result) {
+        var obj = JSON.parse(result.target.responseText);
+
+        return obj.id;
+      },
+            function (error) {handleError(error, id); });
+  }
+
+  GdriveStorage.prototype.put = function (id, param) {
+    return sendMetaData(id, param, this._access_token);
+  };
+
+  GdriveStorage.prototype.post = function (param) {
+    return sendMetaData(undefined, param, this._access_token);
+  };
+
+  function sendData(id, blob, token) {
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          "type": "PUT",
+          "url": upload_template.expand({
+            access_token: token,
+            upload: "upload",
+            id: id,
+            uploadType: "media"
+          }),
+          data: blob
+        });
+      })
+      .push(function (data) {
+        data = JSON.parse(data.target.responseText);
+        if (data.mimeType === "application/vnd.google-apps.folder") {
+          throw new jIO.util.jIOError("cannot put attachments to folder", 400);
+        }
+        return data;
+      }, function (error) {handleError(error, id); });
+  }
+
+  GdriveStorage.prototype.putAttachment = function (id, name, blob) {
+    checkName(name);
+    return sendData(id, blob, this._access_token);
+  };
+
+  GdriveStorage.prototype.remove = function (id) {
+    var that  = this;
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          type: that._trashing ? "POST" : "DELETE",
+          url: remove_template.expand({
+            id : id,
+            access_token : that._access_token,
+            trash : that._trashing ? "trash" : []
+          })
+        });
+      })
+      .push(undefined, function (error) {handleError(error, id); });
+  };
+
+  function getData(id, attach, token) {
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          type: "GET",
+          dataType: attach ? "blob" : "json",
+          url: get_template.expand({
+            id: id,
+            alt: attach ? "media" : [],
+            access_token: token
+          }),
+          headers: {
+            "Authorization" : "Bearer " + token
+          }
+        });
+      })
+      .push(function (evt) {
+        return evt.target.response ||
+          (attach ? new Blob([evt.target.responseText],
+                             {"type" :
+                              evt.target.responseHeaders["Content-Type"]}) :
+              JSON.parse(evt.target.responseText));
+      }, function (error) {handleError(error, id); });
+  }
+
+  GdriveStorage.prototype.get = function (id) {
+    return getData(id, false, this._access_token);
+  };
+
+  GdriveStorage.prototype.getAttachment = function (id, name) {
+    checkName(name);
+    return getData(id, true, this._access_token);
+  };
+
+  GdriveStorage.prototype.allAttachments = function (id) {
+    var token = this._access_token;
+
+    return new RSVP.Queue()
+      .push(function () {
+        return getData(id, false, token);
+      })
+      .push(function (data) {
+        if (data.mimeType === "application/vnd.google-apps.folder") {
+          return {};
+        }
+        return {"enclosure": {}};
+      });
+  };
+
+  jIO.addStorage('gdrive', GdriveStorage);
+
+}(jIO, Blob, RSVP, UriTemplate, JSON));
+;/*jslint nomen: true */
+/*global RSVP*/
+
+/**
+ * JIO Union Storage. Type = 'union'.
+ * This provide a unified access other multiple storage.
+ * New document are created in the first sub storage.
+ * Document are searched in each sub storage until it is found.
+ * 
+ *
+ * Storage Description:
+ *
+ *     {
+ *       "type": "union",
+ *       "storage_list": [
+ *         sub_storage_description_1,
+ *         sub_storage_description_2,
+ *
+ *         sub_storage_description_X,
+ *       ]
+ *     }
+ *
+ * @class UnionStorage
+ */
+
+(function (jIO, RSVP) {
+  "use strict";
+
+  /**
+   * The JIO UnionStorage extension
+   *
+   * @class UnionStorage
+   * @constructor
+   */
+  function UnionStorage(spec) {
+    if (!Array.isArray(spec.storage_list)) {
+      throw new jIO.util.jIOError("storage_list is not an Array", 400);
+    }
+    var i;
+    this._storage_list = [];
+    for (i = 0; i < spec.storage_list.length; i += 1) {
+      this._storage_list.push(jIO.createJIO(spec.storage_list[i]));
+    }
+  }
+
+  UnionStorage.prototype._getWithStorageIndex = function () {
+    var i,
+      index = 0,
+      context = this,
+      arg = arguments,
+      result = this._storage_list[0].get.apply(this._storage_list[0], arg);
+
+    function handle404(j) {
+      result
+        .push(undefined, function (error) {
+          if ((error instanceof jIO.util.jIOError) &&
+              (error.status_code === 404)) {
+            return context._storage_list[j].get.apply(context._storage_list[j],
+                                                      arg)
+              .push(function (doc) {
+                index = j;
+                return doc;
+              });
+          }
+          throw error;
+        });
+    }
+
+    for (i = 1; i < this._storage_list.length; i += 1) {
+      handle404(i);
+    }
+    return result
+      .push(function (doc) {
+        return [index, doc];
+      });
+  };
+
+  /*
+   * Get a document
+   * Try on each substorage on after the other
+   */
+  UnionStorage.prototype.get = function () {
+    return this._getWithStorageIndex.apply(this, arguments)
+      .push(function (result) {
+        return result[1];
+      });
+  };
+
+  /*
+   * Get attachments list
+   * Try on each substorage on after the other
+   */
+  UnionStorage.prototype.allAttachments = function () {
+    var argument_list = arguments,
+      context = this;
+    return this._getWithStorageIndex.apply(this, arguments)
+      .push(function (result) {
+        var sub_storage = context._storage_list[result[0]];
+        return sub_storage.allAttachments.apply(sub_storage, argument_list);
+      });
+  };
+
+  /*
+   * Post a document
+   * Simply store on the first substorage
+   */
+  UnionStorage.prototype.post = function () {
+    return this._storage_list[0].post.apply(this._storage_list[0], arguments);
+  };
+
+  /*
+   * Put a document
+   * Search the document location, and modify it in its storage.
+   */
+  UnionStorage.prototype.put = function () {
+    var arg = arguments,
+      context = this;
+    return this._getWithStorageIndex(arg[0])
+      .push(undefined, function (error) {
+        if ((error instanceof jIO.util.jIOError) &&
+            (error.status_code === 404)) {
+          // Document does not exist, create in first substorage
+          return [0];
+        }
+        throw error;
+      })
+      .push(function (result) {
+        // Storage found, modify in it directly
+        var sub_storage = context._storage_list[result[0]];
+        return sub_storage.put.apply(sub_storage, arg);
+      });
+  };
+
+  /*
+   * Remove a document
+   * Search the document location, and remove it from its storage.
+   */
+  UnionStorage.prototype.remove = function () {
+    var arg = arguments,
+      context = this;
+    return this._getWithStorageIndex(arg[0])
+      .push(function (result) {
+        // Storage found, remove from it directly
+        var sub_storage = context._storage_list[result[0]];
+        return sub_storage.remove.apply(sub_storage, arg);
+      });
+  };
+
+  UnionStorage.prototype.buildQuery = function () {
+    var promise_list = [],
+      i,
+      id_dict = {},
+      len = this._storage_list.length,
+      sub_storage;
+    for (i = 0; i < len; i += 1) {
+      sub_storage = this._storage_list[i];
+      promise_list.push(sub_storage.buildQuery.apply(sub_storage, arguments));
+    }
+    return new RSVP.Queue()
+      .push(function () {
+        return RSVP.all(promise_list);
+      })
+      .push(function (result_list) {
+        var result = [],
+          sub_result,
+          sub_result_len,
+          j;
+        len = result_list.length;
+        for (i = 0; i < len; i += 1) {
+          sub_result = result_list[i];
+          sub_result_len = sub_result.length;
+          for (j = 0; j < sub_result_len; j += 1) {
+            if (!id_dict.hasOwnProperty(sub_result[j].id)) {
+              id_dict[sub_result[j].id] = null;
+              result.push(sub_result[j]);
+            }
+          }
+        }
+        return result;
+      });
+  };
+
+  UnionStorage.prototype.hasCapacity = function (name) {
+    var i,
+      len,
+      result,
+      sub_storage;
+    if ((name === "list") ||
+            (name === "query") ||
+            (name === "select")) {
+      result = true;
+      len = this._storage_list.length;
+      for (i = 0; i < len; i += 1) {
+        sub_storage = this._storage_list[i];
+        result = result && sub_storage.hasCapacity(name);
+      }
+      return result;
+    }
+    return false;
+  };
+
+  UnionStorage.prototype.repair = function () {
+    var i,
+      promise_list = [];
+    for (i = 0; i < this._storage_list.length; i += 1) {
+      promise_list.push(this._storage_list[i].repair.apply(
+        this._storage_list[i],
+        arguments
+      ));
+    }
+    return RSVP.all(promise_list);
+  };
+
+  UnionStorage.prototype.getAttachment = function () {
+    var argument_list = arguments,
+      context = this;
+    return this._getWithStorageIndex.apply(this, arguments)
+      .push(function (result) {
+        var sub_storage = context._storage_list[result[0]];
+        return sub_storage.getAttachment.apply(sub_storage, argument_list);
+      });
+  };
+
+  UnionStorage.prototype.putAttachment = function () {
+    var argument_list = arguments,
+      context = this;
+    return this._getWithStorageIndex.apply(this, arguments)
+      .push(function (result) {
+        var sub_storage = context._storage_list[result[0]];
+        return sub_storage.putAttachment.apply(sub_storage, argument_list);
+      });
+  };
+
+  UnionStorage.prototype.removeAttachment = function () {
+    var argument_list = arguments,
+      context = this;
+    return this._getWithStorageIndex.apply(this, arguments)
+      .push(function (result) {
+        var sub_storage = context._storage_list[result[0]];
+        return sub_storage.removeAttachment.apply(sub_storage, argument_list);
+      });
+  };
+
+  jIO.addStorage('union', UnionStorage);
+
+}(jIO, RSVP));
+;/*
+ * Copyright 2013, Nexedi SA
+ * Released under the LGPL license.
+ * http://www.gnu.org/licenses/lgpl.html
+ */
+// JIO ERP5 Storage Description :
+// {
+//   type: "erp5"
+//   url: {string}
+// }
+
+/*jslint nomen: true, unparam: true */
+/*global jIO, UriTemplate, FormData, RSVP, URI, Blob,
+         SimpleQuery, ComplexQuery*/
+
+(function (jIO, UriTemplate, FormData, RSVP, URI, Blob,
+           SimpleQuery, ComplexQuery) {
+  "use strict";
+
+  function getSiteDocument(storage) {
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.ajax({
+          "type": "GET",
+          "url": storage._url,
+          "xhrFields": {
+            withCredentials: true
+          }
+        });
+      })
+      .push(function (event) {
+        return JSON.parse(event.target.responseText);
+      });
+  }
+
+  function getDocumentAndHateoas(storage, id, options) {
+    if (options === undefined) {
+      options = {};
+    }
+    return getSiteDocument(storage)
+      .push(function (site_hal) {
+        // XXX need to get modified metadata
+        return new RSVP.Queue()
+          .push(function () {
+            return jIO.util.ajax({
+              "type": "GET",
+              "url": UriTemplate.parse(site_hal._links.traverse.href)
+                                .expand({
+                  relative_url: id,
+                  view: options._view
+                }),
+              "xhrFields": {
+                withCredentials: true
+              }
+            });
+          })
+          .push(undefined, function (error) {
+            if ((error.target !== undefined) &&
+                (error.target.status === 404)) {
+              throw new jIO.util.jIOError("Cannot find document: " + id, 404);
+            }
+            throw error;
+          });
+      });
+  }
+
+  var allowed_field_dict = {
+    "StringField": null,
+    "EmailField": null,
+    "IntegerField": null,
+    "FloatField": null,
+    "TextAreaField": null
+  };
+
+  function extractPropertyFromFormJSON(json) {
+    return new RSVP.Queue()
+      .push(function () {
+        var form = json._embedded._view,
+          converted_json = {
+            portal_type: json._links.type.name
+          },
+          form_data_json = {},
+          field,
+          key,
+          prefix_length,
+          result;
+
+        if (json._links.hasOwnProperty('parent')) {
+          converted_json.parent_relative_url =
+            new URI(json._links.parent.href).segment(2);
+        }
+
+        form_data_json.form_id = {
+          "key": [form.form_id.key],
+          "default": form.form_id["default"]
+        };
+        // XXX How to store datetime
+        for (key in form) {
+          if (form.hasOwnProperty(key)) {
+            field = form[key];
+            prefix_length = 0;
+            if (key.indexOf('my_') === 0 && field.editable) {
+              prefix_length = 3;
+            }
+            if (key.indexOf('your_') === 0) {
+              prefix_length = 5;
+            }
+            if ((prefix_length !== 0) &&
+                (allowed_field_dict.hasOwnProperty(field.type))) {
+              form_data_json[key.substring(prefix_length)] = {
+                "default": field["default"],
+                "key": field.key
+              };
+              converted_json[key.substring(prefix_length)] = field["default"];
+            }
+          }
+        }
+
+        result = {
+          data: converted_json,
+          form_data: form_data_json
+        };
+        if (form.hasOwnProperty('_actions') &&
+            form._actions.hasOwnProperty('put')) {
+          result.action_href = form._actions.put.href;
+        }
+        return result;
+      });
+  }
+
+  function extractPropertyFromForm(context, id) {
+    return context.getAttachment(id, "view")
+      .push(function (blob) {
+        return jIO.util.readBlobAsText(blob);
+      })
+      .push(function (evt) {
+        return JSON.parse(evt.target.result);
+      })
+      .push(function (json) {
+        return extractPropertyFromFormJSON(json);
+      });
+  }
+
+  // XXX docstring
+  function ERP5Storage(spec) {
+    if (typeof spec.url !== "string" || !spec.url) {
+      throw new TypeError("ERP5 'url' must be a string " +
+                          "which contains more than one character.");
+    }
+    this._url = spec.url;
+    this._default_view_reference = spec.default_view_reference;
+  }
+
+  function convertJSONToGet(json) {
+    var key,
+      result = json.data;
+    // Remove all ERP5 hateoas links / convert them into jIO ID
+    for (key in result) {
+      if (result.hasOwnProperty(key)) {
+        if (!result[key]) {
+          delete result[key];
+        }
+      }
+    }
+    return result;
+  }
+
+  ERP5Storage.prototype.get = function (id) {
+    return extractPropertyFromForm(this, id)
+      .push(function (result) {
+        return convertJSONToGet(result);
+      });
+  };
+
+  ERP5Storage.prototype.bulk = function (request_list) {
+    var i,
+      storage = this,
+      bulk_list = [];
+
+
+    for (i = 0; i < request_list.length; i += 1) {
+      if (request_list[i].method !== "get") {
+        throw new Error("ERP5Storage: not supported " +
+                        request_list[i].method + " in bulk");
+      }
+      bulk_list.push({
+        relative_url: request_list[i].parameter_list[0],
+        view: storage._default_view_reference
+      });
+    }
+    return getSiteDocument(storage)
+      .push(function (site_hal) {
+        var form_data = new FormData();
+        form_data.append("bulk_list", JSON.stringify(bulk_list));
+        return jIO.util.ajax({
+          "type": "POST",
+          "url": site_hal._actions.bulk.href,
+          "data": form_data,
+//           "headers": {
+//             "Content-Type": "application/json"
+//           },
+          "xhrFields": {
+            withCredentials: true
+          }
+        });
+      })
+      .push(function (response) {
+        var result_list = [],
+          hateoas = JSON.parse(response.target.responseText);
+
+        function pushResult(json) {
+          return extractPropertyFromFormJSON(json)
+            .push(function (json2) {
+              return convertJSONToGet(json2);
+            });
+        }
+
+        for (i = 0; i < hateoas.result_list.length; i += 1) {
+          result_list.push(pushResult(hateoas.result_list[i]));
+        }
+        return RSVP.all(result_list);
+      });
+  };
+
+  ERP5Storage.prototype.post = function (data) {
+    var context = this,
+      new_id;
+
+    return getSiteDocument(this)
+      .push(function (site_hal) {
+        var form_data = new FormData();
+        form_data.append("portal_type", data.portal_type);
+        form_data.append("parent_relative_url", data.parent_relative_url);
+        return jIO.util.ajax({
+          type: "POST",
+          url: site_hal._actions.add.href,
+          data: form_data,
+          xhrFields: {
+            withCredentials: true
+          }
+        });
+      })
+      .push(function (evt) {
+        var location = evt.target.getResponseHeader("X-Location"),
+          uri = new URI(location);
+        new_id = uri.segment(2);
+        return context.put(new_id, data);
+      })
+      .push(function () {
+        return new_id;
+      });
+  };
+
+  ERP5Storage.prototype.put = function (id, data) {
+    var context = this;
+
+    return extractPropertyFromForm(context, id)
+      .push(function (result) {
+        var key,
+          json = result.form_data,
+          form_data = {};
+        form_data[json.form_id.key] = json.form_id["default"];
+
+        // XXX How to store datetime:!!!!!
+        for (key in data) {
+          if (data.hasOwnProperty(key)) {
+            if (key === "form_id") {
+              throw new jIO.util.jIOError(
+                "ERP5: forbidden property: " + key,
+                400
+              );
+            }
+            if ((key !== "portal_type") && (key !== "parent_relative_url")) {
+              if (!json.hasOwnProperty(key)) {
+                throw new jIO.util.jIOError(
+                  "ERP5: can not store property: " + key,
+                  400
+                );
+              }
+              form_data[json[key].key] = data[key];
+            }
+          }
+        }
+        if (!result.hasOwnProperty('action_href')) {
+          throw new jIO.util.jIOError(
+            "ERP5: can not modify document: " + id,
+            403
+          );
+        }
+        return context.putAttachment(
+          id,
+          result.action_href,
+          new Blob([JSON.stringify(form_data)], {type: "application/json"})
+        );
+      });
+  };
+
+  ERP5Storage.prototype.allAttachments = function (id) {
+    var context = this;
+    return getDocumentAndHateoas(this, id)
+      .push(function () {
+        if (context._default_view_reference === undefined) {
+          return {
+            links: {}
+          };
+        }
+        return {
+          view: {},
+          links: {}
+        };
+      });
+  };
+
+  ERP5Storage.prototype.getAttachment = function (id, action, options) {
+    if (options === undefined) {
+      options = {};
+    }
+    if (action === "view") {
+      if (this._default_view_reference === undefined) {
+        throw new jIO.util.jIOError(
+          "Cannot find attachment view for: " + id,
+          404
+        );
+      }
+      return getDocumentAndHateoas(this, id,
+                                   {"_view": this._default_view_reference})
+        .push(function (response) {
+          var result = JSON.parse(response.target.responseText);
+          // Remove all ERP5 hateoas links / convert them into jIO ID
+
+          // XXX Change default action to an jio urn with attachment name inside
+          // if Base_edit, do put URN
+          // if others, do post URN (ie, unique new attachment name)
+          // XXX Except this attachment name should be generated when
+          return new Blob(
+            [JSON.stringify(result)],
+            {"type": 'application/hal+json'}
+          );
+        });
+    }
+    if (action === "links") {
+      return getDocumentAndHateoas(this, id)
+        .push(function (response) {
+          return new Blob(
+            [JSON.stringify(JSON.parse(response.target.responseText))],
+            {"type": 'application/hal+json'}
+          );
+        });
+    }
+    if (action.indexOf(this._url) === 0) {
+      return new RSVP.Queue()
+        .push(function () {
+          var start,
+            end,
+            range,
+            request_options = {
+              "type": "GET",
+              "dataType": "blob",
+              "url": action,
+              "xhrFields": {
+                withCredentials: true
+              }
+            };
+          if (options.start !== undefined ||  options.end !== undefined) {
+            start = options.start || 0;
+            end = options.end;
+            if (end !== undefined && end < 0) {
+              throw new jIO.util.jIOError("end must be positive",
+                                          400);
+            }
+            if (start < 0) {
+              range = "bytes=" + start;
+            } else if (end === undefined) {
+              range = "bytes=" + start + "-";
+            } else {
+              if (start > end) {
+                throw new jIO.util.jIOError("start is greater than end",
+                                            400);
+              }
+              range = "bytes=" + start + "-" + end;
+            }
+            request_options.headers = {Range: range};
+          }
+          return jIO.util.ajax(request_options);
+        })
+        .push(function (evt) {
+          if (evt.target.response === undefined) {
+            return new Blob(
+              [evt.target.responseText],
+              {"type": evt.target.getResponseHeader("Content-Type")}
+            );
+          }
+          return evt.target.response;
+        });
+    }
+    throw new jIO.util.jIOError("ERP5: not support get attachment: " + action,
+                                400);
+  };
+
+  ERP5Storage.prototype.putAttachment = function (id, name, blob) {
+    // Assert we use a callable on a document from the ERP5 site
+    if (name.indexOf(this._url) !== 0) {
+      throw new jIO.util.jIOError("Can not store outside ERP5: " +
+                                  name, 400);
+    }
+
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.readBlobAsText(blob);
+      })
+      .push(function (evt) {
+        var form_data = JSON.parse(evt.target.result),
+          data = new FormData(),
+          array,
+          i,
+          key,
+          value;
+        for (key in form_data) {
+          if (form_data.hasOwnProperty(key)) {
+            if (Array.isArray(form_data[key])) {
+              array = form_data[key];
+            } else {
+              array = [form_data[key]];
+            }
+            for (i = 0; i < array.length; i += 1) {
+              value = array[i];
+              if (typeof value === "object") {
+                data.append(key, jIO.util.dataURItoBlob(value.url),
+                            value.file_name);
+              } else {
+                data.append(key, value);
+              }
+            }
+          }
+        }
+        return jIO.util.ajax({
+          "type": "POST",
+          "url": name,
+          "data": data,
+          "xhrFields": {
+            withCredentials: true
+          }
+        });
+      });
+  };
+
+  ERP5Storage.prototype.hasCapacity = function (name) {
+    return ((name === "list") || (name === "query") ||
+            (name === "select") || (name === "limit") ||
+            (name === "sort"));
+  };
+
+  function isSingleLocalRoles(parsed_query) {
+    if ((parsed_query instanceof SimpleQuery) &&
+        (parsed_query.key === 'local_roles')) {
+      // local_roles:"Assignee"
+      return parsed_query.value;
+    }
+  }
+
+  function isMultipleLocalRoles(parsed_query) {
+    var i,
+      sub_query,
+      is_multiple = true,
+      local_role_list = [];
+    if ((parsed_query instanceof ComplexQuery) &&
+        (parsed_query.operator === 'OR')) {
+
+      for (i = 0; i < parsed_query.query_list.length; i += 1) {
+        sub_query = parsed_query.query_list[i];
+        if ((sub_query instanceof SimpleQuery) &&
+            (sub_query.key === 'local_roles')) {
+          local_role_list.push(sub_query.value);
+        } else {
+          is_multiple = false;
+        }
+      }
+      if (is_multiple) {
+        // local_roles:"Assignee" OR local_roles:"Assignor"
+        return local_role_list;
+      }
+    }
+  }
+
+  ERP5Storage.prototype.buildQuery = function (options) {
+//     if (typeof options.query !== "string") {
+//       options.query = (options.query ?
+//                        jIO.Query.objectToSearchText(options.query) :
+//                        undefined);
+//     }
+    return getSiteDocument(this)
+      .push(function (site_hal) {
+        var query = options.query,
+          i,
+          parsed_query,
+          sub_query,
+          result_list,
+          local_roles,
+          tmp_list = [];
+        if (options.query) {
+          parsed_query = jIO.QueryFactory.create(options.query);
+
+          result_list = isSingleLocalRoles(parsed_query);
+          if (result_list) {
+            query = undefined;
+            local_roles = result_list;
+          } else {
+
+            result_list = isMultipleLocalRoles(parsed_query);
+            if (result_list) {
+              query = undefined;
+              local_roles = result_list;
+            } else if ((parsed_query instanceof ComplexQuery) &&
+                       (parsed_query.operator === 'AND')) {
+
+              // portal_type:"Person" AND local_roles:"Assignee"
+              for (i = 0; i < parsed_query.query_list.length; i += 1) {
+                sub_query = parsed_query.query_list[i];
+
+                result_list = isSingleLocalRoles(sub_query);
+                if (result_list) {
+                  local_roles = result_list;
+                  parsed_query.query_list.splice(i, 1);
+                  query = jIO.Query.objectToSearchText(parsed_query);
+                  i = parsed_query.query_list.length;
+                } else {
+                  result_list = isMultipleLocalRoles(sub_query);
+                  if (result_list) {
+                    local_roles = result_list;
+                    parsed_query.query_list.splice(i, 1);
+                    query = jIO.Query.objectToSearchText(parsed_query);
+                    i = parsed_query.query_list.length;
+                  }
+                }
+              }
+            }
+
+          }
+        }
+
+        if (options.sort_on) {
+          for (i = 0; i < options.sort_on.length; i += 1) {
+            tmp_list.push(JSON.stringify(options.sort_on[i]));
+          }
+          options.sort_on = tmp_list;
+        }
+
+        return jIO.util.ajax({
+          "type": "GET",
+          "url": UriTemplate.parse(site_hal._links.raw_search.href)
+                            .expand({
+              query: query,
+              // XXX Force erp5 to return embedded document
+              select_list: options.select_list || ["title", "reference"],
+              limit: options.limit,
+              sort_on: options.sort_on,
+              local_roles: local_roles
+            }),
+          "xhrFields": {
+            withCredentials: true
+          }
+        });
+      })
+      .push(function (response) {
+        return JSON.parse(response.target.responseText);
+      })
+      .push(function (catalog_json) {
+        var data = catalog_json._embedded.contents,
+          count = data.length,
+          i,
+          uri,
+          item,
+          result = [];
+        for (i = 0; i < count; i += 1) {
+          item = data[i];
+          uri = new URI(item._links.self.href);
+          delete item._links;
+          result.push({
+            id: uri.segment(2),
+            value: item
+          });
+        }
+        return result;
+      });
+  };
+
+  jIO.addStorage("erp5", ERP5Storage);
+
+}(jIO, UriTemplate, FormData, RSVP, URI, Blob,
+  SimpleQuery, ComplexQuery));
+;/*jslint nomen: true*/
+/*global RSVP*/
+(function (jIO, RSVP) {
+  "use strict";
+
+  /**
+   * The jIO QueryStorage extension
+   *
+   * @class QueryStorage
+   * @constructor
+   */
+  function QueryStorage(spec) {
+    this._sub_storage = jIO.createJIO(spec.sub_storage);
+    this._key_schema = spec.key_schema;
+  }
+
+  QueryStorage.prototype.get = function () {
+    return this._sub_storage.get.apply(this._sub_storage, arguments);
+  };
+  QueryStorage.prototype.allAttachments = function () {
+    return this._sub_storage.allAttachments.apply(this._sub_storage, arguments);
+  };
+  QueryStorage.prototype.post = function () {
+    return this._sub_storage.post.apply(this._sub_storage, arguments);
+  };
+  QueryStorage.prototype.put = function () {
+    return this._sub_storage.put.apply(this._sub_storage, arguments);
+  };
+  QueryStorage.prototype.remove = function () {
+    return this._sub_storage.remove.apply(this._sub_storage, arguments);
+  };
+  QueryStorage.prototype.getAttachment = function () {
+    return this._sub_storage.getAttachment.apply(this._sub_storage, arguments);
+  };
+  QueryStorage.prototype.putAttachment = function () {
+    return this._sub_storage.putAttachment.apply(this._sub_storage, arguments);
+  };
+  QueryStorage.prototype.removeAttachment = function () {
+    return this._sub_storage.removeAttachment.apply(this._sub_storage,
+                                                    arguments);
+  };
+  QueryStorage.prototype.repair = function () {
+    return this._sub_storage.repair.apply(this._sub_storage, arguments);
+  };
+
+  QueryStorage.prototype.hasCapacity = function (name) {
+    var this_storage_capacity_list = ["limit",
+                                      "sort",
+                                      "select",
+                                      "query"];
+
+    if (this_storage_capacity_list.indexOf(name) !== -1) {
+      return true;
+    }
+    if (name === "list") {
+      return this._sub_storage.hasCapacity(name);
+    }
+    return false;
+  };
+  QueryStorage.prototype.buildQuery = function (options) {
+    var substorage = this._sub_storage,
+      context = this,
+      sub_options = {},
+      is_manual_query_needed = false,
+      is_manual_include_needed = false;
+
+    if (substorage.hasCapacity("list")) {
+
+      // Can substorage handle the queries if needed?
+      try {
+        if (((options.query === undefined) ||
+             (substorage.hasCapacity("query"))) &&
+            ((options.sort_on === undefined) ||
+             (substorage.hasCapacity("sort"))) &&
+            ((options.select_list === undefined) ||
+             (substorage.hasCapacity("select"))) &&
+            ((options.limit === undefined) ||
+             (substorage.hasCapacity("limit")))) {
+          sub_options.query = options.query;
+          sub_options.sort_on = options.sort_on;
+          sub_options.select_list = options.select_list;
+          sub_options.limit = options.limit;
+        }
+      } catch (error) {
+        if ((error instanceof jIO.util.jIOError) &&
+            (error.status_code === 501)) {
+          is_manual_query_needed = true;
+        } else {
+          throw error;
+        }
+      }
+
+      // Can substorage include the docs if needed?
+      try {
+        if ((is_manual_query_needed ||
+            (options.include_docs === true)) &&
+            (substorage.hasCapacity("include"))) {
+          sub_options.include_docs = true;
+        }
+      } catch (error) {
+        if ((error instanceof jIO.util.jIOError) &&
+            (error.status_code === 501)) {
+          is_manual_include_needed = true;
+        } else {
+          throw error;
+        }
+      }
+
+      return substorage.buildQuery(sub_options)
+
+        // Include docs if needed
+        .push(function (result) {
+          var include_query_list = [result],
+            len,
+            i;
+
+          function safeGet(j) {
+            var id = result[j].id;
+            return substorage.get(id)
+              .push(function (doc) {
+                // XXX Can delete user data!
+                doc._id = id;
+                return doc;
+              }, function (error) {
+                // Document may have been dropped after listing
+                if ((error instanceof jIO.util.jIOError) &&
+                    (error.status_code === 404)) {
+                  return;
+                }
+                throw error;
+              });
+          }
+
+          if (is_manual_include_needed) {
+            len = result.length;
+            for (i = 0; i < len; i += 1) {
+              include_query_list.push(safeGet(i));
+            }
+            result = RSVP.all(include_query_list);
+          }
+          return result;
+        })
+        .push(function (result) {
+          var original_result,
+            len,
+            i;
+          if (is_manual_include_needed) {
+            original_result = result[0];
+            len = original_result.length;
+            for (i = 0; i < len; i += 1) {
+              original_result[i].doc = result[i + 1];
+            }
+            result = original_result;
+          }
+          return result;
+
+        })
+
+        // Manual query if needed
+        .push(function (result) {
+          var data_rows = [],
+            len,
+            i;
+          if (is_manual_query_needed) {
+            len = result.length;
+            for (i = 0; i < len; i += 1) {
+              result[i].doc.__id = result[i].id;
+              data_rows.push(result[i].doc);
+            }
+            if (options.select_list) {
+              options.select_list.push("__id");
+            }
+            result = jIO.QueryFactory.create(options.query || "",
+                                             context._key_schema).
+              exec(data_rows, options);
+          }
+          return result;
+        })
+
+        // reconstruct filtered rows, preserving the order from docs
+        .push(function (result) {
+          var new_result = [],
+            element,
+            len,
+            i;
+          if (is_manual_query_needed) {
+            len = result.length;
+            for (i = 0; i < len; i += 1) {
+              element = {
+                id: result[i].__id,
+                value: options.select_list ? result[i] : {},
+                doc: {}
+              };
+              if (options.select_list) {
+                // Does not work if user manually request __id
+                delete element.value.__id;
+              }
+              if (options.include_docs) {
+                // XXX To implement
+                throw new Error("QueryStorage does not support include docs");
+              }
+              new_result.push(element);
+            }
+            result = new_result;
+          }
+          return result;
+        });
+
+    }
+  };
+
+  jIO.addStorage('query', QueryStorage);
+
+}(jIO, RSVP));
+;/*jslint nomen: true*/
+/*global RSVP, Blob*/
+(function (jIO, RSVP, Blob) {
+  "use strict";
+
+  /**
+   * The jIO FileSystemBridgeStorage extension
+   *
+   * @class FileSystemBridgeStorage
+   * @constructor
+   */
+  function FileSystemBridgeStorage(spec) {
+    this._sub_storage = jIO.createJIO(spec.sub_storage);
+  }
+  var DOCUMENT_EXTENSION = ".json",
+    DOCUMENT_KEY = "/.jio_documents/",
+    ROOT = "/";
+
+  function endsWith(str, suffix) {
+    return str.indexOf(suffix, str.length - suffix.length) !== -1;
+  }
+
+  FileSystemBridgeStorage.prototype.get = function (id) {
+    var context = this;
+    return new RSVP.Queue()
+
+      // First, try to get explicit reference to the document
+
+      .push(function () {
+        // First get the document itself if it exists
+        return context._sub_storage.getAttachment(
+          DOCUMENT_KEY,
+          id + DOCUMENT_EXTENSION,
+          {format: "json"}
+        );
+      })
+      .push(undefined, function (error) {
+        if ((error instanceof jIO.util.jIOError) &&
+            (error.status_code === 404)) {
+
+          // Second, try to get default attachment
+          return context._sub_storage.allAttachments(ROOT)
+            .push(function (attachment_dict) {
+              if (attachment_dict.hasOwnProperty(id)) {
+                return {};
+              }
+              throw new jIO.util.jIOError("Cannot find document " + id,
+                                          404);
+            });
+        }
+        throw error;
+      });
+  };
+
+  FileSystemBridgeStorage.prototype.allAttachments = function (id) {
+    var context = this;
+    return context._sub_storage.allAttachments(ROOT)
+      .push(function (attachment_dict) {
+        if (attachment_dict.hasOwnProperty(id)) {
+          return {
+            enclosure: {}
+          };
+        }
+        // Second get the document itself if it exists
+        return context._sub_storage.getAttachment(
+          DOCUMENT_KEY,
+          id + DOCUMENT_EXTENSION
+        )
+          .push(function () {
+            return {};
+          }, function (error) {
+            if ((error instanceof jIO.util.jIOError) &&
+                (error.status_code === 404)) {
+              throw new jIO.util.jIOError("Cannot find document " + id,
+                                          404);
+            }
+            throw error;
+          });
+      });
+
+  };
+
+  FileSystemBridgeStorage.prototype.put = function (doc_id, param) {
+    var context = this;
+    // XXX Handle conflict!
+
+    return context._sub_storage.putAttachment(
+      DOCUMENT_KEY,
+      doc_id + DOCUMENT_EXTENSION,
+      new Blob([JSON.stringify(param)], {type: "application/json"})
+    )
+      .push(undefined, function (error) {
+        if ((error instanceof jIO.util.jIOError) &&
+            (error.status_code === 404)) {
+          return context._sub_storage.put(DOCUMENT_KEY, {})
+            .push(function () {
+              return context._sub_storage.putAttachment(
+                DOCUMENT_KEY,
+                doc_id + DOCUMENT_EXTENSION,
+                new Blob([JSON.stringify(param)],
+                         {type: "application/json"})
+              );
+            });
+        }
+        throw error;
+      })
+      .push(function () {
+        return doc_id;
+      });
+
+  };
+
+  FileSystemBridgeStorage.prototype.remove = function (doc_id) {
+    var context = this,
+      got_error = false;
+    return new RSVP.Queue()
+
+      // First, try to remove enclosure
+      .push(function () {
+        return context._sub_storage.removeAttachment(
+          ROOT,
+          doc_id
+        );
+      })
+
+      .push(undefined, function (error) {
+        if ((error instanceof jIO.util.jIOError) &&
+            (error.status_code === 404)) {
+          got_error = true;
+          return;
+        }
+        throw error;
+      })
+
+      // Second, try to remove explicit doc
+      .push(function () {
+        return context._sub_storage.removeAttachment(
+          DOCUMENT_KEY,
+          doc_id + DOCUMENT_EXTENSION
+        );
+      })
+
+      .push(undefined, function (error) {
+        if ((!got_error) && (error instanceof jIO.util.jIOError) &&
+            (error.status_code === 404)) {
+          return doc_id;
+        }
+        throw error;
+      });
+
+  };
+
+  FileSystemBridgeStorage.prototype.hasCapacity = function (capacity) {
+    return (capacity === "list");
+  };
+
+  FileSystemBridgeStorage.prototype.buildQuery = function () {
+    var result_dict = {},
+      context = this;
+    return new RSVP.Queue()
+
+      // First, get list of explicit documents
+
+      .push(function () {
+        return context._sub_storage.allAttachments(DOCUMENT_KEY);
+      })
+      .push(function (result) {
+        var key;
+        for (key in result) {
+          if (result.hasOwnProperty(key)) {
+            if (endsWith(key, DOCUMENT_EXTENSION)) {
+              result_dict[key.substring(
+                0,
+                key.length - DOCUMENT_EXTENSION.length
+              )] = null;
+            }
+          }
+        }
+      }, function (error) {
+        if ((error instanceof jIO.util.jIOError) &&
+            (error.status_code === 404)) {
+          return;
+        }
+        throw error;
+      })
+
+      // Second, get list of enclosure
+
+      .push(function () {
+        return context._sub_storage.allAttachments(ROOT);
+      })
+      .push(function (result) {
+        var key;
+        for (key in result) {
+          if (result.hasOwnProperty(key)) {
+            result_dict[key] = null;
+          }
+        }
+      })
+
+      // Finally, build the result
+
+      .push(function () {
+        var result = [],
+          key;
+        for (key in result_dict) {
+          if (result_dict.hasOwnProperty(key)) {
+            result.push({
+              id: key,
+              value: {}
+            });
+          }
+        }
+        return result;
+      });
+
+  };
+
+  FileSystemBridgeStorage.prototype.getAttachment = function (id, name) {
+    if (name !== "enclosure") {
+      throw new jIO.util.jIOError("Only support 'enclosure' attachment",
+                                  400);
+    }
+
+    return this._sub_storage.getAttachment(ROOT, id);
+  };
+
+  FileSystemBridgeStorage.prototype.putAttachment = function (id, name, blob) {
+    if (name !== "enclosure") {
+      throw new jIO.util.jIOError("Only support 'enclosure' attachment",
+                                  400);
+    }
+
+    return this._sub_storage.putAttachment(
+      ROOT,
+      id,
+      blob
+    );
+  };
+
+  FileSystemBridgeStorage.prototype.removeAttachment = function (id, name) {
+    if (name !== "enclosure") {
+      throw new jIO.util.jIOError("Only support 'enclosure' attachment",
+                                  400);
+    }
+
+    return this._sub_storage.removeAttachment(ROOT, id);
+  };
+
+  FileSystemBridgeStorage.prototype.repair = function () {
+    return this._sub_storage.repair.apply(this._sub_storage, arguments);
+  };
+
+  jIO.addStorage('drivetojiomapping', FileSystemBridgeStorage);
+
+}(jIO, RSVP, Blob));
+;/*jslint nomen: true*/
+/*global Blob, atob, btoa, RSVP*/
+(function (jIO, Blob, atob, btoa, RSVP) {
+  "use strict";
+
+  /**
+   * The jIO DocumentStorage extension
+   *
+   * @class DocumentStorage
+   * @constructor
+   */
+  function DocumentStorage(spec) {
+    this._sub_storage = jIO.createJIO(spec.sub_storage);
+    this._document_id = spec.document_id;
+    this._repair_attachment = spec.repair_attachment || false;
+  }
+
+  var DOCUMENT_EXTENSION = ".json",
+    DOCUMENT_REGEXP = new RegExp("^jio_document/([\\w=]+)" +
+                                 DOCUMENT_EXTENSION + "$"),
+    ATTACHMENT_REGEXP = new RegExp("^jio_attachment/([\\w=]+)/([\\w=]+)$");
+
+  function getSubAttachmentIdFromParam(id, name) {
+    if (name === undefined) {
+      return 'jio_document/' + btoa(id) + DOCUMENT_EXTENSION;
+    }
+    return 'jio_attachment/' + btoa(id) + "/" + btoa(name);
+  }
+
+  DocumentStorage.prototype.get = function (id) {
+    return this._sub_storage.getAttachment(
+      this._document_id,
+      getSubAttachmentIdFromParam(id),
+      {format: "json"}
+    );
+  };
+
+  DocumentStorage.prototype.allAttachments = function (id) {
+    return this._sub_storage.allAttachments(this._document_id)
+      .push(function (result) {
+        var attachments = {},
+          exec,
+          key;
+        for (key in result) {
+          if (result.hasOwnProperty(key)) {
+            if (ATTACHMENT_REGEXP.test(key)) {
+              exec = ATTACHMENT_REGEXP.exec(key);
+              try {
+                if (atob(exec[1]) === id) {
+                  attachments[atob(exec[2])] = {};
+                }
+              } catch (error) {
+                // Check if unable to decode base64 data
+                if (!error instanceof ReferenceError) {
+                  throw error;
+                }
+              }
+            }
+          }
+        }
+        return attachments;
+      });
+  };
+
+  DocumentStorage.prototype.put = function (doc_id, param) {
+    return this._sub_storage.putAttachment(
+      this._document_id,
+      getSubAttachmentIdFromParam(doc_id),
+      new Blob([JSON.stringify(param)], {type: "application/json"})
+    )
+      .push(function () {
+        return doc_id;
+      });
+
+  };
+
+  DocumentStorage.prototype.remove = function (id) {
+    var context = this;
+    return this.allAttachments(id)
+      .push(function (result) {
+        var key,
+          promise_list = [];
+        for (key in result) {
+          if (result.hasOwnProperty(key)) {
+            promise_list.push(context.removeAttachment(id, key));
+          }
+        }
+        return RSVP.all(promise_list);
+      })
+      .push(function () {
+        return context._sub_storage.removeAttachment(
+          context._document_id,
+          getSubAttachmentIdFromParam(id)
+        );
+      })
+      .push(function () {
+        return id;
+      });
+  };
+
+  DocumentStorage.prototype.repair = function () {
+    var context = this;
+    return this._sub_storage.repair.apply(this._sub_storage, arguments)
+      .push(function (result) {
+        if (context._repair_attachment) {
+          return context._sub_storage.allAttachments(context._document_id)
+            .push(function (result_dict) {
+              var promise_list = [],
+                id_dict = {},
+                attachment_dict = {},
+                id,
+                attachment,
+                exec,
+                key;
+              for (key in result_dict) {
+                if (result_dict.hasOwnProperty(key)) {
+                  id = undefined;
+                  attachment = undefined;
+                  if (DOCUMENT_REGEXP.test(key)) {
+                    try {
+                      id = atob(DOCUMENT_REGEXP.exec(key)[1]);
+                    } catch (error) {
+                      // Check if unable to decode base64 data
+                      if (!error instanceof ReferenceError) {
+                        throw error;
+                      }
+                    }
+                    if (id !== undefined) {
+                      id_dict[id] = null;
+                    }
+                  } else if (ATTACHMENT_REGEXP.test(key)) {
+                    exec = ATTACHMENT_REGEXP.exec(key);
+                    try {
+                      id = atob(exec[1]);
+                      attachment = atob(exec[2]);
+                    } catch (error) {
+                      // Check if unable to decode base64 data
+                      if (!error instanceof ReferenceError) {
+                        throw error;
+                      }
+                    }
+                    if (attachment !== undefined) {
+                      if (!id_dict.hasOwnProperty(id)) {
+                        if (!attachment_dict.hasOwnProperty(id)) {
+                          attachment_dict[id] = {};
+                        }
+                        attachment_dict[id][attachment] = null;
+                      }
+                    }
+                  }
+                }
+              }
+              for (id in attachment_dict) {
+                if (attachment_dict.hasOwnProperty(id)) {
+                  if (!id_dict.hasOwnProperty(id)) {
+                    for (attachment in attachment_dict[id]) {
+                      if (attachment_dict[id].hasOwnProperty(attachment)) {
+                        promise_list.push(context.removeAttachment(
+                          id,
+                          attachment
+                        ));
+                      }
+                    }
+                  }
+                }
+              }
+              return RSVP.all(promise_list);
+            });
+        }
+        return result;
+      });
+  };
+
+  DocumentStorage.prototype.hasCapacity = function (capacity) {
+    return (capacity === "list");
+  };
+
+  DocumentStorage.prototype.buildQuery = function () {
+    return this._sub_storage.allAttachments(this._document_id)
+      .push(function (attachment_dict) {
+        var result = [],
+          key;
+        for (key in attachment_dict) {
+          if (attachment_dict.hasOwnProperty(key)) {
+            if (DOCUMENT_REGEXP.test(key)) {
+              try {
+                result.push({
+                  id: atob(DOCUMENT_REGEXP.exec(key)[1]),
+                  value: {}
+                });
+              } catch (error) {
+                // Check if unable to decode base64 data
+                if (!error instanceof ReferenceError) {
+                  throw error;
+                }
+              }
+            }
+          }
+        }
+        return result;
+      });
+  };
+
+  DocumentStorage.prototype.getAttachment = function (id, name) {
+    return this._sub_storage.getAttachment(
+      this._document_id,
+      getSubAttachmentIdFromParam(id, name)
+    );
+  };
+
+  DocumentStorage.prototype.putAttachment = function (id, name, blob) {
+    return this._sub_storage.putAttachment(
+      this._document_id,
+      getSubAttachmentIdFromParam(id, name),
+      blob
+    );
+  };
+
+  DocumentStorage.prototype.removeAttachment = function (id, name) {
+    return this._sub_storage.removeAttachment(
+      this._document_id,
+      getSubAttachmentIdFromParam(id, name)
+    );
+  };
+
+  jIO.addStorage('document', DocumentStorage);
+
+}(jIO, Blob, atob, btoa, RSVP));
+;/*
+ * Copyright 2013, Nexedi SA
+ * Released under the LGPL license.
+ * http://www.gnu.org/licenses/lgpl.html
+ */
+
+/*jslint nomen: true*/
+/*global jIO, sessionStorage, localStorage, RSVP */
+
+/**
+ * JIO Local Storage. Type = 'local'.
+ * Local browser "database" storage.
+ *
+ * Storage Description:
+ *
+ *     {
+ *       "type": "local",
+ *       "sessiononly": false
+ *     }
+ *
+ * @class LocalStorage
+ */
+
+(function (jIO, sessionStorage, localStorage, RSVP) {
+  "use strict";
+
+  function LocalStorage(spec) {
+    if (spec.sessiononly === true) {
+      this._storage = sessionStorage;
+    } else {
+      this._storage = localStorage;
+    }
+  }
+
+  function restrictDocumentId(id) {
+    if (id !== "/") {
+      throw new jIO.util.jIOError("id " + id + " is forbidden (!== /)",
+                                  400);
+    }
+  }
+
+  LocalStorage.prototype.get = function (id) {
+    restrictDocumentId(id);
+    return {};
+  };
+
+  LocalStorage.prototype.allAttachments = function (id) {
+    restrictDocumentId(id);
+
+    var attachments = {},
+      key;
+
+    for (key in this._storage) {
+      if (this._storage.hasOwnProperty(key)) {
+        attachments[key] = {};
+      }
+    }
+    return attachments;
+  };
+
+  LocalStorage.prototype.getAttachment = function (id, name) {
+    restrictDocumentId(id);
+
+    var textstring = this._storage.getItem(name);
+
+    if (textstring === null) {
+      throw new jIO.util.jIOError(
+        "Cannot find attachment " + name,
+        404
+      );
+    }
+    return jIO.util.dataURItoBlob(textstring);
+  };
+
+  LocalStorage.prototype.putAttachment = function (id, name, blob) {
+    var context = this;
+    restrictDocumentId(id);
+
+    // the document already exists
+    // download data
+    return new RSVP.Queue()
+      .push(function () {
+        return jIO.util.readBlobAsDataURL(blob);
+      })
+      .push(function (e) {
+        context._storage.setItem(name, e.target.result);
+      });
+  };
+
+  LocalStorage.prototype.removeAttachment = function (id, name) {
+    restrictDocumentId(id);
+    return this._storage.removeItem(name);
+  };
+
+
+  LocalStorage.prototype.hasCapacity = function (name) {
+    return (name === "list");
+  };
+
+  LocalStorage.prototype.buildQuery = function () {
+    return [{
+      id: "/",
+      value: {}
+    }];
+  };
+
+  jIO.addStorage('local', LocalStorage);
+
+}(jIO, sessionStorage, localStorage, RSVP));
+;/*
+ * Copyright 2014, Nexedi SA
+ * Released under the LGPL license.
+ * http://www.gnu.org/licenses/lgpl.html
+ */
+
+/**
+ * JIO Indexed Database Storage.
+ *
+ * A local browser "database" storage greatly more powerful than localStorage.
+ *
+ * Description:
+ *
+ *    {
+ *      "type": "indexeddb",
+ *      "database": <string>
+ *    }
+ *
+ * The database name will be prefixed by "jio:", so if the database property is
+ * "hello", then you can manually reach this database with
+ * `indexedDB.open("jio:hello");`. (Or
+ * `indexedDB.deleteDatabase("jio:hello");`.)
+ *
+ * For more informations:
+ *
+ * - http://www.w3.org/TR/IndexedDB/
+ * - https://developer.mozilla.org/en-US/docs/IndexedDB/Using_IndexedDB
+ */
+
+/*jslint nomen: true */
+/*global indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange*/
+
+(function (indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange) {
+  "use strict";
+
+  // Read only as changing it can lead to data corruption
+  var UNITE = 2000000;
+
+  function IndexedDBStorage(description) {
+    if (typeof description.database !== "string" ||
+        description.database === "") {
+      throw new TypeError("IndexedDBStorage 'database' description property " +
+                          "must be a non-empty string");
+    }
+    this._database_name = "jio:" + description.database;
+  }
+
+  IndexedDBStorage.prototype.hasCapacity = function (name) {
+    return ((name === "list") || (name === "include"));
+  };
+
+  function buildKeyPath(key_list) {
+    return key_list.join("_");
+  }
+
+  function handleUpgradeNeeded(evt) {
+    var db = evt.target.result,
+      store;
+
+    store = db.createObjectStore("metadata", {
+      keyPath: "_id",
+      autoIncrement: false
+    });
+    // It is not possible to use openKeyCursor on keypath directly
+    // https://www.w3.org/Bugs/Public/show_bug.cgi?id=19955
+    store.createIndex("_id", "_id", {unique: true});
+
+    store = db.createObjectStore("attachment", {
+      keyPath: "_key_path",
+      autoIncrement: false
+    });
+    store.createIndex("_id", "_id", {unique: false});
+
+    store = db.createObjectStore("blob", {
+      keyPath: "_key_path",
+      autoIncrement: false
+    });
+    store.createIndex("_id_attachment",
+                      ["_id", "_attachment"], {unique: false});
+    store.createIndex("_id", "_id", {unique: false});
+  }
+
+  function openIndexedDB(jio_storage) {
+    var db_name = jio_storage._database_name;
+    function resolver(resolve, reject) {
+      // Open DB //
+      var request = indexedDB.open(db_name);
+      request.onerror = function (error) {
+        if (request.result) {
+          request.result.close();
+        }
+        reject(error);
+      };
+
+      request.onabort = function () {
+        request.result.close();
+        reject("Aborting connection to: " + db_name);
+      };
+
+      request.ontimeout = function () {
+        request.result.close();
+        reject("Connection to: " + db_name + " timeout");
+      };
+
+      request.onblocked = function () {
+        request.result.close();
+        reject("Connection to: " + db_name + " was blocked");
+      };
+
+      // Create DB if necessary //
+      request.onupgradeneeded = handleUpgradeNeeded;
+
+      request.onversionchange = function () {
+        request.result.close();
+        reject(db_name + " was upgraded");
+      };
+
+      request.onsuccess = function () {
+        resolve(request.result);
+      };
+    }
+    // XXX Canceller???
+    return new RSVP.Queue()
+      .push(function () {
+        return new RSVP.Promise(resolver);
+      });
+  }
+
+  function openTransaction(db, stores, flag, autoclosedb) {
+    var tx = db.transaction(stores, flag);
+    if (autoclosedb !== false) {
+      tx.oncomplete = function () {
+        db.close();
+      };
+    }
+    tx.onabort = function () {
+      db.close();
+    };
+    return tx;
+  }
+
+  function handleCursor(request, callback) {
+    function resolver(resolve, reject) {
+      // Open DB //
+      request.onerror = function (error) {
+        if (request.transaction) {
+          request.transaction.abort();
+        }
+        reject(error);
+      };
+
+      request.onsuccess = function (evt) {
+        var cursor = evt.target.result;
+        if (cursor) {
+          // XXX Wait for result
+          try {
+            callback(cursor);
+          } catch (error) {
+            reject(error);
+          }
+
+          // continue to next iteration
+          cursor["continue"]();
+        } else {
+          resolve();
+        }
+      };
+    }
+    // XXX Canceller???
+    return new RSVP.Promise(resolver);
+  }
+
+  IndexedDBStorage.prototype.buildQuery = function (options) {
+    var result_list = [];
+
+    function pushIncludedMetadata(cursor) {
+      result_list.push({
+        "id": cursor.key,
+        "value": {},
+        "doc": cursor.value.doc
+      });
+    }
+
+    function pushMetadata(cursor) {
+      result_list.push({
+        "id": cursor.key,
+        "value": {}
+      });
+    }
+    return openIndexedDB(this)
+      .push(function (db) {
+        var tx = openTransaction(db, ["metadata"], "readonly");
+        if (options.include_docs === true) {
+          return handleCursor(tx.objectStore("metadata").index("_id")
+                              .openCursor(), pushIncludedMetadata);
+        }
+        return handleCursor(tx.objectStore("metadata").index("_id")
+                            .openKeyCursor(), pushMetadata);
+      })
+      .push(function () {
+        return result_list;
+      });
+
+  };
+
+  function handleGet(request) {
+    function resolver(resolve, reject) {
+      request.onerror = reject;
+      request.onsuccess = function () {
+        if (request.result) {
+          resolve(request.result);
+        }
+        // XXX How to get ID
+        reject(new jIO.util.jIOError("Cannot find document", 404));
+      };
+    }
+    return new RSVP.Promise(resolver);
+  }
+
+  IndexedDBStorage.prototype.get = function (id) {
+    return openIndexedDB(this)
+      .push(function (db) {
+        var transaction = openTransaction(db, ["metadata"],
+                                          "readonly");
+        return handleGet(transaction.objectStore("metadata").get(id));
+      })
+      .push(function (result) {
+        return result.doc;
+      });
+  };
+
+  IndexedDBStorage.prototype.allAttachments = function (id) {
+    var attachment_dict = {};
+
+    function addEntry(cursor) {
+      attachment_dict[cursor.value._attachment] = {};
+    }
+
+    return openIndexedDB(this)
+      .push(function (db) {
+        var transaction = openTransaction(db, ["metadata", "attachment"],
+                                          "readonly");
+        return RSVP.all([
+          handleGet(transaction.objectStore("metadata").get(id)),
+          handleCursor(transaction.objectStore("attachment").index("_id")
+                       .openCursor(IDBKeyRange.only(id)), addEntry)
+        ]);
+      })
+      .push(function () {
+        return attachment_dict;
+      });
+  };
+
+  function handleRequest(request) {
+    function resolver(resolve, reject) {
+      request.onerror = reject;
+      request.onsuccess = function () {
+        resolve(request.result);
+      };
+    }
+    return new RSVP.Promise(resolver);
+  }
+
+  IndexedDBStorage.prototype.put = function (id, metadata) {
+    return openIndexedDB(this)
+      .push(function (db) {
+        var transaction = openTransaction(db, ["metadata"], "readwrite");
+        return handleRequest(transaction.objectStore("metadata").put({
+          "_id": id,
+          "doc": metadata
+        }));
+      });
+  };
+
+  function deleteEntry(cursor) {
+    cursor["delete"]();
+  }
+
+  IndexedDBStorage.prototype.remove = function (id) {
+    return openIndexedDB(this)
+      .push(function (db) {
+        var transaction = openTransaction(db, ["metadata", "attachment",
+                                          "blob"], "readwrite");
+        return RSVP.all([
+          handleRequest(transaction
+                        .objectStore("metadata")["delete"](id)),
+          // XXX Why not possible to delete with KeyCursor?
+          handleCursor(transaction.objectStore("attachment").index("_id")
+                       .openCursor(IDBKeyRange.only(id)), deleteEntry),
+          handleCursor(transaction.objectStore("blob").index("_id")
+                       .openCursor(IDBKeyRange.only(id)), deleteEntry)
+        ]);
+      });
+  };
+
+  IndexedDBStorage.prototype.getAttachment = function (id, name, options) {
+    var transaction,
+      type,
+      start,
+      end;
+    if (options === undefined) {
+      options = {};
+    }
+    return openIndexedDB(this)
+      .push(function (db) {
+        transaction = openTransaction(db, ["attachment", "blob"], "readonly");
+        // XXX Should raise if key is not good
+        return handleGet(transaction.objectStore("attachment")
+                         .get(buildKeyPath([id, name])));
+      })
+      .push(function (attachment) {
+        var total_length = attachment.info.length,
+          i,
+          promise_list = [],
+          store = transaction.objectStore("blob"),
+          start_index,
+          end_index;
+
+        type = attachment.info.content_type;
+        start = options.start || 0;
+        end = options.end || total_length;
+        if (end > total_length) {
+          end = total_length;
+        }
+
+        if (start < 0 || end < 0) {
+          throw new jIO.util.jIOError("_start and _end must be positive",
+                                      400);
+        }
+        if (start > end) {
+          throw new jIO.util.jIOError("_start is greater than _end",
+                                      400);
+        }
+
+        start_index = Math.floor(start / UNITE);
+        end_index =  Math.floor(end / UNITE);
+        if (end % UNITE === 0) {
+          end_index -= 1;
+        }
+
+        for (i = start_index; i <= end_index; i += 1) {
+          promise_list.push(
+            handleGet(store.get(buildKeyPath([id,
+                                name, i])))
+          );
+        }
+        return RSVP.all(promise_list);
+      })
+      .push(function (result_list) {
+        var array_buffer_list = [],
+          blob,
+          i,
+          index,
+          len = result_list.length;
+        for (i = 0; i < len; i += 1) {
+          array_buffer_list.push(result_list[i].blob);
+        }
+        if ((options.start === undefined) && (options.end === undefined)) {
+          return new Blob(array_buffer_list, {type: type});
+        }
+        index = Math.floor(start / UNITE) * UNITE;
+        blob = new Blob(array_buffer_list, {type: "application/octet-stream"});
+        return blob.slice(start - index, end - index,
+                          "application/octet-stream");
+      });
+  };
+
+  function removeAttachment(transaction, id, name) {
+    return RSVP.all([
+      // XXX How to get the right attachment
+      handleRequest(transaction.objectStore("attachment")["delete"](
+        buildKeyPath([id, name])
+      )),
+      handleCursor(transaction.objectStore("blob").index("_id_attachment")
+                   .openCursor(IDBKeyRange.only(
+          [id, name]
+        )),
+          deleteEntry
+        )
+    ]);
+  }
+
+  IndexedDBStorage.prototype.putAttachment = function (id, name, blob) {
+    var blob_part = [],
+      transaction,
+      db;
+
+    return openIndexedDB(this)
+      .push(function (database) {
+        db = database;
+
+        // Split the blob first
+        return jIO.util.readBlobAsArrayBuffer(blob);
+      })
+      .push(function (event) {
+        var array_buffer = event.target.result,
+          total_size = blob.size,
+          handled_size = 0;
+
+        while (handled_size < total_size) {
+          blob_part.push(array_buffer.slice(handled_size,
+                                            handled_size + UNITE));
+          handled_size += UNITE;
+        }
+
+        // Remove previous attachment
+        transaction = openTransaction(db, ["attachment", "blob"], "readwrite");
+        return removeAttachment(transaction, id, name);
+      })
+      .push(function () {
+
+        var promise_list = [
+            handleRequest(transaction.objectStore("attachment").put({
+              "_key_path": buildKeyPath([id, name]),
+              "_id": id,
+              "_attachment": name,
+              "info": {
+                "content_type": blob.type,
+                "length": blob.size
+              }
+            }))
+          ],
+          len = blob_part.length,
+          blob_store = transaction.objectStore("blob"),
+          i;
+        for (i = 0; i < len; i += 1) {
+          promise_list.push(
+            handleRequest(blob_store.put({
+              "_key_path": buildKeyPath([id, name,
+                                         i]),
+              "_id" : id,
+              "_attachment" : name,
+              "_part" : i,
+              "blob": blob_part[i]
+            }))
+          );
+        }
+        // Store all new data
+        return RSVP.all(promise_list);
+      });
+  };
+
+  IndexedDBStorage.prototype.removeAttachment = function (id, name) {
+    return openIndexedDB(this)
+      .push(function (db) {
+        var transaction = openTransaction(db, ["attachment", "blob"],
+                                          "readwrite");
+        return removeAttachment(transaction, id, name);
+      });
+  };
+
+  jIO.addStorage("indexeddb", IndexedDBStorage);
+}(indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange));
+;/*
+ * Copyright 2015, Nexedi SA
+ * Released under the LGPL license.
+ * http://www.gnu.org/licenses/lgpl.html
+ */
+
+/*jslint nomen: true*/
+/*global jIO, RSVP, DOMException, Blob, crypto, Uint8Array, ArrayBuffer*/
+
+(function (jIO, RSVP, DOMException, Blob, crypto, Uint8Array, ArrayBuffer) {
+  "use strict";
+
+
+  // you the cryptography system used by this storage is AES-GCM.
+  // here is an example of how to generate a key to the json format.
+
+  // var key,
+  //     jsonKey;
+  // crypto.subtle.generateKey({name: "AES-GCM",length: 256},
+  //                           (true), ["encrypt", "decrypt"])
+  // .then(function(res){key = res;});
+  //
+  // window.crypto.subtle.exportKey("jwk", key)
+  // .then(function(res){jsonKey = val})
+  //
+  //var storage = jIO.createJIO({type: "crypt", key: jsonKey,
+  //                             sub_storage: {...}});
+
+  // find more informations about this cryptography system on
+  // https://github.com/diafygi/webcrypto-examples#aes-gcm
+
+  /**
+   * The JIO Cryptography Storage extension
+   *
+   * @class CryptStorage
+   * @constructor
+   */
+
+  var MIME_TYPE = "application/x-jio-aes-gcm-encryption";
+
+  function CryptStorage(spec) {
+    this._key = spec.key;
+    this._jsonKey = true;
+    this._sub_storage = jIO.createJIO(spec.sub_storage);
+  }
+
+  function convertKey(that) {
+    return new RSVP.Queue()
+      .push(function () {
+        return crypto.subtle.importKey("jwk", that._key,
+                                       "AES-GCM", false,
+                                       ["encrypt", "decrypt"]);
+      })
+      .push(function (res) {
+        that._key = res;
+        that._jsonKey = false;
+        return;
+      });
+  }
+
+  CryptStorage.prototype.get = function () {
+    return this._sub_storage.get.apply(this._sub_storage,
+                                       arguments);
+  };
+
+  CryptStorage.prototype.post = function () {
+    return this._sub_storage.post.apply(this._sub_storage,
+                                        arguments);
+  };
+
+  CryptStorage.prototype.put = function () {
+    return this._sub_storage.put.apply(this._sub_storage,
+                                       arguments);
+  };
+
+  CryptStorage.prototype.remove = function () {
+    return this._sub_storage.remove.apply(this._sub_storage,
+                                          arguments);
+  };
+
+  CryptStorage.prototype.hasCapacity = function () {
+    return this._sub_storage.hasCapacity.apply(this._sub_storage,
+                                               arguments);
+  };
+
+  CryptStorage.prototype.buildQuery = function () {
+    return this._sub_storage.buildQuery.apply(this._sub_storage,
+                                              arguments);
+  };
+
+
+  CryptStorage.prototype.putAttachment = function (id, name, blob) {
+    var initializaton_vector = crypto.getRandomValues(new Uint8Array(12)),
+      that = this;
+
+    return new RSVP.Queue()
+      .push(function () {
+        if (that._jsonKey === true) {
+          return convertKey(that);
+        }
+        return;
+      })
+      .push(function () {
+        return jIO.util.readBlobAsDataURL(blob);
+      })
+      .push(function (dataURL) {
+        //string->arraybuffer
+        var strLen = dataURL.currentTarget.result.length,
+          buf = new ArrayBuffer(strLen),
+          bufView = new Uint8Array(buf),
+          i;
+
+        dataURL = dataURL.currentTarget.result;
+        for (i = 0; i < strLen; i += 1) {
+          bufView[i] = dataURL.charCodeAt(i);
+        }
+        return crypto.subtle.encrypt({
+          name : "AES-GCM",
+          iv : initializaton_vector
+        },
+                                     that._key, buf);
+      })
+      .push(function (coded) {
+        var blob = new Blob([initializaton_vector, coded], {type: MIME_TYPE});
+        return that._sub_storage.putAttachment(id, name, blob);
+      });
+  };
+
+  CryptStorage.prototype.getAttachment = function (id, name) {
+    var that = this;
+
+    return that._sub_storage.getAttachment(id, name)
+      .push(function (blob) {
+        if (blob.type !== MIME_TYPE) {
+          return blob;
+        }
+        return new RSVP.Queue()
+          .push(function () {
+            if (that._jsonKey === true) {
+              return convertKey(that);
+            }
+            return;
+          })
+          .push(function () {
+            return jIO.util.readBlobAsArrayBuffer(blob);
+          })
+          .push(function (coded) {
+            var initializaton_vector;
+
+            coded = coded.currentTarget.result;
+            initializaton_vector = new Uint8Array(coded.slice(0, 12));
+            return new RSVP.Queue()
+              .push(function () {
+                return crypto.subtle.decrypt({
+                  name : "AES-GCM",
+                  iv : initializaton_vector
+                },
+                                             that._key, coded.slice(12));
+              })
+              .push(function (arr) {
+                //arraybuffer->string
+                arr = String.fromCharCode.apply(null, new Uint8Array(arr));
+                return jIO.util.dataURItoBlob(arr);
+              })
+              .push(undefined, function (error) {
+                if (error instanceof DOMException) {
+                  return blob;
+                }
+                throw error;
+              });
+          });
+      });
+  };
+
+  CryptStorage.prototype.removeAttachment = function () {
+    return this._sub_storage.removeAttachment.apply(this._sub_storage,
+                                                    arguments);
+  };
+
+  CryptStorage.prototype.allAttachments = function () {
+    return this._sub_storage.allAttachments.apply(this._sub_storage,
+                                                  arguments);
+  };
+
+  jIO.addStorage('crypt', CryptStorage);
+
+}(jIO, RSVP, DOMException, Blob, crypto, Uint8Array, ArrayBuffer));
+;/*
+ * Copyright 2013, Nexedi SA
+ * Released under the LGPL license.
+ * http://www.gnu.org/licenses/lgpl.html
+ */
+/**
+ * JIO Websql Storage. Type = "websql".
+ * websql "database" storage.
+ */
+/*global Blob, jIO, RSVP, openDatabase*/
+/*jslint nomen: true*/
+
+(function (jIO, RSVP, Blob, openDatabase) {
+
+  "use strict";
+
+  /**
+   * The JIO Websql Storage extension
+   *
+   * @class WebSQLStorage
+   * @constructor
+   */
+
+  function queueSql(db, query_list, argument_list) {
+    return new RSVP.Promise(function (resolve, reject) {
+      /*jslint unparam: true*/
+      db.transaction(function (tx) {
+        var len = query_list.length,
+          result_list = [],
+          i;
+
+        function resolveTransaction(tx, result) {
+          result_list.push(result);
+          if (result_list.length === len) {
+            resolve(result_list);
+          }
+        }
+        function rejectTransaction(tx, error) {
+          reject(error);
+          return true;
+        }
+        for (i = 0; i < len; i += 1) {
+          tx.executeSql(query_list[i], argument_list[i], resolveTransaction,
+                        rejectTransaction);
+        }
+      }, function (tx, error) {
+        reject(error);
+      });
+      /*jslint unparam: false*/
+    });
+  }
+
+  function initDatabase(db) {
+    var query_list = [
+      "CREATE TABLE IF NOT EXISTS document" +
+        "(id VARCHAR PRIMARY KEY NOT NULL, data TEXT)",
+      "CREATE TABLE IF NOT EXISTS attachment" +
+        "(id VARCHAR, attachment VARCHAR, part INT, blob TEXT)",
+      "CREATE TRIGGER IF NOT EXISTS removeAttachment " +
+        "BEFORE DELETE ON document FOR EACH ROW " +
+        "BEGIN DELETE from attachment WHERE id = OLD.id;END;",
+      "CREATE INDEX IF NOT EXISTS index_document ON document (id);",
+      "CREATE INDEX IF NOT EXISTS index_attachment " +
+        "ON attachment (id, attachment);"
+    ];
+    return new RSVP.Queue()
+      .push(function () {
+        return queueSql(db, query_list, []);
+      });
+  }
+
+  function WebSQLStorage(spec) {
+    if (typeof spec.database !== 'string' || !spec.database) {
+      throw new TypeError("database must be a string " +
+                          "which contains more than one character.");
+    }
+    this._database = openDatabase("jio:" + spec.database,
+                                  '1.0', '', 2 * 1024 * 1024);
+    if (spec.blob_length &&
+        (typeof spec.blob_length !== "number" ||
+         spec.blob_length < 20)) {
+      throw new TypeError("blob_len parameter must be a number >= 20");
+    }
+    this._blob_length = spec.blob_length || 2000000;
+    this._init_db_promise = initDatabase(this._database);
+  }
+
+  WebSQLStorage.prototype.put = function (id, param) {
+    var db = this._database,
+      that = this,
+      data_string = JSON.stringify(param);
+
+    return new RSVP.Queue()
+      .push(function () {
+        return that._init_db_promise;
+      })
+      .push(function () {
+        return queueSql(db, ["INSERT OR REPLACE INTO " +
+                            "document(id, data) VALUES(?,?)"],
+                       [[id, data_string]]);
+      })
+      .push(function () {
+        return id;
+      });
+  };
+
+  WebSQLStorage.prototype.remove = function (id) {
+    var db = this._database,
+      that = this;
+
+    return new RSVP.Queue()
+      .push(function () {
+        return that._init_db_promise;
+      })
+      .push(function () {
+        return queueSql(db, ["DELETE FROM document WHERE id = ?"], [[id]]);
+      })
+      .push(function (result_list) {
+        if (result_list[0].rowsAffected === 0) {
+          throw new jIO.util.jIOError("Cannot find document", 404);
+        }
+        return id;
+      });
+
+  };
+
+  WebSQLStorage.prototype.get = function (id) {
+    var db = this._database,
+      that = this;
+
+    return new RSVP.Queue()
+      .push(function () {
+        return that._init_db_promise;
+      })
+      .push(function () {
+        return queueSql(db, ["SELECT data FROM document WHERE id = ?"],
+                        [[id]]);
+      })
+      .push(function (result_list) {
+        if (result_list[0].rows.length === 0) {
+          throw new jIO.util.jIOError("Cannot find document", 404);
+        }
+        return JSON.parse(result_list[0].rows[0].data);
+      });
+  };
+
+  WebSQLStorage.prototype.allAttachments = function (id) {
+    var db = this._database,
+      that = this;
+
+    return new RSVP.Queue()
+      .push(function () {
+        return that._init_db_promise;
+      })
+      .push(function () {
+        return queueSql(db, [
+          "SELECT id FROM document WHERE id = ?",
+          "SELECT DISTINCT attachment FROM attachment WHERE id = ?"
+        ], [[id], [id]]);
+      })
+      .push(function (result_list) {
+        if (result_list[0].rows.length === 0) {
+          throw new jIO.util.jIOError("Cannot find document", 404);
+        }
+
+        var len = result_list[1].rows.length,
+          obj = {},
+          i;
+
+        for (i = 0; i < len; i += 1) {
+          obj[result_list[1].rows[i].attachment] = {};
+        }
+        return obj;
+      });
+  };
+
+  function sendBlobPart(blob, argument_list, index, queue) {
+    queue.push(function () {
+      return jIO.util.readBlobAsDataURL(blob);
+    })
+      .push(function (strBlob) {
+        argument_list[index + 2].push(strBlob.currentTarget.result);
+        return;
+      });
+  }
+
+  WebSQLStorage.prototype.putAttachment = function (id, name, blob) {
+    var db = this._database,
+      that = this,
+      part_size = this._blob_length;
+
+    return new RSVP.Queue()
+      .push(function () {
+        return that._init_db_promise;
+      })
+      .push(function () {
+        return queueSql(db, ["SELECT id FROM document WHERE id = ?"], [[id]]);
+      })
+      .push(function (result) {
+        var query_list = [],
+          argument_list = [],
+          blob_size = blob.size,
+          queue = new RSVP.Queue(),
+          i,
+          index;
+
+        if (result[0].rows.length === 0) {
+          throw new jIO.util.jIOError("Cannot access subdocument", 404);
+        }
+        query_list.push("DELETE FROM attachment WHERE id = ? " +
+                        "AND attachment = ?");
+        argument_list.push([id, name]);
+        query_list.push("INSERT INTO attachment(id, attachment, part, blob)" +
+                     "VALUES(?, ?, ?, ?)");
+        argument_list.push([id, name, -1,
+                            blob.type || "application/octet-stream"]);
+
+        for (i = 0, index = 0; i < blob_size; i += part_size, index += 1) {
+          query_list.push("INSERT INTO attachment(id, attachment, part, blob)" +
+                       "VALUES(?, ?, ?, ?)");
+          argument_list.push([id, name, index]);
+          sendBlobPart(blob.slice(i, i + part_size), argument_list, index,
+                       queue);
+        }
+        queue.push(function () {
+          return queueSql(db, query_list, argument_list);
+        });
+        return queue;
+      });
+  };
+
+  WebSQLStorage.prototype.getAttachment = function (id, name, options) {
+    var db = this._database,
+      that = this,
+      part_size = this._blob_length,
+      start,
+      end,
+      start_index,
+      end_index;
+
+    if (options === undefined) { options = {}; }
+    start = options.start || 0;
+    end = options.end || -1;
+
+    if (start < 0 || (options.end !== undefined && options.end < 0)) {
+      throw new jIO.util.jIOError("_start and _end must be positive",
+                                  400);
+    }
+    if (start > end && end !== -1) {
+      throw new jIO.util.jIOError("_start is greater than _end",
+                                  400);
+    }
+
+    start_index = Math.floor(start / part_size);
+    if (start === 0) { start_index -= 1; }
+    end_index =  Math.floor(end / part_size);
+    if (end % part_size === 0) {
+      end_index -= 1;
+    }
+
+    return new RSVP.Queue()
+      .push(function () {
+        return that._init_db_promise;
+      })
+      .push(function () {
+        var command = "SELECT part, blob FROM attachment WHERE id = ? AND " +
+          "attachment = ? AND part >= ?",
+          argument_list = [id, name, start_index];
+
+        if (end !== -1) {
+          command += " AND part <= ?";
+          argument_list.push(end_index);
+        }
+        return queueSql(db, [command], [argument_list]);
+      })
+      .push(function (response_list) {
+        var i,
+          response,
+          blob_array = [],
+          blob,
+          type;
+
+        response = response_list[0].rows;
+        if (response.length === 0) {
+          throw new jIO.util.jIOError("Cannot find document", 404);
+        }
+        for (i = 0; i < response.length; i += 1) {
+          if (response[i].part === -1) {
+            type = response[i].blob;
+            start_index += 1;
+          } else {
+            blob_array.push(jIO.util.dataURItoBlob(response[i].blob));
+          }
+        }
+        if ((start === 0) && (options.end === undefined)) {
+          return new Blob(blob_array, {type: type});
+        }
+        blob = new Blob(blob_array, {});
+        return blob.slice(start - (start_index * part_size),
+                          end === -1 ? blob.size :
+                          end - (start_index * part_size),
+                          "application/octet-stream");
+      });
+  };
+
+  WebSQLStorage.prototype.removeAttachment = function (id, name) {
+    var db = this._database,
+      that = this;
+
+    return new RSVP.Queue()
+      .push(function () {
+        return that._init_db_promise;
+      })
+      .push(function () {
+        return queueSql(db, ["DELETE FROM attachment WHERE " +
+                            "id = ? AND attachment = ?"], [[id, name]]);
+      })
+      .push(function (result) {
+        if (result[0].rowsAffected === 0) {
+          throw new jIO.util.jIOError("Cannot find document", 404);
+        }
+        return name;
+      });
+  };
+
+  WebSQLStorage.prototype.hasCapacity = function (name) {
+    return (name === "list" || (name === "include"));
+  };
+
+  WebSQLStorage.prototype.buildQuery = function (options) {
+    var db = this._database,
+      that = this,
+      query =  "SELECT id";
+
+    return new RSVP.Queue()
+      .push(function () {
+        return that._init_db_promise;
+      })
+      .push(function () {
+        if (options === undefined) { options = {}; }
+        if (options.include_docs === true) {
+          query += ", data AS doc";
+        }
+        query += " FROM document";
+        return queueSql(db, [query], [[]]);
+      })
+      .push(function (result) {
+        var array = [],
+          len = result[0].rows.length,
+          i;
+
+        for (i = 0; i < len; i += 1) {
+          array.push(result[0].rows[i]);
+          array[i].value = {};
+          if (array[i].doc !== undefined) {
+            array[i].doc = JSON.parse(array[i].doc);
+          }
+        }
+        return array;
+      });
+  };
+
+  jIO.addStorage('websql', WebSQLStorage);
+
+}(jIO, RSVP, Blob, openDatabase));
diff --git a/dist/jio-v3.11.0.min.js b/dist/jio-v3.11.0.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..93a1e3ff4e5b43f9883ead595eac0bdfeebf5812
--- /dev/null
+++ b/dist/jio-v3.11.0.min.js
@@ -0,0 +1,7 @@
+/*! jio v3.11.0 2016-06-23 */
+function parseStringToObject(a){var b=function(){var a,b,c=[],d=arguments;for(a=0;a<d.length;a+=1)for(b=0;b<d[a].length;b+=1)c.push(d[a][b]);return c},c=function(a,b,c){var d={type:"simple",key:a,value:b};return void 0!==c&&(d.operator=c),d},d=function(a){return"NOT"===a.operator?a.query_list[0]:{type:"complex",operator:"NOT",query_list:[a]}},e=function(a,c){var d,e=[];for(d=0;d<c.length;d+=1)c[d].operator===a?e=b(e,c[d].query_list):e.push(c[d]);return{type:"complex",operator:a,query_list:e}},f=function(a,b){var c;if("complex"===a.type){for(c=0;c<a.query_list.length;++c)f(a.query_list[c],b);return!0}return"simple"!==a.type||a.key?!1:(a.key=b,!0)},g=function(){function a(){this.yy={}}var b=function(a,b,c,d){for(c=c||{},d=a.length;d--;c[a[d]]=b);return c},g=[1,5],h=[1,7],i=[1,8],j=[1,10],k=[1,12],l=[1,6,7,15],m=[1,6,7,9,12,14,15,16,19,21],n=[1,6,7,9,11,12,14,15,16,19,21],o=[2,17],p={trace:function(){},yy:{},symbols_:{error:2,begin:3,search_text:4,end:5,EOF:6,NEWLINE:7,and_expression:8,OR:9,boolean_expression:10,AND:11,NOT:12,expression:13,LEFT_PARENTHESE:14,RIGHT_PARENTHESE:15,WORD:16,DEFINITION:17,value:18,OPERATOR:19,string:20,QUOTE:21,QUOTED_STRING:22,$accept:0,$end:1},terminals_:{2:"error",6:"EOF",7:"NEWLINE",9:"OR",11:"AND",12:"NOT",14:"LEFT_PARENTHESE",15:"RIGHT_PARENTHESE",16:"WORD",17:"DEFINITION",19:"OPERATOR",21:"QUOTE",22:"QUOTED_STRING"},productions_:[0,[3,2],[5,0],[5,1],[5,1],[4,1],[4,2],[4,3],[8,1],[8,3],[10,2],[10,1],[13,3],[13,3],[13,1],[18,2],[18,1],[20,1],[20,3]],performAction:function(a,b,g,h,i,j,k){var l=j.length-1;switch(i){case 1:return j[l-1];case 5:case 8:case 11:case 14:case 16:this.$=j[l];break;case 6:this.$=e("OR",[j[l-1],j[l]]);break;case 7:this.$=e("OR",[j[l-2],j[l]]);break;case 9:this.$=e("AND",[j[l-2],j[l]]);break;case 10:this.$=d(j[l]);break;case 12:this.$=j[l-1];break;case 13:f(j[l],j[l-2]),this.$=j[l];break;case 15:j[l].operator=j[l-1],this.$=j[l];break;case 17:this.$=c("",j[l]);break;case 18:this.$=c("",j[l-1])}},table:[{3:1,4:2,8:3,10:4,12:g,13:6,14:h,16:i,18:9,19:j,20:11,21:k},{1:[3]},{1:[2,2],5:13,6:[1,14],7:[1,15]},b(l,[2,5],{8:3,10:4,13:6,18:9,20:11,4:16,9:[1,17],12:g,14:h,16:i,19:j,21:k}),b(m,[2,8],{11:[1,18]}),{13:19,14:h,16:i,18:9,19:j,20:11,21:k},b(n,[2,11]),{4:20,8:3,10:4,12:g,13:6,14:h,16:i,18:9,19:j,20:11,21:k},b(n,o,{17:[1,21]}),b(n,[2,14]),{16:[1,23],20:22,21:k},b(n,[2,16]),{22:[1,24]},{1:[2,1]},{1:[2,3]},{1:[2,4]},b(l,[2,6]),{4:25,8:3,10:4,12:g,13:6,14:h,16:i,18:9,19:j,20:11,21:k},{8:26,10:4,12:g,13:6,14:h,16:i,18:9,19:j,20:11,21:k},b(n,[2,10]),{15:[1,27]},{13:28,14:h,16:i,18:9,19:j,20:11,21:k},b(n,[2,15]),b(n,o),{21:[1,29]},b(l,[2,7]),b(m,[2,9]),b(n,[2,12]),b(n,[2,13]),b(n,[2,18])],defaultActions:{13:[2,1],14:[2,3],15:[2,4]},parseError:function(a,b){function c(a,b){this.message=a,this.hash=b}if(!b.recoverable)throw c.prototype=new Error,new c(a,b);this.trace(a)},parse:function(a){var b=this,c=[0],d=[null],e=[],f=this.table,g="",h=0,i=0,j=0,k=2,l=1,m=e.slice.call(arguments,1),n=Object.create(this.lexer),o={yy:{}};for(var p in this.yy)Object.prototype.hasOwnProperty.call(this.yy,p)&&(o.yy[p]=this.yy[p]);n.setInput(a,o.yy),o.yy.lexer=n,o.yy.parser=this,"undefined"==typeof n.yylloc&&(n.yylloc={});var q=n.yylloc;e.push(q);var r=n.options&&n.options.ranges;"function"==typeof o.yy.parseError?this.parseError=o.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var s,t,u,v,w,x,y,z,A,B=function(){var a;return a=n.lex()||l,"number"!=typeof a&&(a=b.symbols_[a]||a),a},C={};;){if(u=c[c.length-1],this.defaultActions[u]?v=this.defaultActions[u]:((null===s||"undefined"==typeof s)&&(s=B()),v=f[u]&&f[u][s]),"undefined"==typeof v||!v.length||!v[0]){var D="";A=[];for(x in f[u])this.terminals_[x]&&x>k&&A.push("'"+this.terminals_[x]+"'");D=n.showPosition?"Parse error on line "+(h+1)+":\n"+n.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[s]||s)+"'":"Parse error on line "+(h+1)+": Unexpected "+(s==l?"end of input":"'"+(this.terminals_[s]||s)+"'"),this.parseError(D,{text:n.match,token:this.terminals_[s]||s,line:n.yylineno,loc:q,expected:A})}if(v[0]instanceof Array&&v.length>1)throw new Error("Parse Error: multiple actions possible at state: "+u+", token: "+s);switch(v[0]){case 1:c.push(s),d.push(n.yytext),e.push(n.yylloc),c.push(v[1]),s=null,t?(s=t,t=null):(i=n.yyleng,g=n.yytext,h=n.yylineno,q=n.yylloc,j>0&&j--);break;case 2:if(y=this.productions_[v[1]][1],C.$=d[d.length-y],C._$={first_line:e[e.length-(y||1)].first_line,last_line:e[e.length-1].last_line,first_column:e[e.length-(y||1)].first_column,last_column:e[e.length-1].last_column},r&&(C._$.range=[e[e.length-(y||1)].range[0],e[e.length-1].range[1]]),w=this.performAction.apply(C,[g,i,h,o.yy,v[1],d,e].concat(m)),"undefined"!=typeof w)return w;y&&(c=c.slice(0,-1*y*2),d=d.slice(0,-1*y),e=e.slice(0,-1*y)),c.push(this.productions_[v[1]][0]),d.push(C.$),e.push(C._$),z=f[c[c.length-2]][c[c.length-1]],c.push(z);break;case 3:return!0}}return!0}},q=function(){var a={EOF:1,parseError:function(a,b){if(!this.yy.parser)throw new Error(a);this.yy.parser.parseError(a,b)},setInput:function(a,b){return this.yy=b||this.yy||{},this._input=a,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.offset++,this.match+=a,this.matched+=a;var b=a.match(/(?:\r\n?|\n).*/g);return b?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),a},unput:function(a){var b=a.length,c=a.split(/(?:\r\n?|\n)/g);this._input=a+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-b),this.offset-=b;var d=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var e=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===d.length?this.yylloc.first_column:0)+d[d.length-c.length].length-c[0].length:this.yylloc.first_column-b},this.options.ranges&&(this.yylloc.range=[e[0],e[0]+this.yyleng-b]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(a){this.unput(this.match.slice(a))},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var a=this.pastInput(),b=new Array(a.length+1).join("-");return a+this.upcomingInput()+"\n"+b+"^"},test_match:function(a,b){var c,d,e;if(this.options.backtrack_lexer&&(e={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(e.yylloc.range=this.yylloc.range.slice(0))),d=a[0].match(/(?:\r\n?|\n).*/g),d&&(this.yylineno+=d.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:d?d[d.length-1].length-d[d.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+a[0].length},this.yytext+=a[0],this.match+=a[0],this.matches=a,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(a[0].length),this.matched+=a[0],c=this.performAction.call(this,this.yy,this,b,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),c)return c;if(this._backtrack){for(var f in e)this[f]=e[f];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var a,b,c,d;this._more||(this.yytext="",this.match="");for(var e=this._currentRules(),f=0;f<e.length;f++)if(c=this._input.match(this.rules[e[f]]),c&&(!b||c[0].length>b[0].length)){if(b=c,d=f,this.options.backtrack_lexer){if(a=this.test_match(c,e[f]),a!==!1)return a;if(this._backtrack){b=!1;continue}return!1}if(!this.options.flex)break}return b?(a=this.test_match(b,e[d]),a!==!1?a:!1):""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var a=this.next();return a?a:this.lex()},begin:function(a){this.conditionStack.push(a)},popState:function(){var a=this.conditionStack.length-1;return a>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(a){return a=this.conditionStack.length-1-Math.abs(a||0),a>=0?this.conditionStack[a]:"INITIAL"},pushState:function(a){this.begin(a)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(a,b,c,d){switch(c){case 0:return this.begin("letsquote"),"QUOTE";case 1:return this.popState(),this.begin("endquote"),"QUOTED_STRING";case 2:return this.popState(),"QUOTE";case 3:break;case 4:return"LEFT_PARENTHESE";case 5:return"RIGHT_PARENTHESE";case 6:return"AND";case 7:return"OR";case 8:return"NOT";case 9:return"DEFINITION";case 10:return 19;case 11:return 16;case 12:return 6}},rules:[/^(?:")/,/^(?:(\\"|[^"])*)/,/^(?:")/,/^(?:[^\S]+)/,/^(?:\()/,/^(?:\))/,/^(?:AND\b)/,/^(?:OR\b)/,/^(?:NOT\b)/,/^(?::)/,/^(?:(!?=|<=?|>=?))/,/^(?:[^\s\n"():><!=]+)/,/^(?:$)/],conditions:{endquote:{rules:[2],inclusive:!1},letsquote:{rules:[1],inclusive:!1},INITIAL:{rules:[0,3,4,5,6,7,8,9,10,11,12],inclusive:!0}}};return a}();return p.lexer=q,a.prototype=p,p.Parser=a,new a}();return g.parse(a)}!function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define(b):a.IPv6=b(a)}(this,function(a){var b=a&&a.IPv6;return{best:function(a){a=a.toLowerCase().split(":");var b=a.length,c=8;""===a[0]&&""===a[1]&&""===a[2]?(a.shift(),a.shift()):""===a[0]&&""===a[1]?a.shift():""===a[b-1]&&""===a[b-2]&&a.pop(),b=a.length,-1!==a[b-1].indexOf(".")&&(c=7);var d;for(d=0;b>d&&""!==a[d];d++);if(c>d)for(a.splice(d,1,"0000");a.length<c;)a.splice(d,0,"0000");for(d=0;c>d;d++){for(var b=a[d].split(""),e=0;3>e&&("0"===b[0]&&1<b.length);e++)b.splice(0,1);a[d]=b.join("")}var b=-1,f=e=0,g=-1,h=!1;for(d=0;c>d;d++)h?"0"===a[d]?f+=1:(h=!1,f>e&&(b=g,e=f)):"0"==a[d]&&(h=!0,g=d,f=1);for(f>e&&(b=g,e=f),e>1&&a.splice(b,e,""),b=a.length,c="",""===a[0]&&(beststr=":"),d=0;b>d&&(c+=a[d],d!==b-1);d++)c+=":";return""===a[b-1]&&(c+=":"),c},noConflict:function(){return a.IPv6===this&&(a.IPv6=b),this}}}),function(a){function b(a){throw RangeError(B[a])}function c(a,b){for(var c=a.length;c--;)a[c]=b(a[c]);return a}function d(a,b){return c(a.split(A),b).join(".")}function e(a){for(var b,c,d=[],e=0,f=a.length;f>e;)b=a.charCodeAt(e++),b>=55296&&56319>=b&&f>e?(c=a.charCodeAt(e++),56320==(64512&c)?d.push(((1023&b)<<10)+(1023&c)+65536):(d.push(b),e--)):d.push(b);return d}function f(a){return c(a,function(a){var b="";return a>65535&&(a-=65536,b+=E(a>>>10&1023|55296),a=56320|1023&a),b+=E(a)}).join("")}function g(a,b){return a+22+75*(26>a)-((0!=b)<<5)}function h(a,b,c){var d=0;for(a=c?D(a/u):a>>1,a+=D(a/b);a>C*s>>1;d+=q)a=D(a/C);return D(d+(C+1)*a/(a+t))}function i(a){var c,d,e,g,i,j,k=[],l=a.length,m=0,n=w,o=v;for(d=a.lastIndexOf(x),0>d&&(d=0),e=0;d>e;++e)128<=a.charCodeAt(e)&&b("not-basic"),k.push(a.charCodeAt(e));for(d=d>0?d+1:0;l>d;){for(e=m,c=1,g=q;d>=l&&b("invalid-input"),i=a.charCodeAt(d++),i=10>i-48?i-22:26>i-65?i-65:26>i-97?i-97:q,(i>=q||i>D((p-m)/c))&&b("overflow"),m+=i*c,j=o>=g?r:g>=o+s?s:g-o,!(j>i);g+=q)i=q-j,c>D(p/i)&&b("overflow"),c*=i;c=k.length+1,o=h(m-e,c,0==e),D(m/c)>p-n&&b("overflow"),n+=D(m/c),m%=c,k.splice(m++,0,n)}return f(k)}function j(a){var c,d,f,i,j,k,l,m,n,o,t,u,y=[];for(a=e(a),o=a.length,c=w,d=0,j=v,k=0;o>k;++k)n=a[k],128>n&&y.push(E(n));for((f=i=y.length)&&y.push(x);o>f;){for(l=p,k=0;o>k;++k)n=a[k],n>=c&&l>n&&(l=n);for(t=f+1,l-c>D((p-d)/t)&&b("overflow"),d+=(l-c)*t,c=l,k=0;o>k;++k)if(n=a[k],c>n&&++d>p&&b("overflow"),n==c){for(m=d,l=q;n=j>=l?r:l>=j+s?s:l-j,!(n>m);l+=q)u=m-n,m=q-n,y.push(E(g(n+u%m,0))),m=D(u/m);y.push(E(g(m,0))),j=h(d,t,f==i),d=0,++f}++d,++c}return y.join("")}var k="object"==typeof exports&&exports,l="object"==typeof module&&module&&module.exports==k&&module,m="object"==typeof global&&global;(m.global===m||m.window===m)&&(a=m);var n,o,p=2147483647,q=36,r=1,s=26,t=38,u=700,v=72,w=128,x="-",y=/^xn--/,z=/[^ -~]/,A=/\x2E|\u3002|\uFF0E|\uFF61/g,B={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},C=q-r,D=Math.floor,E=String.fromCharCode;if(n={version:"1.2.3",ucs2:{decode:e,encode:f},decode:i,encode:j,toASCII:function(a){return d(a,function(a){return z.test(a)?"xn--"+j(a):a})},toUnicode:function(a){return d(a,function(a){return y.test(a)?i(a.slice(4).toLowerCase()):a})}},"function"==typeof define&&"object"==typeof define.amd&&define.amd)define(function(){return n});else if(k&&!k.nodeType)if(l)l.exports=n;else for(o in n)n.hasOwnProperty(o)&&(k[o]=n[o]);else a.punycode=n}(this),function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define(b):a.SecondLevelDomains=b(a)}(this,function(a){var b=a&&a.SecondLevelDomains,c=Object.prototype.hasOwnProperty,d={list:{ac:"com|gov|mil|net|org",ae:"ac|co|gov|mil|name|net|org|pro|sch",af:"com|edu|gov|net|org",al:"com|edu|gov|mil|net|org",ao:"co|ed|gv|it|og|pb",ar:"com|edu|gob|gov|int|mil|net|org|tur",at:"ac|co|gv|or",au:"asn|com|csiro|edu|gov|id|net|org",ba:"co|com|edu|gov|mil|net|org|rs|unbi|unmo|unsa|untz|unze",bb:"biz|co|com|edu|gov|info|net|org|store|tv",bh:"biz|cc|com|edu|gov|info|net|org",bn:"com|edu|gov|net|org",bo:"com|edu|gob|gov|int|mil|net|org|tv",br:"adm|adv|agr|am|arq|art|ato|b|bio|blog|bmd|cim|cng|cnt|com|coop|ecn|edu|eng|esp|etc|eti|far|flog|fm|fnd|fot|fst|g12|ggf|gov|imb|ind|inf|jor|jus|lel|mat|med|mil|mus|net|nom|not|ntr|odo|org|ppg|pro|psc|psi|qsl|rec|slg|srv|tmp|trd|tur|tv|vet|vlog|wiki|zlg",bs:"com|edu|gov|net|org",bz:"du|et|om|ov|rg",ca:"ab|bc|mb|nb|nf|nl|ns|nt|nu|on|pe|qc|sk|yk",ck:"biz|co|edu|gen|gov|info|net|org",cn:"ac|ah|bj|com|cq|edu|fj|gd|gov|gs|gx|gz|ha|hb|he|hi|hl|hn|jl|js|jx|ln|mil|net|nm|nx|org|qh|sc|sd|sh|sn|sx|tj|tw|xj|xz|yn|zj",co:"com|edu|gov|mil|net|nom|org",cr:"ac|c|co|ed|fi|go|or|sa",cy:"ac|biz|com|ekloges|gov|ltd|name|net|org|parliament|press|pro|tm","do":"art|com|edu|gob|gov|mil|net|org|sld|web",dz:"art|asso|com|edu|gov|net|org|pol",ec:"com|edu|fin|gov|info|med|mil|net|org|pro",eg:"com|edu|eun|gov|mil|name|net|org|sci",er:"com|edu|gov|ind|mil|net|org|rochest|w",es:"com|edu|gob|nom|org",et:"biz|com|edu|gov|info|name|net|org",fj:"ac|biz|com|info|mil|name|net|org|pro",fk:"ac|co|gov|net|nom|org",fr:"asso|com|f|gouv|nom|prd|presse|tm",gg:"co|net|org",gh:"com|edu|gov|mil|org",gn:"ac|com|gov|net|org",gr:"com|edu|gov|mil|net|org",gt:"com|edu|gob|ind|mil|net|org",gu:"com|edu|gov|net|org",hk:"com|edu|gov|idv|net|org",id:"ac|co|go|mil|net|or|sch|web",il:"ac|co|gov|idf|k12|muni|net|org","in":"ac|co|edu|ernet|firm|gen|gov|i|ind|mil|net|nic|org|res",iq:"com|edu|gov|i|mil|net|org",ir:"ac|co|dnssec|gov|i|id|net|org|sch",it:"edu|gov",je:"co|net|org",jo:"com|edu|gov|mil|name|net|org|sch",jp:"ac|ad|co|ed|go|gr|lg|ne|or",ke:"ac|co|go|info|me|mobi|ne|or|sc",kh:"com|edu|gov|mil|net|org|per",ki:"biz|com|de|edu|gov|info|mob|net|org|tel",km:"asso|com|coop|edu|gouv|k|medecin|mil|nom|notaires|pharmaciens|presse|tm|veterinaire",kn:"edu|gov|net|org",kr:"ac|busan|chungbuk|chungnam|co|daegu|daejeon|es|gangwon|go|gwangju|gyeongbuk|gyeonggi|gyeongnam|hs|incheon|jeju|jeonbuk|jeonnam|k|kg|mil|ms|ne|or|pe|re|sc|seoul|ulsan",kw:"com|edu|gov|net|org",ky:"com|edu|gov|net|org",kz:"com|edu|gov|mil|net|org",lb:"com|edu|gov|net|org",lk:"assn|com|edu|gov|grp|hotel|int|ltd|net|ngo|org|sch|soc|web",lr:"com|edu|gov|net|org",lv:"asn|com|conf|edu|gov|id|mil|net|org",ly:"com|edu|gov|id|med|net|org|plc|sch",ma:"ac|co|gov|m|net|org|press",mc:"asso|tm",me:"ac|co|edu|gov|its|net|org|priv",mg:"com|edu|gov|mil|nom|org|prd|tm",mk:"com|edu|gov|inf|name|net|org|pro",ml:"com|edu|gov|net|org|presse",mn:"edu|gov|org",mo:"com|edu|gov|net|org",mt:"com|edu|gov|net|org",mv:"aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro",mw:"ac|co|com|coop|edu|gov|int|museum|net|org",mx:"com|edu|gob|net|org",my:"com|edu|gov|mil|name|net|org|sch",nf:"arts|com|firm|info|net|other|per|rec|store|web",ng:"biz|com|edu|gov|mil|mobi|name|net|org|sch",ni:"ac|co|com|edu|gob|mil|net|nom|org",np:"com|edu|gov|mil|net|org",nr:"biz|com|edu|gov|info|net|org",om:"ac|biz|co|com|edu|gov|med|mil|museum|net|org|pro|sch",pe:"com|edu|gob|mil|net|nom|org|sld",ph:"com|edu|gov|i|mil|net|ngo|org",pk:"biz|com|edu|fam|gob|gok|gon|gop|gos|gov|net|org|web",pl:"art|bialystok|biz|com|edu|gda|gdansk|gorzow|gov|info|katowice|krakow|lodz|lublin|mil|net|ngo|olsztyn|org|poznan|pwr|radom|slupsk|szczecin|torun|warszawa|waw|wroc|wroclaw|zgora",pr:"ac|biz|com|edu|est|gov|info|isla|name|net|org|pro|prof",ps:"com|edu|gov|net|org|plo|sec",pw:"belau|co|ed|go|ne|or",ro:"arts|com|firm|info|nom|nt|org|rec|store|tm|www",rs:"ac|co|edu|gov|in|org",sb:"com|edu|gov|net|org",sc:"com|edu|gov|net|org",sh:"co|com|edu|gov|net|nom|org",sl:"com|edu|gov|net|org",st:"co|com|consulado|edu|embaixada|gov|mil|net|org|principe|saotome|store",sv:"com|edu|gob|org|red",sz:"ac|co|org",tr:"av|bbs|bel|biz|com|dr|edu|gen|gov|info|k12|name|net|org|pol|tel|tsk|tv|web",tt:"aero|biz|cat|co|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel",tw:"club|com|ebiz|edu|game|gov|idv|mil|net|org",mu:"ac|co|com|gov|net|or|org",mz:"ac|co|edu|gov|org",na:"co|com",nz:"ac|co|cri|geek|gen|govt|health|iwi|maori|mil|net|org|parliament|school",pa:"abo|ac|com|edu|gob|ing|med|net|nom|org|sld",pt:"com|edu|gov|int|net|nome|org|publ",py:"com|edu|gov|mil|net|org",qa:"com|edu|gov|mil|net|org",re:"asso|com|nom",ru:"ac|adygeya|altai|amur|arkhangelsk|astrakhan|bashkiria|belgorod|bir|bryansk|buryatia|cbg|chel|chelyabinsk|chita|chukotka|chuvashia|com|dagestan|e-burg|edu|gov|grozny|int|irkutsk|ivanovo|izhevsk|jar|joshkar-ola|kalmykia|kaluga|kamchatka|karelia|kazan|kchr|kemerovo|khabarovsk|khakassia|khv|kirov|koenig|komi|kostroma|kranoyarsk|kuban|kurgan|kursk|lipetsk|magadan|mari|mari-el|marine|mil|mordovia|mosreg|msk|murmansk|nalchik|net|nnov|nov|novosibirsk|nsk|omsk|orenburg|org|oryol|penza|perm|pp|pskov|ptz|rnd|ryazan|sakhalin|samara|saratov|simbirsk|smolensk|spb|stavropol|stv|surgut|tambov|tatarstan|tom|tomsk|tsaritsyn|tsk|tula|tuva|tver|tyumen|udm|udmurtia|ulan-ude|vladikavkaz|vladimir|vladivostok|volgograd|vologda|voronezh|vrn|vyatka|yakutia|yamal|yekaterinburg|yuzhno-sakhalinsk",rw:"ac|co|com|edu|gouv|gov|int|mil|net",sa:"com|edu|gov|med|net|org|pub|sch",sd:"com|edu|gov|info|med|net|org|tv",se:"a|ac|b|bd|c|d|e|f|g|h|i|k|l|m|n|o|org|p|parti|pp|press|r|s|t|tm|u|w|x|y|z",sg:"com|edu|gov|idn|net|org|per",sn:"art|com|edu|gouv|org|perso|univ",sy:"com|edu|gov|mil|net|news|org",th:"ac|co|go|in|mi|net|or",tj:"ac|biz|co|com|edu|go|gov|info|int|mil|name|net|nic|org|test|web",tn:"agrinet|com|defense|edunet|ens|fin|gov|ind|info|intl|mincom|nat|net|org|perso|rnrt|rns|rnu|tourism",tz:"ac|co|go|ne|or",ua:"biz|cherkassy|chernigov|chernovtsy|ck|cn|co|com|crimea|cv|dn|dnepropetrovsk|donetsk|dp|edu|gov|if|in|ivano-frankivsk|kh|kharkov|kherson|khmelnitskiy|kiev|kirovograd|km|kr|ks|kv|lg|lugansk|lutsk|lviv|me|mk|net|nikolaev|od|odessa|org|pl|poltava|pp|rovno|rv|sebastopol|sumy|te|ternopil|uzhgorod|vinnica|vn|zaporizhzhe|zhitomir|zp|zt",ug:"ac|co|go|ne|or|org|sc",uk:"ac|bl|british-library|co|cym|gov|govt|icnet|jet|lea|ltd|me|mil|mod|national-library-scotland|nel|net|nhs|nic|nls|org|orgn|parliament|plc|police|sch|scot|soc",us:"dni|fed|isa|kids|nsn",uy:"com|edu|gub|mil|net|org",ve:"co|com|edu|gob|info|mil|net|org|web",vi:"co|com|k12|net|org",vn:"ac|biz|com|edu|gov|health|info|int|name|net|org|pro",ye:"co|com|gov|ltd|me|net|org|plc",yu:"ac|co|edu|gov|org",za:"ac|agric|alt|bourse|city|co|cybernet|db|edu|gov|grondar|iaccess|imt|inca|landesign|law|mil|net|ngo|nis|nom|olivetti|org|pix|school|tm|web",zm:"ac|co|com|edu|gov|net|org|sch"},has_expression:null,is_expression:null,has:function(a){return!!a.match(d.has_expression)},is:function(a){return!!a.match(d.is_expression)},get:function(a){return(a=a.match(d.has_expression))&&a[1]||null},noConflict:function(){return a.SecondLevelDomains===this&&(a.SecondLevelDomains=b),this},init:function(){var a,b="";for(a in d.list)c.call(d.list,a)&&(b+="|("+("("+d.list[a]+")."+a)+")");d.has_expression=RegExp("\\.("+b.substr(1)+")$","i"),d.is_expression=RegExp("^("+b.substr(1)+")$","i")}};return d.init(),d}),function(a,b){"object"==typeof exports?module.exports=b(require("./punycode"),require("./IPv6"),require("./SecondLevelDomains")):"function"==typeof define&&define.amd?define(["./punycode","./IPv6","./SecondLevelDomains"],b):a.URI=b(a.punycode,a.IPv6,a.SecondLevelDomains,a)}(this,function(a,b,c,d){function e(a,b){return this instanceof e?(void 0===a&&(a="undefined"!=typeof location?location.href+"":""),this.href(a),void 0!==b?this.absoluteTo(b):this):new e(a,b)}function f(a){return a.replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")}function g(a){return void 0===a?"Undefined":String(Object.prototype.toString.call(a)).slice(8,-1)}function h(a){return"Array"===g(a)}function i(a,b){var c,d;if(h(b)){for(c=0,d=b.length;d>c;c++)if(!i(a,b[c]))return!1;return!0}var e=g(b);for(c=0,d=a.length;d>c;c++)if("RegExp"===e){if("string"==typeof a[c]&&a[c].match(b))return!0}else if(a[c]===b)return!0;return!1}function j(a,b){if(!h(a)||!h(b)||a.length!==b.length)return!1;a.sort(),b.sort();for(var c=0,d=a.length;d>c;c++)if(a[c]!==b[c])return!1;return!0}function k(a){return escape(a)}function l(a){return encodeURIComponent(a).replace(/[!'()*]/g,k).replace(/\*/g,"%2A")}var m=d&&d.URI;e.version="1.12.0";var n=e.prototype,o=Object.prototype.hasOwnProperty;e._parts=function(){return{protocol:null,username:null,password:null,hostname:null,urn:null,port:null,path:null,query:null,fragment:null,duplicateQueryParameters:e.duplicateQueryParameters,escapeQuerySpace:e.escapeQuerySpace}},e.duplicateQueryParameters=!1,e.escapeQuerySpace=!0,e.protocol_expression=/^[a-z][a-z0-9.+-]*$/i,e.idn_expression=/[^a-z0-9\.-]/i,e.punycode_expression=/(xn--)/i,e.ip4_expression=/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,e.ip6_expression=/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,e.find_uri_expression=/\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u2018\u2019]))/gi,e.findUri={start:/\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,end:/[\s\r\n]|$/,trim:/[`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u201e\u2018\u2019]+$/},e.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"},e.invalid_hostname_characters=/[^a-zA-Z0-9\.-]/,e.domAttributes={a:"href",blockquote:"cite",link:"href",base:"href",script:"src",form:"action",img:"src",area:"href",iframe:"src",embed:"src",source:"src",track:"src",input:"src"},e.getDomAttribute=function(a){if(a&&a.nodeName){var b=a.nodeName.toLowerCase();return"input"===b&&"image"!==a.type?void 0:e.domAttributes[b]}},e.encode=l,e.decode=decodeURIComponent,e.iso8859=function(){e.encode=escape,e.decode=unescape},e.unicode=function(){e.encode=l,e.decode=decodeURIComponent},e.characters={pathname:{encode:{expression:/%(24|26|2B|2C|3B|3D|3A|40)/gi,map:{"%24":"$","%26":"&","%2B":"+","%2C":",","%3B":";","%3D":"=","%3A":":","%40":"@"}},decode:{expression:/[\/\?#]/g,map:{"/":"%2F","?":"%3F","#":"%23"}}},reserved:{encode:{expression:/%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/gi,map:{"%3A":":","%2F":"/","%3F":"?","%23":"#","%5B":"[","%5D":"]","%40":"@","%21":"!","%24":"$","%26":"&","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"="}}}},e.encodeQuery=function(a,b){var c=e.encode(a+"");return b?c.replace(/%20/g,"+"):c},e.decodeQuery=function(a,b){a+="";try{return e.decode(b?a.replace(/\+/g,"%20"):a)}catch(c){return a}},e.recodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;c>b;b++)a[b]=e.encodePathSegment(e.decode(a[b]));return a.join("/")},e.decodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;c>b;b++)a[b]=e.decodePathSegment(a[b]);return a.join("/")};var p,q={encode:"encode",decode:"decode"},r=function(a,b){return function(c){return e[b](c+"").replace(e.characters[a][b].expression,function(c){return e.characters[a][b].map[c]})}};for(p in q)e[p+"PathSegment"]=r("pathname",q[p]);e.encodeReserved=r("reserved","encode"),e.parse=function(a,b){var c;return b||(b={}),c=a.indexOf("#"),c>-1&&(b.fragment=a.substring(c+1)||null,a=a.substring(0,c)),c=a.indexOf("?"),c>-1&&(b.query=a.substring(c+1)||null,a=a.substring(0,c)),"//"===a.substring(0,2)?(b.protocol=null,a=a.substring(2),a=e.parseAuthority(a,b)):(c=a.indexOf(":"),c>-1&&(b.protocol=a.substring(0,c)||null,b.protocol&&!b.protocol.match(e.protocol_expression)?b.protocol=void 0:"file"===b.protocol?a=a.substring(c+3):"//"===a.substring(c+1,c+3)?(a=a.substring(c+3),a=e.parseAuthority(a,b)):(a=a.substring(c+1),b.urn=!0))),b.path=a,b},e.parseHost=function(a,b){var c,d=a.indexOf("/");return-1===d&&(d=a.length),"["===a.charAt(0)?(c=a.indexOf("]"),b.hostname=a.substring(1,c)||null,b.port=a.substring(c+2,d)||null):a.indexOf(":")!==a.lastIndexOf(":")?(b.hostname=a.substring(0,d)||null,b.port=null):(c=a.substring(0,d).split(":"),b.hostname=c[0]||null,b.port=c[1]||null),b.hostname&&"/"!==a.substring(d).charAt(0)&&(d++,a="/"+a),a.substring(d)||"/"},e.parseAuthority=function(a,b){return a=e.parseUserinfo(a,b),e.parseHost(a,b)},e.parseUserinfo=function(a,b){var c=a.indexOf("/"),d=c>-1?a.lastIndexOf("@",c):a.indexOf("@");return d>-1&&(-1===c||c>d)?(c=a.substring(0,d).split(":"),b.username=c[0]?e.decode(c[0]):null,c.shift(),b.password=c[0]?e.decode(c.join(":")):null,a=a.substring(d+1)):(b.username=null,b.password=null),a},e.parseQuery=function(a,b){if(!a)return{};if(a=a.replace(/&+/g,"&").replace(/^\?*&*|&+$/g,""),!a)return{};for(var c,d,f={},g=a.split("&"),h=g.length,i=0;h>i;i++)c=g[i].split("="),d=e.decodeQuery(c.shift(),b),c=c.length?e.decodeQuery(c.join("="),b):null,f[d]?("string"==typeof f[d]&&(f[d]=[f[d]]),f[d].push(c)):f[d]=c;return f},e.build=function(a){var b="";return a.protocol&&(b+=a.protocol+":"),a.urn||!b&&!a.hostname||(b+="//"),b+=e.buildAuthority(a)||"","string"==typeof a.path&&("/"!==a.path.charAt(0)&&"string"==typeof a.hostname&&(b+="/"),b+=a.path),"string"==typeof a.query&&a.query&&(b+="?"+a.query),"string"==typeof a.fragment&&a.fragment&&(b+="#"+a.fragment),b},e.buildHost=function(a){var b="";return a.hostname?(e.ip6_expression.test(a.hostname)?b=a.port?b+("["+a.hostname+"]:"+a.port):b+a.hostname:(b+=a.hostname,a.port&&(b+=":"+a.port)),b):""},e.buildAuthority=function(a){return e.buildUserinfo(a)+e.buildHost(a)},e.buildUserinfo=function(a){var b="";return a.username&&(b+=e.encode(a.username),a.password&&(b+=":"+e.encode(a.password)),b+="@"),b},e.buildQuery=function(a,b,c){var d,f,g,i,j="";for(f in a)if(o.call(a,f)&&f)if(h(a[f]))for(d={},g=0,i=a[f].length;i>g;g++)void 0!==a[f][g]&&void 0===d[a[f][g]+""]&&(j+="&"+e.buildQueryParameter(f,a[f][g],c),!0!==b&&(d[a[f][g]+""]=!0));else void 0!==a[f]&&(j+="&"+e.buildQueryParameter(f,a[f],c));return j.substring(1)},e.buildQueryParameter=function(a,b,c){return e.encodeQuery(a,c)+(null!==b?"="+e.encodeQuery(b,c):"")},e.addQuery=function(a,b,c){if("object"==typeof b)for(var d in b)o.call(b,d)&&e.addQuery(a,d,b[d]);else{if("string"!=typeof b)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");void 0===a[b]?a[b]=c:("string"==typeof a[b]&&(a[b]=[a[b]]),h(c)||(c=[c]),a[b]=a[b].concat(c))}},e.removeQuery=function(a,b,c){var d;if(h(b))for(c=0,d=b.length;d>c;c++)a[b[c]]=void 0;else if("object"==typeof b)for(d in b)o.call(b,d)&&e.removeQuery(a,d,b[d]);else{if("string"!=typeof b)throw new TypeError("URI.addQuery() accepts an object, string as the first parameter");if(void 0!==c){if(a[b]===c)a[b]=void 0;else if(h(a[b])){d=a[b];var f,g,i={};if(h(c))for(f=0,g=c.length;g>f;f++)i[c[f]]=!0;else i[c]=!0;for(f=0,g=d.length;g>f;f++)void 0!==i[d[f]]&&(d.splice(f,1),g--,f--);a[b]=d}}else a[b]=void 0}},e.hasQuery=function(a,b,c,d){if("object"==typeof b){for(var f in b)if(o.call(b,f)&&!e.hasQuery(a,f,b[f]))return!1;return!0}if("string"!=typeof b)throw new TypeError("URI.hasQuery() accepts an object, string as the name parameter");switch(g(c)){case"Undefined":return b in a;case"Boolean":return a=Boolean(h(a[b])?a[b].length:a[b]),c===a;case"Function":return!!c(a[b],b,a);case"Array":return h(a[b])?(d?i:j)(a[b],c):!1;case"RegExp":return h(a[b])?d?i(a[b],c):!1:Boolean(a[b]&&a[b].match(c));case"Number":c=String(c);case"String":return h(a[b])?d?i(a[b],c):!1:a[b]===c;default:throw new TypeError("URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter")}},e.commonPath=function(a,b){var c,d=Math.min(a.length,b.length);for(c=0;d>c;c++)if(a.charAt(c)!==b.charAt(c)){c--;break}return 1>c?a.charAt(0)===b.charAt(0)&&"/"===a.charAt(0)?"/":"":(("/"!==a.charAt(c)||"/"!==b.charAt(c))&&(c=a.substring(0,c).lastIndexOf("/")),a.substring(0,c+1))},e.withinString=function(a,b,c){c||(c={});var d=c.start||e.findUri.start,f=c.end||e.findUri.end,g=c.trim||e.findUri.trim,h=/[a-z0-9-]=["']?$/i;for(d.lastIndex=0;;){var i=d.exec(a);if(!i)break;if(i=i.index,c.ignoreHtml){var j=a.slice(Math.max(i-3,0),i);if(j&&h.test(j))continue}var j=i+a.slice(i).search(f),k=a.slice(i,j).replace(g,"");c.ignore&&c.ignore.test(k)||(j=i+k.length,k=b(k,i,j,a),a=a.slice(0,i)+k+a.slice(j),d.lastIndex=i+k.length)}return d.lastIndex=0,a},e.ensureValidHostname=function(b){if(b.match(e.invalid_hostname_characters)){if(!a)throw new TypeError("Hostname '"+b+"' contains characters other than [A-Z0-9.-] and Punycode.js is not available");
+if(a.toASCII(b).match(e.invalid_hostname_characters))throw new TypeError("Hostname '"+b+"' contains characters other than [A-Z0-9.-]")}},e.noConflict=function(a){return a?(a={URI:this.noConflict()},URITemplate&&"function"==typeof URITemplate.noConflict&&(a.URITemplate=URITemplate.noConflict()),b&&"function"==typeof b.noConflict&&(a.IPv6=b.noConflict()),SecondLevelDomains&&"function"==typeof SecondLevelDomains.noConflict&&(a.SecondLevelDomains=SecondLevelDomains.noConflict()),a):(d.URI===this&&(d.URI=m),this)},n.build=function(a){return!0===a?this._deferred_build=!0:(void 0===a||this._deferred_build)&&(this._string=e.build(this._parts),this._deferred_build=!1),this},n.clone=function(){return new e(this)},n.valueOf=n.toString=function(){return this.build(!1)._string},q={protocol:"protocol",username:"username",password:"password",hostname:"hostname",port:"port"},r=function(a){return function(b,c){return void 0===b?this._parts[a]||"":(this._parts[a]=b||null,this.build(!c),this)}};for(p in q)n[p]=r(q[p]);q={query:"?",fragment:"#"},r=function(a,b){return function(c,d){return void 0===c?this._parts[a]||"":(null!==c&&(c+="",c.charAt(0)===b&&(c=c.substring(1))),this._parts[a]=c,this.build(!d),this)}};for(p in q)n[p]=r(p,q[p]);q={search:["?","query"],hash:["#","fragment"]},r=function(a,b){return function(c,d){var e=this[a](c,d);return"string"==typeof e&&e.length?b+e:e}};for(p in q)n[p]=r(q[p][1],q[p][0]);n.pathname=function(a,b){if(void 0===a||!0===a){var c=this._parts.path||(this._parts.hostname?"/":"");return a?e.decodePath(c):c}return this._parts.path=a?e.recodePath(a):"/",this.build(!b),this},n.path=n.pathname,n.href=function(a,b){var c;if(void 0===a)return this.toString();this._string="",this._parts=e._parts();var d=a instanceof e,f="object"==typeof a&&(a.hostname||a.path||a.pathname);if(a.nodeName&&(f=e.getDomAttribute(a),a=a[f]||"",f=!1),!d&&f&&void 0!==a.pathname&&(a=a.toString()),"string"==typeof a)this._parts=e.parse(a,this._parts);else{if(!d&&!f)throw new TypeError("invalid input");for(c in d=d?a._parts:a)o.call(this._parts,c)&&(this._parts[c]=d[c])}return this.build(!b),this},n.is=function(a){var b=!1,d=!1,f=!1,g=!1,h=!1,i=!1,j=!1,k=!this._parts.urn;switch(this._parts.hostname&&(k=!1,d=e.ip4_expression.test(this._parts.hostname),f=e.ip6_expression.test(this._parts.hostname),b=d||f,h=(g=!b)&&c&&c.has(this._parts.hostname),i=g&&e.idn_expression.test(this._parts.hostname),j=g&&e.punycode_expression.test(this._parts.hostname)),a.toLowerCase()){case"relative":return k;case"absolute":return!k;case"domain":case"name":return g;case"sld":return h;case"ip":return b;case"ip4":case"ipv4":case"inet4":return d;case"ip6":case"ipv6":case"inet6":return f;case"idn":return i;case"url":return!this._parts.urn;case"urn":return!!this._parts.urn;case"punycode":return j}return null};var s=n.protocol,t=n.port,u=n.hostname;n.protocol=function(a,b){if(void 0!==a&&a&&(a=a.replace(/:(\/\/)?$/,""),!a.match(e.protocol_expression)))throw new TypeError("Protocol '"+a+"' contains characters other than [A-Z0-9.+-] or doesn't start with [A-Z]");return s.call(this,a,b)},n.scheme=n.protocol,n.port=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a&&(0===a&&(a=null),a&&(a+="",":"===a.charAt(0)&&(a=a.substring(1)),a.match(/[^0-9]/))))throw new TypeError("Port '"+a+"' contains characters other than [0-9]");return t.call(this,a,b)},n.hostname=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a){var c={};e.parseHost(a,c),a=c.hostname}return u.call(this,a,b)},n.host=function(a,b){return this._parts.urn?void 0===a?"":this:void 0===a?this._parts.hostname?e.buildHost(this._parts):"":(e.parseHost(a,this._parts),this.build(!b),this)},n.authority=function(a,b){return this._parts.urn?void 0===a?"":this:void 0===a?this._parts.hostname?e.buildAuthority(this._parts):"":(e.parseAuthority(a,this._parts),this.build(!b),this)},n.userinfo=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.username)return"";var c=e.buildUserinfo(this._parts);return c.substring(0,c.length-1)}return"@"!==a[a.length-1]&&(a+="@"),e.parseUserinfo(a,this._parts),this.build(!b),this},n.resource=function(a,b){var c;return void 0===a?this.path()+this.search()+this.hash():(c=e.parse(a),this._parts.path=c.path,this._parts.query=c.query,this._parts.fragment=c.fragment,this.build(!b),this)},n.subdomain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.length-this.domain().length-1;return this._parts.hostname.substring(0,c)||""}return c=this._parts.hostname.length-this.domain().length,c=this._parts.hostname.substring(0,c),c=RegExp("^"+f(c)),a&&"."!==a.charAt(a.length-1)&&(a+="."),a&&e.ensureValidHostname(a),this._parts.hostname=this._parts.hostname.replace(c,a),this.build(!b),this},n.domain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if("boolean"==typeof a&&(b=a,a=void 0),void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.match(/\./g);return c&&2>c.length?this._parts.hostname:(c=this._parts.hostname.length-this.tld(b).length-1,c=this._parts.hostname.lastIndexOf(".",c-1)+1,this._parts.hostname.substring(c)||"")}if(!a)throw new TypeError("cannot set domain empty");return e.ensureValidHostname(a),!this._parts.hostname||this.is("IP")?this._parts.hostname=a:(c=RegExp(f(this.domain())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a)),this.build(!b),this},n.tld=function(a,b){if(this._parts.urn)return void 0===a?"":this;if("boolean"==typeof a&&(b=a,a=void 0),void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var d=this._parts.hostname.lastIndexOf("."),d=this._parts.hostname.substring(d+1);return!0!==b&&c&&c.list[d.toLowerCase()]?c.get(this._parts.hostname)||d:d}if(!a)throw new TypeError("cannot set TLD empty");if(a.match(/[^a-zA-Z0-9-]/)){if(!c||!c.is(a))throw new TypeError("TLD '"+a+"' contains characters other than [A-Z0-9]");d=RegExp(f(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(d,a)}else{if(!this._parts.hostname||this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");d=RegExp(f(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(d,a)}return this.build(!b),this},n.directory=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var c=this._parts.path.length-this.filename().length-1,c=this._parts.path.substring(0,c)||(this._parts.hostname?"/":"");return a?e.decodePath(c):c}return c=this._parts.path.length-this.filename().length,c=this._parts.path.substring(0,c),c=RegExp("^"+f(c)),this.is("relative")||(a||(a="/"),"/"!==a.charAt(0)&&(a="/"+a)),a&&"/"!==a.charAt(a.length-1)&&(a+="/"),a=e.recodePath(a),this._parts.path=this._parts.path.replace(c,a),this.build(!b),this},n.filename=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var c=this._parts.path.lastIndexOf("/"),c=this._parts.path.substring(c+1);return a?e.decodePathSegment(c):c}c=!1,"/"===a.charAt(0)&&(a=a.substring(1)),a.match(/\.?\//)&&(c=!0);var d=RegExp(f(this.filename())+"$");return a=e.recodePath(a),this._parts.path=this._parts.path.replace(d,a),c?this.normalizePath(b):this.build(!b),this},n.suffix=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var c=this.filename(),d=c.lastIndexOf(".");return-1===d?"":(c=c.substring(d+1),c=/^[a-z0-9%]+$/i.test(c)?c:"",a?e.decodePathSegment(c):c)}if("."===a.charAt(0)&&(a=a.substring(1)),c=this.suffix())d=a?RegExp(f(c)+"$"):RegExp(f("."+c)+"$");else{if(!a)return this;this._parts.path+="."+e.recodePath(a)}return d&&(a=e.recodePath(a),this._parts.path=this._parts.path.replace(d,a)),this.build(!b),this},n.segment=function(a,b,c){var d=this._parts.urn?":":"/",e=this.path(),f="/"===e.substring(0,1),e=e.split(d);if(void 0!==a&&"number"!=typeof a&&(c=b,b=a,a=void 0),void 0!==a&&"number"!=typeof a)throw Error("Bad segment '"+a+"', must be 0-based integer");if(f&&e.shift(),0>a&&(a=Math.max(e.length+a,0)),void 0===b)return void 0===a?e:e[a];if(null===a||void 0===e[a])if(h(b)){e=[],a=0;for(var g=b.length;g>a;a++)(b[a].length||e.length&&e[e.length-1].length)&&(e.length&&!e[e.length-1].length&&e.pop(),e.push(b[a]))}else(b||"string"==typeof b)&&(""===e[e.length-1]?e[e.length-1]=b:e.push(b));else b||"string"==typeof b&&b.length?e[a]=b:e.splice(a,1);return f&&e.unshift(""),this.path(e.join(d),c)},n.segmentCoded=function(a,b,c){var d,f;if("number"!=typeof a&&(c=b,b=a,a=void 0),void 0===b){if(a=this.segment(a,b,c),h(a))for(d=0,f=a.length;f>d;d++)a[d]=e.decode(a[d]);else a=void 0!==a?e.decode(a):void 0;return a}if(h(b))for(d=0,f=b.length;f>d;d++)b[d]=e.decode(b[d]);else b="string"==typeof b?e.encode(b):b;return this.segment(a,b,c)};var v=n.query;return n.query=function(a,b){if(!0===a)return e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("function"==typeof a){var c=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace),d=a.call(this,c);return this._parts.query=e.buildQuery(d||c,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!b),this}return void 0!==a&&"string"!=typeof a?(this._parts.query=e.buildQuery(a,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!b),this):v.call(this,a,b)},n.setQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("object"==typeof a)for(var f in a)o.call(a,f)&&(d[f]=a[f]);else{if("string"!=typeof a)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");d[a]=void 0!==b?b:null}return this._parts.query=e.buildQuery(d,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof a&&(c=b),this.build(!c),this},n.addQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return e.addQuery(d,a,void 0===b?null:b),this._parts.query=e.buildQuery(d,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof a&&(c=b),this.build(!c),this},n.removeQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return e.removeQuery(d,a,b),this._parts.query=e.buildQuery(d,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof a&&(c=b),this.build(!c),this},n.hasQuery=function(a,b,c){var d=e.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return e.hasQuery(d,a,b,c)},n.setSearch=n.setQuery,n.addSearch=n.addQuery,n.removeSearch=n.removeQuery,n.hasSearch=n.hasQuery,n.normalize=function(){return this._parts.urn?this.normalizeProtocol(!1).normalizeQuery(!1).normalizeFragment(!1).build():this.normalizeProtocol(!1).normalizeHostname(!1).normalizePort(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build()},n.normalizeProtocol=function(a){return"string"==typeof this._parts.protocol&&(this._parts.protocol=this._parts.protocol.toLowerCase(),this.build(!a)),this},n.normalizeHostname=function(c){return this._parts.hostname&&(this.is("IDN")&&a?this._parts.hostname=a.toASCII(this._parts.hostname):this.is("IPv6")&&b&&(this._parts.hostname=b.best(this._parts.hostname)),this._parts.hostname=this._parts.hostname.toLowerCase(),this.build(!c)),this},n.normalizePort=function(a){return"string"==typeof this._parts.protocol&&this._parts.port===e.defaultPorts[this._parts.protocol]&&(this._parts.port=null,this.build(!a)),this},n.normalizePath=function(a){if(this._parts.urn||!this._parts.path||"/"===this._parts.path)return this;var b,c,d,f=this._parts.path,g="";for("/"!==f.charAt(0)&&(b=!0,f="/"+f),f=f.replace(/(\/(\.\/)+)|(\/\.$)/g,"/").replace(/\/{2,}/g,"/"),b&&(g=f.substring(1).match(/^(\.\.\/)+/)||"")&&(g=g[0]);c=f.indexOf("/.."),-1!==c;)0!==c?(d=f.substring(0,c).lastIndexOf("/"),-1===d&&(d=c),f=f.substring(0,d)+f.substring(c+3)):f=f.substring(3);return b&&this.is("relative")&&(f=g+f.substring(1)),f=e.recodePath(f),this._parts.path=f,this.build(!a),this},n.normalizePathname=n.normalizePath,n.normalizeQuery=function(a){return"string"==typeof this._parts.query&&(this._parts.query.length?this.query(e.parseQuery(this._parts.query,this._parts.escapeQuerySpace)):this._parts.query=null,this.build(!a)),this},n.normalizeFragment=function(a){return this._parts.fragment||(this._parts.fragment=null,this.build(!a)),this},n.normalizeSearch=n.normalizeQuery,n.normalizeHash=n.normalizeFragment,n.iso8859=function(){var a=e.encode,b=e.decode;return e.encode=escape,e.decode=decodeURIComponent,this.normalize(),e.encode=a,e.decode=b,this},n.unicode=function(){var a=e.encode,b=e.decode;return e.encode=l,e.decode=unescape,this.normalize(),e.encode=a,e.decode=b,this},n.readable=function(){var b=this.clone();b.username("").password("").normalize();var c="";if(b._parts.protocol&&(c+=b._parts.protocol+"://"),b._parts.hostname&&(b.is("punycode")&&a?(c+=a.toUnicode(b._parts.hostname),b._parts.port&&(c+=":"+b._parts.port)):c+=b.host()),b._parts.hostname&&b._parts.path&&"/"!==b._parts.path.charAt(0)&&(c+="/"),c+=b.path(!0),b._parts.query){for(var d="",f=0,g=b._parts.query.split("&"),h=g.length;h>f;f++){var i=(g[f]||"").split("="),d=d+("&"+e.decodeQuery(i[0],this._parts.escapeQuerySpace).replace(/&/g,"%26"));void 0!==i[1]&&(d+="="+e.decodeQuery(i[1],this._parts.escapeQuerySpace).replace(/&/g,"%26"))}c+="?"+d.substring(1)}return c+=e.decodeQuery(b.hash(),!0)},n.absoluteTo=function(a){var b,c,d=this.clone(),f=["protocol","username","password","hostname","port"];if(this._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");if(a instanceof e||(a=new e(a)),d._parts.protocol||(d._parts.protocol=a._parts.protocol),this._parts.hostname)return d;for(b=0;c=f[b];b++)d._parts[c]=a._parts[c];return d._parts.path?".."===d._parts.path.substring(-2)&&(d._parts.path+="/"):(d._parts.path=a._parts.path,d._parts.query||(d._parts.query=a._parts.query)),"/"!==d.path().charAt(0)&&(a=a.directory(),d._parts.path=(a?a+"/":"")+d._parts.path,d.normalizePath()),d.build(),d},n.relativeTo=function(a){var b,c,d,f,g=this.clone().normalize();if(g._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");if(a=new e(a).normalize(),b=g._parts,c=a._parts,d=g.path(),f=a.path(),"/"!==d.charAt(0))throw Error("URI is already relative");if("/"!==f.charAt(0))throw Error("Cannot calculate a URI relative to another relative URI");return b.protocol===c.protocol&&(b.protocol=null),b.username!==c.username||b.password!==c.password||null!==b.protocol||null!==b.username||null!==b.password||b.hostname!==c.hostname||b.port!==c.port?g.build():(b.hostname=null,b.port=null,d===f?(b.path="",g.build()):(a=e.commonPath(g.path(),a.path()))?(c=c.path.substring(a.length).replace(/[^\/]*$/,"").replace(/.*?\//g,"../"),b.path=c+b.path.substring(a.length),g.build()):g.build())},n.equals=function(a){var b=this.clone();a=new e(a);var c,d={},f={},g={};if(b.normalize(),a.normalize(),b.toString()===a.toString())return!0;if(d=b.query(),f=a.query(),b.query(""),a.query(""),b.toString()!==a.toString()||d.length!==f.length)return!1;d=e.parseQuery(d,this._parts.escapeQuerySpace),f=e.parseQuery(f,this._parts.escapeQuerySpace);for(c in d)if(o.call(d,c)){if(h(d[c])){if(!j(d[c],f[c]))return!1}else if(d[c]!==f[c])return!1;g[c]=!0}for(c in f)if(o.call(f,c)&&!g[c])return!1;return!0},n.duplicateQueryParameters=function(a){return this._parts.duplicateQueryParameters=!!a,this},n.escapeQuerySpace=function(a){return this._parts.escapeQuerySpace=!!a,this},e}),function(a,b){"object"==typeof exports?module.exports=b(require("./URI")):"function"==typeof define&&define.amd?define(["./URI"],b):b(a.URI)}(this,function(a){var b=a.prototype,c=b.fragment;a.fragmentPrefix="?";var d=a._parts;return a._parts=function(){var b=d();return b.fragmentPrefix=a.fragmentPrefix,b},b.fragmentPrefix=function(a){return this._parts.fragmentPrefix=a,this},b.fragment=function(b,d){var e=this._parts.fragmentPrefix,f=this._parts.fragment||"";return!0===b?f.substring(0,e.length)!==e?{}:a.parseQuery(f.substring(e.length)):void 0!==b&&"string"!=typeof b?(this._parts.fragment=e+a.buildQuery(b),this.build(!d),this):c.call(this,b,d)},b.addFragment=function(b,c,d){var e=this._parts.fragmentPrefix,f=a.parseQuery((this._parts.fragment||"").substring(e.length));return a.addQuery(f,b,c),this._parts.fragment=e+a.buildQuery(f),"string"!=typeof b&&(d=c),this.build(!d),this},b.removeFragment=function(b,c,d){var e=this._parts.fragmentPrefix,f=a.parseQuery((this._parts.fragment||"").substring(e.length));return a.removeQuery(f,b,c),this._parts.fragment=e+a.buildQuery(f),"string"!=typeof b&&(d=c),this.build(!d),this},b.addHash=b.addFragment,b.removeHash=b.removeFragment,{}}),function(a){"use strict";function b(a){var c;if(null===a||void 0===a)return!1;if(d.isArray(a))return a.length>0;if("string"==typeof a||"number"==typeof a||"boolean"==typeof a)return!0;for(c in a)if(a.hasOwnProperty(c)&&b(a[c]))return!0;return!1}var c=function(){function a(a){this.options=a}return a.prototype.toString=function(){return JSON&&JSON.stringify?JSON.stringify(this.options):this.options},a}(),d=function(){function a(a){return"[object Array]"===Object.prototype.toString.apply(a)}function b(a){return"[object String]"===Object.prototype.toString.apply(a)}function c(a){return"[object Number]"===Object.prototype.toString.apply(a)}function d(a){return"[object Boolean]"===Object.prototype.toString.apply(a)}function e(a,b){var c,d="",e=!0;for(c=0;c<a.length;c+=1)e?e=!1:d+=b,d+=a[c];return d}function f(a,b){for(var c=[],d=0;d<a.length;d+=1)c.push(b(a[d]));return c}function g(a,b){for(var c=[],d=0;d<a.length;d+=1)b(a[d])&&c.push(a[d]);return c}function h(a){if("object"!=typeof a||null===a)return a;Object.freeze(a);var b,c;for(c in a)a.hasOwnProperty(c)&&(b=a[c],"object"!=typeof b||b instanceof RegExp||i(b));return a}function i(a){return"function"==typeof Object.freeze?h(a):a}return{isArray:a,isString:b,isNumber:c,isBoolean:d,join:e,map:f,filter:g,deepFreeze:i}}(),e=function(){function a(a){return a>="a"&&"z">=a||a>="A"&&"Z">=a}function b(a){return a>="0"&&"9">=a}function c(a){return b(a)||a>="a"&&"f">=a||a>="A"&&"F">=a}return{isAlpha:a,isDigit:b,isHexDigit:c}}(),f=function(){function a(a){var b,c,d="",e=g.encode(a);for(c=0;c<e.length;c+=1)b=e.charCodeAt(c),d+="%"+(16>b?"0":"")+b.toString(16).toUpperCase();return d}function b(a,b){return"%"===a.charAt(b)&&e.isHexDigit(a.charAt(b+1))&&e.isHexDigit(a.charAt(b+2))}function c(a,b){return parseInt(a.substr(b,2),16)}function d(a){if(!b(a,0))return!1;var d=c(a,1),e=g.numBytes(d);if(0===e)return!1;for(var f=1;e>f;f+=1)if(!b(a,3*f)||!g.isValidFollowingCharCode(c(a,3*f+1)))return!1;return!0}function f(a,d){var e=a.charAt(d);if(!b(a,d))return e;var f=c(a,d+1),h=g.numBytes(f);if(0===h)return e;for(var i=1;h>i;i+=1)if(!b(a,d+3*i)||!g.isValidFollowingCharCode(c(a,d+3*i+1)))return e;return a.substr(d,3*h)}var g={encode:function(a){return unescape(encodeURIComponent(a))},numBytes:function(a){return 127>=a?1:a>=194&&223>=a?2:a>=224&&239>=a?3:a>=240&&244>=a?4:0},isValidFollowingCharCode:function(a){return a>=128&&191>=a}};return{encodeCharacter:a,isPctEncoded:d,pctCharAt:f}}(),g=function(){function a(a){return e.isAlpha(a)||e.isDigit(a)||"_"===a||f.isPctEncoded(a)}function b(a){return e.isAlpha(a)||e.isDigit(a)||"-"===a||"."===a||"_"===a||"~"===a}function c(a){return":"===a||"/"===a||"?"===a||"#"===a||"["===a||"]"===a||"@"===a||"!"===a||"$"===a||"&"===a||"("===a||")"===a||"*"===a||"+"===a||","===a||";"===a||"="===a||"'"===a}return{isVarchar:a,isUnreserved:b,isReserved:c}}(),h=function(){function a(a,b){var c,d="",e="";for(("number"==typeof a||"boolean"==typeof a)&&(a=a.toString()),c=0;c<a.length;c+=e.length)e=a.charAt(c),d+=g.isUnreserved(e)||b&&g.isReserved(e)?e:f.encodeCharacter(e);return d}function b(b){return a(b,!0)}function c(a,b){var c=f.pctCharAt(a,b);return c.length>1?c:g.isReserved(c)||g.isUnreserved(c)?c:f.encodeCharacter(c)}function d(a){var b,c="",d="";for(b=0;b<a.length;b+=d.length)d=f.pctCharAt(a,b),c+=d.length>1?d:g.isReserved(d)||g.isUnreserved(d)?d:f.encodeCharacter(d);return c}return{encode:a,encodePassReserved:b,encodeLiteral:d,encodeLiteralCharacter:c}}(),i=function(){function a(a){b[a]={symbol:a,separator:"?"===a?"&":""===a||"+"===a||"#"===a?",":a,named:";"===a||"&"===a||"?"===a,ifEmpty:"&"===a||"?"===a?"=":"",first:"+"===a?"":a,encode:"+"===a||"#"===a?h.encodePassReserved:h.encode,toString:function(){return this.symbol}}}var b={};return a(""),a("+"),a("#"),a("."),a("/"),a(";"),a("?"),a("&"),{valueOf:function(a){return b[a]?b[a]:"=,!@|".indexOf(a)>=0?null:b[""]}}}(),j=function(){function a(a){this.literal=h.encodeLiteral(a)}return a.prototype.expand=function(){return this.literal},a.prototype.toString=a.prototype.expand,a}(),k=function(){function a(a){function b(){var b=a.substring(n,j);if(0===b.length)throw new c({expressionText:a,message:"a varname must be specified",position:j});m={varname:b,exploded:!1,maxLength:null},n=null}function d(){if(o===j)throw new c({expressionText:a,message:"after a ':' you have to specify the length",position:j});m.maxLength=parseInt(a.substring(o,j),10),o=null}var h,j,k=[],m=null,n=null,o=null,p="";for(h=function(b){var d=i.valueOf(b);if(null===d)throw new c({expressionText:a,message:"illegal use of reserved operator",position:j,operator:b});return d}(a.charAt(0)),j=h.symbol.length,n=j;j<a.length;j+=p.length){if(p=f.pctCharAt(a,j),null!==n){if("."===p){if(n===j)throw new c({expressionText:a,message:"a varname MUST NOT start with a dot",position:j});continue}if(g.isVarchar(p))continue;b()}if(null!==o){if(j===o&&"0"===p)throw new c({expressionText:a,message:"A :prefix must not start with digit 0",position:j});if(e.isDigit(p)){if(j-o>=4)throw new c({expressionText:a,message:"A :prefix must have max 4 digits",position:j});continue}d()}if(":"!==p)if("*"!==p){if(","!==p)throw new c({expressionText:a,message:"illegal character",character:p,position:j});k.push(m),m=null,n=j+1}else{if(null===m)throw new c({expressionText:a,message:"exploded without varspec",position:j});if(m.exploded)throw new c({expressionText:a,message:"exploded twice",position:j});if(m.maxLength)throw new c({expressionText:a,message:"an explode (*) MUST NOT follow to a prefix",position:j});m.exploded=!0}else{if(null!==m.maxLength)throw new c({expressionText:a,message:"only one :maxLength is allowed per varspec",position:j});if(m.exploded)throw new c({expressionText:a,message:"an exploeded varspec MUST NOT be varspeced",position:j});o=j+1}}return null!==n&&b(),null!==o&&d(),k.push(m),new l(a,h,k)}function b(a){return a.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function d(d){var e,f,g,h=[],i=null,k="",l=!0,n=0;for(e=0;e<d.length;e+=1)if(f=d.charAt(e),null===n){if(null===i)throw new Error("reached unreachable code");if("{"===f)throw new c({templateText:d,message:"brace already opened",position:e});if("}"===f){if(i+1===e)throw new c({templateText:d,message:"empty braces",position:i});try{g=a(d.substring(i+1,e))}catch(o){if(o.prototype===c.prototype)throw new c({templateText:d,message:o.options.message,position:i+o.options.position,details:o.options});throw o}h.push(g),0===g.operator.symbol.length?k+="([^/]+)":l=!1,i=null,n=e+1}}else{if("}"===f)throw new c({templateText:d,message:"unopened brace closed",position:e});"{"===f&&(e>n&&(g=new j(d.substring(n,e)),h.push(g),k+=b(g.literal)),n=null,i=e)}if(null!==i)throw new c({templateText:d,message:"unclosed brace",position:i});return n<d.length&&(g=new j(d.substring(n)),h.push(g),k+=b(g.literal)),l===!1&&(k=void 0),new m(d,h,k)}return d}(),l=function(){function a(a){return JSON&&JSON.stringify?JSON.stringify(a):a}function c(a){if(!b(a))return!0;if(d.isString(a))return""===a;if(d.isNumber(a)||d.isBoolean(a))return!1;if(d.isArray(a))return 0===a.length;for(var c in a)if(a.hasOwnProperty(c))return!1;return!0}function e(a){var b,c=[];for(b in a)a.hasOwnProperty(b)&&c.push({name:b,value:a[b]});return c}function f(a,b,c){this.templateText=a,this.operator=b,this.varspecs=c}function g(a,b,c){var d="";if(c=c.toString(),b.named){if(d+=h.encodeLiteral(a.varname),""===c)return d+=b.ifEmpty;d+="="}return null!==a.maxLength&&(c=c.substr(0,a.maxLength)),d+=b.encode(c)}function i(a){return b(a.value)}function j(a,f,g){var j=[],k="";if(f.named){if(k+=h.encodeLiteral(a.varname),c(g))return k+=f.ifEmpty;k+="="}return d.isArray(g)?(j=g,j=d.filter(j,b),j=d.map(j,f.encode),k+=d.join(j,",")):(j=e(g),j=d.filter(j,i),j=d.map(j,function(a){return f.encode(a.name)+","+f.encode(a.value)}),k+=d.join(j,",")),k}function k(a,f,g){var j=d.isArray(g),k=[];return j?(k=g,k=d.filter(k,b),k=d.map(k,function(b){var d=h.encodeLiteral(a.varname);return d+=c(b)?f.ifEmpty:"="+f.encode(b)})):(k=e(g),k=d.filter(k,i),k=d.map(k,function(a){var b=h.encodeLiteral(a.name);return b+=c(a.value)?f.ifEmpty:"="+f.encode(a.value)})),d.join(k,f.separator)}function l(a,c){var f=[],g="";return d.isArray(c)?(f=c,f=d.filter(f,b),f=d.map(f,a.encode),g+=d.join(f,a.separator)):(f=e(c),f=d.filter(f,function(a){return b(a.value)}),f=d.map(f,function(b){return a.encode(b.name)+"="+a.encode(b.value)}),g+=d.join(f,a.separator)),g}return f.prototype.toString=function(){return this.templateText},f.prototype.expand=function(e){var f,h,i,m,n=[],o=!1,p=this.operator;for(f=0;f<this.varspecs.length;f+=1)if(h=this.varspecs[f],i=e[h.varname],null!==i&&void 0!==i)if(h.exploded&&(o=!0),m=d.isArray(i),"string"==typeof i||"number"==typeof i||"boolean"==typeof i)n.push(g(h,p,i));else{if(h.maxLength&&b(i))throw new Error("Prefix modifiers are not applicable to variables that have composite values. You tried to expand "+this+" with "+a(i));h.exploded?b(i)&&(p.named?n.push(k(h,p,i)):n.push(l(p,i))):(p.named||!c(i))&&n.push(j(h,p,i))}return 0===n.length?"":p.first+d.join(n,p.separator)},f}(),m=function(){function a(a,b,c){this.templateText=a,this.expressions=b,void 0!==c&&(this.regexp=new RegExp("^"+c+"$")),d.deepFreeze(this)}return a.prototype.toString=function(){return this.templateText},a.prototype.expand=function(a){var b,c="";for(b=0;b<this.expressions.length;b+=1)c+=this.expressions[b].expand(a);return c},a.prototype.extract=function(a){var b,c,d,e,f=1,g=!0,h={};if(void 0!==this.regexp&&this.regexp.test(a)){for(e=this.regexp.exec(a),b=0;b<this.expressions.length;b+=1)c=this.expressions[b],void 0===c.literal&&(void 0!==c.operator&&0===c.operator.symbol.length&&1===c.varspecs.length?(d=c.varspecs[0],d.exploded===!1&&null===d.maxLength&&-1===e[f].indexOf(",")?(h[d.varname]=decodeURIComponent(e[f]),f+=1):g=!1):g=!1);if(g)return h}return!1},a.parse=k,a.UriTemplateError=c,a}();a(m)}(function(a){"use strict";"undefined"!=typeof module?module.exports=a:"function"==typeof define?define([],function(){return a}):"undefined"!=typeof window?window.UriTemplate=a:global.UriTemplate=a});var LZString=function(){function a(a,b){if(!e[a]){e[a]={};for(var c=0;c<a.length;c++)e[a][a.charAt(c)]=c}return e[a][b]}var b=String.fromCharCode,c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",e={},f={compressToBase64:function(a){if(null==a)return"";var b=f._compress(a,6,function(a){return c.charAt(a)});switch(b.length%4){default:case 0:return b;case 1:return b+"===";case 2:return b+"==";case 3:return b+"="}},decompressFromBase64:function(b){return null==b?"":""==b?null:f._decompress(b.length,32,function(d){return a(c,b.charAt(d))})},compressToUTF16:function(a){return null==a?"":f._compress(a,15,function(a){return b(a+32)})+" "},decompressFromUTF16:function(a){return null==a?"":""==a?null:f._decompress(a.length,16384,function(b){return a.charCodeAt(b)-32})},compressToUint8Array:function(a){for(var b=f.compress(a),c=new Uint8Array(2*b.length),d=0,e=b.length;e>d;d++){var g=b.charCodeAt(d);c[2*d]=g>>>8,c[2*d+1]=g%256}return c},decompressFromUint8Array:function(a){if(null===a||void 0===a)return f.decompress(a);for(var c=new Array(a.length/2),d=0,e=c.length;e>d;d++)c[d]=256*a[2*d]+a[2*d+1];var g=[];return c.forEach(function(a){g.push(b(a))}),f.decompress(g.join(""))},compressToEncodedURIComponent:function(a){return null==a?"":f._compress(a,6,function(a){return d.charAt(a)})},decompressFromEncodedURIComponent:function(b){return null==b?"":""==b?null:(b=b.replace(/ /g,"+"),f._decompress(b.length,32,function(c){return a(d,b.charAt(c))}))},compress:function(a){return f._compress(a,16,function(a){return b(a)})},_compress:function(a,b,c){if(null==a)return"";var d,e,f,g={},h={},i="",j="",k="",l=2,m=3,n=2,o=[],p=0,q=0;for(f=0;f<a.length;f+=1)if(i=a.charAt(f),Object.prototype.hasOwnProperty.call(g,i)||(g[i]=m++,h[i]=!0),j=k+i,Object.prototype.hasOwnProperty.call(g,j))k=j;else{if(Object.prototype.hasOwnProperty.call(h,k)){if(k.charCodeAt(0)<256){for(d=0;n>d;d++)p<<=1,q==b-1?(q=0,o.push(c(p)),p=0):q++;for(e=k.charCodeAt(0),d=0;8>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}else{for(e=1,d=0;n>d;d++)p=p<<1|e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e=0;for(e=k.charCodeAt(0),d=0;16>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}l--,0==l&&(l=Math.pow(2,n),n++),delete h[k]}else for(e=g[k],d=0;n>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1;l--,0==l&&(l=Math.pow(2,n),n++),g[j]=m++,k=String(i)}if(""!==k){if(Object.prototype.hasOwnProperty.call(h,k)){if(k.charCodeAt(0)<256){for(d=0;n>d;d++)p<<=1,q==b-1?(q=0,o.push(c(p)),p=0):q++;for(e=k.charCodeAt(0),d=0;8>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}else{for(e=1,d=0;n>d;d++)p=p<<1|e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e=0;for(e=k.charCodeAt(0),d=0;16>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1}l--,0==l&&(l=Math.pow(2,n),n++),delete h[k]}else for(e=g[k],d=0;n>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1;l--,0==l&&(l=Math.pow(2,n),n++)}for(e=2,d=0;n>d;d++)p=p<<1|1&e,q==b-1?(q=0,o.push(c(p)),p=0):q++,e>>=1;for(;;){if(p<<=1,q==b-1){o.push(c(p));break}q++}return o.join("")},decompress:function(a){return null==a?"":""==a?null:f._decompress(a.length,32768,function(b){return a.charCodeAt(b)})},_decompress:function(a,c,d){var e,f,g,h,i,j,k,l,m=[],n=4,o=4,p=3,q="",r=[],s={val:d(0),position:c,index:1};for(f=0;3>f;f+=1)m[f]=f;for(h=0,j=Math.pow(2,2),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;switch(e=h){case 0:for(h=0,j=Math.pow(2,8),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;l=b(h);break;case 1:for(h=0,j=Math.pow(2,16),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;l=b(h);break;case 2:return""}for(m[3]=l,g=l,r.push(l);;){if(s.index>a)return"";for(h=0,j=Math.pow(2,p),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;switch(l=h){case 0:for(h=0,j=Math.pow(2,8),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;m[o++]=b(h),l=o-1,n--;break;case 1:for(h=0,j=Math.pow(2,16),k=1;k!=j;)i=s.val&s.position,s.position>>=1,0==s.position&&(s.position=c,s.val=d(s.index++)),h|=(i>0?1:0)*k,k<<=1;m[o++]=b(h),l=o-1,n--;break;case 2:return r.join("")}if(0==n&&(n=Math.pow(2,p),p++),m[l])q=m[l];else{if(l!==o)return null;q=g+g.charAt(0)}r.push(q),m[o++]=g+q.charAt(0),n--,g=q,0==n&&(n=Math.pow(2,p),p++)}}};return f}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module&&(module.exports=LZString),function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return fd.apply(null,arguments)}function b(a){fd=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a);
+}function e(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function f(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function g(a,b){for(var c in b)f(b,c)&&(a[c]=b[c]);return f(b,"toString")&&(a.toString=b.toString),f(b,"valueOf")&&(a.valueOf=b.valueOf),a}function h(a,b,c,d){return Ja(a,b,c,d,!0).utc()}function i(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function j(a){return null==a._pf&&(a._pf=i()),a._pf}function k(a){if(null==a._isValid){var b=j(a),c=gd.call(b.parsedDateParts,function(a){return null!=a});a._isValid=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c),a._strict&&(a._isValid=a._isValid&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour)}return a._isValid}function l(a){var b=h(NaN);return null!=a?g(j(b),a):j(b).userInvalidated=!0,b}function m(a){return void 0===a}function n(a,b){var c,d,e;if(m(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),m(b._i)||(a._i=b._i),m(b._f)||(a._f=b._f),m(b._l)||(a._l=b._l),m(b._strict)||(a._strict=b._strict),m(b._tzm)||(a._tzm=b._tzm),m(b._isUTC)||(a._isUTC=b._isUTC),m(b._offset)||(a._offset=b._offset),m(b._pf)||(a._pf=j(b)),m(b._locale)||(a._locale=b._locale),hd.length>0)for(c in hd)d=hd[c],e=b[d],m(e)||(a[d]=e);return a}function o(b){n(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),id===!1&&(id=!0,a.updateOffset(this),id=!1)}function p(a){return a instanceof o||null!=a&&null!=a._isAMomentObject}function q(a){return 0>a?Math.ceil(a):Math.floor(a)}function r(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=q(b)),c}function s(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&r(a[d])!==r(b[d]))&&g++;return g+f}function t(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function u(b,c){var d=!0;return g(function(){return null!=a.deprecationHandler&&a.deprecationHandler(null,b),d&&(t(b+"\nArguments: "+Array.prototype.slice.call(arguments).join(", ")+"\n"+(new Error).stack),d=!1),c.apply(this,arguments)},c)}function v(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),jd[b]||(t(c),jd[b]=!0)}function w(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function x(a){return"[object Object]"===Object.prototype.toString.call(a)}function y(a){var b,c;for(c in a)b=a[c],w(b)?this[c]=b:this["_"+c]=b;this._config=a,this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function z(a,b){var c,d=g({},a);for(c in b)f(b,c)&&(x(a[c])&&x(b[c])?(d[c]={},g(d[c],a[c]),g(d[c],b[c])):null!=b[c]?d[c]=b[c]:delete d[c]);return d}function A(a){null!=a&&this.set(a)}function B(a){return a?a.toLowerCase().replace("_","-"):a}function C(a){for(var b,c,d,e,f=0;f<a.length;){for(e=B(a[f]).split("-"),b=e.length,c=B(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=D(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&s(e,c,!0)>=b-1)break;b--}f++}return null}function D(a){var b=null;if(!nd[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=ld._abbr,require("./locale/"+a),E(b)}catch(c){}return nd[a]}function E(a,b){var c;return a&&(c=m(b)?H(a):F(a,b),c&&(ld=c)),ld._abbr}function F(a,b){return null!==b?(b.abbr=a,null!=nd[a]?(v("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale"),b=z(nd[a]._config,b)):null!=b.parentLocale&&(null!=nd[b.parentLocale]?b=z(nd[b.parentLocale]._config,b):v("parentLocaleUndefined","specified parentLocale is not defined yet")),nd[a]=new A(b),E(a),nd[a]):(delete nd[a],null)}function G(a,b){if(null!=b){var c;null!=nd[a]&&(b=z(nd[a]._config,b)),c=new A(b),c.parentLocale=nd[a],nd[a]=c,E(a)}else null!=nd[a]&&(null!=nd[a].parentLocale?nd[a]=nd[a].parentLocale:null!=nd[a]&&delete nd[a]);return nd[a]}function H(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return ld;if(!c(a)){if(b=D(a))return b;a=[a]}return C(a)}function I(){return kd(nd)}function J(a,b){var c=a.toLowerCase();od[c]=od[c+"s"]=od[b]=a}function K(a){return"string"==typeof a?od[a]||od[a.toLowerCase()]:void 0}function L(a){var b,c,d={};for(c in a)f(a,c)&&(b=K(c),b&&(d[b]=a[c]));return d}function M(b,c){return function(d){return null!=d?(O(this,b,d),a.updateOffset(this,c),this):N(this,b)}}function N(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function O(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)}function P(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=K(a),w(this[a]))return this[a](b);return this}function Q(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function R(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(sd[a]=e),b&&(sd[b[0]]=function(){return Q(e.apply(this,arguments),b[1],b[2])}),c&&(sd[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function S(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function T(a){var b,c,d=a.match(pd);for(b=0,c=d.length;c>b;b++)sd[d[b]]?d[b]=sd[d[b]]:d[b]=S(d[b]);return function(b){var e,f="";for(e=0;c>e;e++)f+=d[e]instanceof Function?d[e].call(b,a):d[e];return f}}function U(a,b){return a.isValid()?(b=V(b,a.localeData()),rd[b]=rd[b]||T(b),rd[b](a)):a.localeData().invalidDate()}function V(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(qd.lastIndex=0;d>=0&&qd.test(a);)a=a.replace(qd,c),qd.lastIndex=0,d-=1;return a}function W(a,b,c){Kd[a]=w(b)?b:function(a,d){return a&&c?c:b}}function X(a,b){return f(Kd,a)?Kd[a](b._strict,b._locale):new RegExp(Y(a))}function Y(a){return Z(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function Z(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function $(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=r(a)}),c=0;c<a.length;c++)Ld[a[c]]=d}function _(a,b){$(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function aa(a,b,c){null!=b&&f(Ld,a)&&Ld[a](b,c._a,c,a)}function ba(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function ca(a,b){return c(this._months)?this._months[a.month()]:this._months[Vd.test(b)?"format":"standalone"][a.month()]}function da(a,b){return c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[Vd.test(b)?"format":"standalone"][a.month()]}function ea(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],d=0;12>d;++d)f=h([2e3,d]),this._shortMonthsParse[d]=this.monthsShort(f,"").toLocaleLowerCase(),this._longMonthsParse[d]=this.months(f,"").toLocaleLowerCase();return c?"MMM"===b?(e=md.call(this._shortMonthsParse,g),-1!==e?e:null):(e=md.call(this._longMonthsParse,g),-1!==e?e:null):"MMM"===b?(e=md.call(this._shortMonthsParse,g),-1!==e?e:(e=md.call(this._longMonthsParse,g),-1!==e?e:null)):(e=md.call(this._longMonthsParse,g),-1!==e?e:(e=md.call(this._shortMonthsParse,g),-1!==e?e:null))}function fa(a,b,c){var d,e,f;if(this._monthsParseExact)return ea.call(this,a,b,c);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function ga(a,b){var c;if(!a.isValid())return a;if("string"==typeof b)if(/^\d+$/.test(b))b=r(b);else if(b=a.localeData().monthsParse(b),"number"!=typeof b)return a;return c=Math.min(a.date(),ba(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ha(b){return null!=b?(ga(this,b),a.updateOffset(this,!0),this):N(this,"Month")}function ia(){return ba(this.year(),this.month())}function ja(a){return this._monthsParseExact?(f(this,"_monthsRegex")||la.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex}function ka(a){return this._monthsParseExact?(f(this,"_monthsRegex")||la.call(this),a?this._monthsStrictRegex:this._monthsRegex):this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex}function la(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;12>b;b++)c=h([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for(d.sort(a),e.sort(a),f.sort(a),b=0;12>b;b++)d[b]=Z(d[b]),e[b]=Z(e[b]),f[b]=Z(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")","i")}function ma(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[Nd]<0||c[Nd]>11?Nd:c[Od]<1||c[Od]>ba(c[Md],c[Nd])?Od:c[Pd]<0||c[Pd]>24||24===c[Pd]&&(0!==c[Qd]||0!==c[Rd]||0!==c[Sd])?Pd:c[Qd]<0||c[Qd]>59?Qd:c[Rd]<0||c[Rd]>59?Rd:c[Sd]<0||c[Sd]>999?Sd:-1,j(a)._overflowDayOfYear&&(Md>b||b>Od)&&(b=Od),j(a)._overflowWeeks&&-1===b&&(b=Td),j(a)._overflowWeekday&&-1===b&&(b=Ud),j(a).overflow=b),a}function na(a){var b,c,d,e,f,g,h=a._i,i=$d.exec(h)||_d.exec(h);if(i){for(j(a).iso=!0,b=0,c=be.length;c>b;b++)if(be[b][1].exec(i[1])){e=be[b][0],d=be[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=ce.length;c>b;b++)if(ce[b][1].exec(i[3])){f=(i[2]||" ")+ce[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!ae.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),Ca(a)}else a._isValid=!1}function oa(b){var c=de.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(na(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function pa(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 100>a&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function qa(a){var b=new Date(Date.UTC.apply(null,arguments));return 100>a&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b}function ra(a){return sa(a)?366:365}function sa(a){return a%4===0&&a%100!==0||a%400===0}function ta(){return sa(this.year())}function ua(a,b,c){var d=7+b-c,e=(7+qa(a,0,d).getUTCDay()-b)%7;return-e+d-1}function va(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ua(a,d,e),j=1+7*(b-1)+h+i;return 0>=j?(f=a-1,g=ra(f)+j):j>ra(a)?(f=a+1,g=j-ra(a)):(f=a,g=j),{year:f,dayOfYear:g}}function wa(a,b,c){var d,e,f=ua(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return 1>g?(e=a.year()-1,d=g+xa(e,b,c)):g>xa(a.year(),b,c)?(d=g-xa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function xa(a,b,c){var d=ua(a,b,c),e=ua(a+1,b,c);return(ra(a)-d+e)/7}function ya(a,b,c){return null!=a?a:null!=b?b:c}function za(b){var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]}function Aa(a){var b,c,d,e,f=[];if(!a._d){for(d=za(a),a._w&&null==a._a[Od]&&null==a._a[Nd]&&Ba(a),a._dayOfYear&&(e=ya(a._a[Md],d[Md]),a._dayOfYear>ra(e)&&(j(a)._overflowDayOfYear=!0),c=qa(e,0,a._dayOfYear),a._a[Nd]=c.getUTCMonth(),a._a[Od]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[Pd]&&0===a._a[Qd]&&0===a._a[Rd]&&0===a._a[Sd]&&(a._nextDay=!0,a._a[Pd]=0),a._d=(a._useUTC?qa:pa).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[Pd]=24)}}function Ba(a){var b,c,d,e,f,g,h,i;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=ya(b.GG,a._a[Md],wa(Ka(),1,4).year),d=ya(b.W,1),e=ya(b.E,1),(1>e||e>7)&&(i=!0)):(f=a._locale._week.dow,g=a._locale._week.doy,c=ya(b.gg,a._a[Md],wa(Ka(),f,g).year),d=ya(b.w,1),null!=b.d?(e=b.d,(0>e||e>6)&&(i=!0)):null!=b.e?(e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):e=f),1>d||d>xa(c,f,g)?j(a)._overflowWeeks=!0:null!=i?j(a)._overflowWeekday=!0:(h=va(c,d,e,f,g),a._a[Md]=h.year,a._dayOfYear=h.dayOfYear)}function Ca(b){if(b._f===a.ISO_8601)return void na(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=V(b._f,b._locale).match(pd)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(X(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),sd[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),aa(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[Pd]<=12&&b._a[Pd]>0&&(j(b).bigHour=void 0),j(b).parsedDateParts=b._a.slice(0),j(b).meridiem=b._meridiem,b._a[Pd]=Da(b._locale,b._a[Pd],b._meridiem),Aa(b),ma(b)}function Da(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function Ea(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=n({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],Ca(b),k(b)&&(f+=j(b).charsLeftOver,f+=10*j(b).unusedTokens.length,j(b).score=f,(null==d||d>f)&&(d=f,c=b));g(a,c||b)}function Fa(a){if(!a._d){var b=L(a._i);a._a=e([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),Aa(a)}}function Ga(a){var b=new o(ma(Ha(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function Ha(a){var b=a._i,e=a._f;return a._locale=a._locale||H(a._l),null===b||void 0===e&&""===b?l({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),p(b)?new o(ma(b)):(c(e)?Ea(a):e?Ca(a):d(b)?a._d=b:Ia(a),k(a)||(a._d=null),a))}function Ia(b){var f=b._i;void 0===f?b._d=new Date(a.now()):d(f)?b._d=new Date(f.valueOf()):"string"==typeof f?oa(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),Aa(b)):"object"==typeof f?Fa(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function Ja(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,Ga(f)}function Ka(a,b,c,d){return Ja(a,b,c,d,!1)}function La(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Ka();for(d=b[0],e=1;e<b.length;++e)(!b[e].isValid()||b[e][a](d))&&(d=b[e]);return d}function Ma(){var a=[].slice.call(arguments,0);return La("isBefore",a)}function Na(){var a=[].slice.call(arguments,0);return La("isAfter",a)}function Oa(a){var b=L(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+1e3*h*60*60,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=H(),this._bubble()}function Pa(a){return a instanceof Oa}function Qa(a,b){R(a,0,0,function(){var a=this.utcOffset(),c="+";return 0>a&&(a=-a,c="-"),c+Q(~~(a/60),2)+b+Q(~~a%60,2)})}function Ra(a,b){var c=(b||"").match(a)||[],d=c[c.length-1]||[],e=(d+"").match(ie)||["-",0,0],f=+(60*e[1])+r(e[2]);return"+"===e[0]?f:-f}function Sa(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(p(b)||d(b)?b.valueOf():Ka(b).valueOf())-e.valueOf(),e._d.setTime(e._d.valueOf()+f),a.updateOffset(e,!1),e):Ka(b).local()}function Ta(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Ua(b,c){var d,e=this._offset||0;return this.isValid()?null!=b?("string"==typeof b?b=Ra(Hd,b):Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ta(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?jb(this,db(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ta(this):null!=b?this:NaN}function Va(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Wa(a){return this.utcOffset(0,a)}function Xa(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ta(this),"m")),this}function Ya(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ra(Gd,this._i)),this}function Za(a){return this.isValid()?(a=a?Ka(a).utcOffset():0,(this.utcOffset()-a)%60===0):!1}function $a(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function _a(){if(!m(this._isDSTShifted))return this._isDSTShifted;var a={};if(n(a,this),a=Ha(a),a._a){var b=a._isUTC?h(a._a):Ka(a._a);this._isDSTShifted=this.isValid()&&s(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function ab(){return this.isValid()?!this._isUTC:!1}function bb(){return this.isValid()?this._isUTC:!1}function cb(){return this.isValid()?this._isUTC&&0===this._offset:!1}function db(a,b){var c,d,e,g=a,h=null;return Pa(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=je.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:r(h[Od])*c,h:r(h[Pd])*c,m:r(h[Qd])*c,s:r(h[Rd])*c,ms:r(h[Sd])*c}):(h=ke.exec(a))?(c="-"===h[1]?-1:1,g={y:eb(h[2],c),M:eb(h[3],c),w:eb(h[4],c),d:eb(h[5],c),h:eb(h[6],c),m:eb(h[7],c),s:eb(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=gb(Ka(g.from),Ka(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Oa(g),Pa(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function eb(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function fb(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function gb(a,b){var c;return a.isValid()&&b.isValid()?(b=Sa(b,a),a.isBefore(b)?c=fb(a,b):(c=fb(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}function hb(a){return 0>a?-1*Math.round(-1*a):Math.round(a)}function ib(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(v(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=db(c,d),jb(this,e,a),this}}function jb(b,c,d,e){var f=c._milliseconds,g=hb(c._days),h=hb(c._months);b.isValid()&&(e=null==e?!0:e,f&&b._d.setTime(b._d.valueOf()+f*d),g&&O(b,"Date",N(b,"Date")+g*d),h&&ga(b,N(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function kb(a,b){var c=a||Ka(),d=Sa(c,this).startOf("day"),e=this.diff(d,"days",!0),f=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse",g=b&&(w(b[f])?b[f]():b[f]);return this.format(g||this.localeData().calendar(f,this,Ka(c)))}function lb(){return new o(this)}function mb(a,b){var c=p(a)?a:Ka(a);return this.isValid()&&c.isValid()?(b=K(m(b)?"millisecond":b),"millisecond"===b?this.valueOf()>c.valueOf():c.valueOf()<this.clone().startOf(b).valueOf()):!1}function nb(a,b){var c=p(a)?a:Ka(a);return this.isValid()&&c.isValid()?(b=K(m(b)?"millisecond":b),"millisecond"===b?this.valueOf()<c.valueOf():this.clone().endOf(b).valueOf()<c.valueOf()):!1}function ob(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!this.isBefore(a,c))&&(")"===d[1]?this.isBefore(b,c):!this.isAfter(b,c))}function pb(a,b){var c,d=p(a)?a:Ka(a);return this.isValid()&&d.isValid()?(b=K(b||"millisecond"),"millisecond"===b?this.valueOf()===d.valueOf():(c=d.valueOf(),this.clone().startOf(b).valueOf()<=c&&c<=this.clone().endOf(b).valueOf())):!1}function qb(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function rb(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function sb(a,b,c){var d,e,f,g;return this.isValid()?(d=Sa(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=K(b),"year"===b||"month"===b||"quarter"===b?(g=tb(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:q(g)):NaN):NaN}function tb(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)||0}function ub(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function vb(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?w(Date.prototype.toISOString)?this.toDate().toISOString():U(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):U(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function wb(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var c=U(this,b);return this.localeData().postformat(c)}function xb(a,b){return this.isValid()&&(p(a)&&a.isValid()||Ka(a).isValid())?db({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function yb(a){return this.from(Ka(),a)}function zb(a,b){return this.isValid()&&(p(a)&&a.isValid()||Ka(a).isValid())?db({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function Ab(a){return this.to(Ka(),a)}function Bb(a){var b;return void 0===a?this._locale._abbr:(b=H(a),null!=b&&(this._locale=b),this)}function Cb(){return this._locale}function Db(a){switch(a=K(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function Eb(a){return a=K(a),void 0===a||"millisecond"===a?this:("date"===a&&(a="day"),this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms"))}function Fb(){return this._d.valueOf()-6e4*(this._offset||0)}function Gb(){return Math.floor(this.valueOf()/1e3)}function Hb(){return this._offset?new Date(this.valueOf()):this._d}function Ib(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function Jb(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function Kb(){return this.isValid()?this.toISOString():null}function Lb(){return k(this)}function Mb(){return g({},j(this))}function Nb(){return j(this).overflow}function Ob(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Pb(a,b){R(0,[a,a.length],0,b)}function Qb(a){return Ub.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function Rb(a){return Ub.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Sb(){return xa(this.year(),1,4)}function Tb(){var a=this.localeData()._week;return xa(this.year(),a.dow,a.doy)}function Ub(a,b,c,d,e){var f;return null==a?wa(this,d,e).year:(f=xa(a,d,e),b>f&&(b=f),Vb.call(this,a,b,c,d,e))}function Vb(a,b,c,d,e){var f=va(a,b,c,d,e),g=qa(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this}function Wb(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}function Xb(a){return wa(a,this._week.dow,this._week.doy).week}function Yb(){return this._week.dow}function Zb(){return this._week.doy}function $b(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function _b(a){var b=wa(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function ac(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function bc(a,b){return c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]}function cc(a){return this._weekdaysShort[a.day()]}function dc(a){return this._weekdaysMin[a.day()]}function ec(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],d=0;7>d;++d)f=h([2e3,1]).day(d),this._minWeekdaysParse[d]=this.weekdaysMin(f,"").toLocaleLowerCase(),this._shortWeekdaysParse[d]=this.weekdaysShort(f,"").toLocaleLowerCase(),this._weekdaysParse[d]=this.weekdays(f,"").toLocaleLowerCase();return c?"dddd"===b?(e=md.call(this._weekdaysParse,g),-1!==e?e:null):"ddd"===b?(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:null):(e=md.call(this._minWeekdaysParse,g),-1!==e?e:null):"dddd"===b?(e=md.call(this._weekdaysParse,g),-1!==e?e:(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:(e=md.call(this._minWeekdaysParse,g),-1!==e?e:null))):"ddd"===b?(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:(e=md.call(this._weekdaysParse,g),-1!==e?e:(e=md.call(this._minWeekdaysParse,g),-1!==e?e:null))):(e=md.call(this._minWeekdaysParse,g),-1!==e?e:(e=md.call(this._weekdaysParse,g),-1!==e?e:(e=md.call(this._shortWeekdaysParse,g),-1!==e?e:null)))}function fc(a,b,c){var d,e,f;if(this._weekdaysParseExact)return ec.call(this,a,b,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;7>d;d++){if(e=h([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}}function gc(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=ac(a,this.localeData()),this.add(a-b,"d")):b}function hc(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function ic(a){return this.isValid()?null==a?this.day()||7:this.day(this.day()%7?a:a-7):null!=a?this:NaN}function jc(a){return this._weekdaysParseExact?(f(this,"_weekdaysRegex")||mc.call(this),a?this._weekdaysStrictRegex:this._weekdaysRegex):this._weekdaysStrictRegex&&a?this._weekdaysStrictRegex:this._weekdaysRegex}function kc(a){return this._weekdaysParseExact?(f(this,"_weekdaysRegex")||mc.call(this),a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):this._weekdaysShortStrictRegex&&a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex}function lc(a){return this._weekdaysParseExact?(f(this,"_weekdaysRegex")||mc.call(this),a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):this._weekdaysMinStrictRegex&&a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex}function mc(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[],i=[],j=[],k=[];for(b=0;7>b;b++)c=h([2e3,1]).day(b),d=this.weekdaysMin(c,""),e=this.weekdaysShort(c,""),f=this.weekdays(c,""),g.push(d),i.push(e),j.push(f),k.push(d),k.push(e),k.push(f);for(g.sort(a),i.sort(a),j.sort(a),k.sort(a),b=0;7>b;b++)i[b]=Z(i[b]),j[b]=Z(j[b]),k[b]=Z(k[b]);this._weekdaysRegex=new RegExp("^("+k.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+j.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+g.join("|")+")","i")}function nc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function oc(){return this.hours()%12||12}function pc(){return this.hours()||24}function qc(a,b){R(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function rc(a,b){return b._meridiemParse}function sc(a){return"p"===(a+"").toLowerCase().charAt(0)}function tc(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function uc(a,b){b[Sd]=r(1e3*("0."+a))}function vc(){return this._isUTC?"UTC":""}function wc(){return this._isUTC?"Coordinated Universal Time":""}function xc(a){return Ka(1e3*a)}function yc(){return Ka.apply(null,arguments).parseZone()}function zc(a,b,c){var d=this._calendar[a];return w(d)?d.call(b,c):d}function Ac(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function Bc(){return this._invalidDate}function Cc(a){return this._ordinal.replace("%d",a)}function Dc(a){return a}function Ec(a,b,c,d){var e=this._relativeTime[c];return w(e)?e(a,b,c,d):e.replace(/%d/i,a)}function Fc(a,b){var c=this._relativeTime[a>0?"future":"past"];return w(c)?c(b):c.replace(/%s/i,b)}function Gc(a,b,c,d){var e=H(),f=h().set(d,b);return e[c](f,a)}function Hc(a,b,c){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return Gc(a,b,c,"month");var d,e=[];for(d=0;12>d;d++)e[d]=Gc(a,d,c,"month");return e}function Ic(a,b,c,d){"boolean"==typeof a?("number"==typeof b&&(c=b,b=void 0),b=b||""):(b=a,c=b,a=!1,"number"==typeof b&&(c=b,b=void 0),b=b||"");var e=H(),f=a?e._week.dow:0;if(null!=c)return Gc(b,(c+f)%7,d,"day");var g,h=[];for(g=0;7>g;g++)h[g]=Gc(b,(g+f)%7,d,"day");return h}function Jc(a,b){return Hc(a,b,"months")}function Kc(a,b){return Hc(a,b,"monthsShort")}function Lc(a,b,c){return Ic(a,b,c,"weekdays")}function Mc(a,b,c){return Ic(a,b,c,"weekdaysShort")}function Nc(a,b,c){return Ic(a,b,c,"weekdaysMin")}function Oc(){var a=this._data;return this._milliseconds=Le(this._milliseconds),this._days=Le(this._days),this._months=Le(this._months),a.milliseconds=Le(a.milliseconds),a.seconds=Le(a.seconds),a.minutes=Le(a.minutes),a.hours=Le(a.hours),a.months=Le(a.months),a.years=Le(a.years),this}function Pc(a,b,c,d){var e=db(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function Qc(a,b){return Pc(this,a,b,1)}function Rc(a,b){return Pc(this,a,b,-1)}function Sc(a){return 0>a?Math.floor(a):Math.ceil(a)}function Tc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*Sc(Vc(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=q(f/1e3),i.seconds=a%60,b=q(a/60),i.minutes=b%60,c=q(b/60),i.hours=c%24,g+=q(c/24),e=q(Uc(g)),h+=e,g-=Sc(Vc(e)),d=q(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function Uc(a){return 4800*a/146097}function Vc(a){return 146097*a/4800}function Wc(a){var b,c,d=this._milliseconds;if(a=K(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+Uc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(Vc(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function Xc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*r(this._months/12)}function Yc(a){return function(){return this.as(a)}}function Zc(a){return a=K(a),this[a+"s"]()}function $c(a){return function(){return this._data[a]}}function _c(){return q(this.days()/7)}function ad(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function bd(a,b,c){var d=db(a).abs(),e=_e(d.as("s")),f=_e(d.as("m")),g=_e(d.as("h")),h=_e(d.as("d")),i=_e(d.as("M")),j=_e(d.as("y")),k=e<af.s&&["s",e]||1>=f&&["m"]||f<af.m&&["mm",f]||1>=g&&["h"]||g<af.h&&["hh",g]||1>=h&&["d"]||h<af.d&&["dd",h]||1>=i&&["M"]||i<af.M&&["MM",i]||1>=j&&["y"]||["yy",j];
+return k[2]=b,k[3]=+a>0,k[4]=c,ad.apply(null,k)}function cd(a,b){return void 0===af[a]?!1:void 0===b?af[a]:(af[a]=b,!0)}function dd(a){var b=this.localeData(),c=bd(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function ed(){var a,b,c,d=bf(this._milliseconds)/1e3,e=bf(this._days),f=bf(this._months);a=q(d/60),b=q(a/60),d%=60,a%=60,c=q(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var fd,gd;gd=Array.prototype.some?Array.prototype.some:function(a){for(var b=Object(this),c=b.length>>>0,d=0;c>d;d++)if(d in b&&a.call(this,b[d],d,b))return!0;return!1};var hd=a.momentProperties=[],id=!1,jd={};a.suppressDeprecationWarnings=!1,a.deprecationHandler=null;var kd;kd=Object.keys?Object.keys:function(a){var b,c=[];for(b in a)f(a,b)&&c.push(b);return c};var ld,md,nd={},od={},pd=/(\[[^\[]*\])|(\\)?([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,qd=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,rd={},sd={},td=/\d/,ud=/\d\d/,vd=/\d{3}/,wd=/\d{4}/,xd=/[+-]?\d{6}/,yd=/\d\d?/,zd=/\d\d\d\d?/,Ad=/\d\d\d\d\d\d?/,Bd=/\d{1,3}/,Cd=/\d{1,4}/,Dd=/[+-]?\d{1,6}/,Ed=/\d+/,Fd=/[+-]?\d+/,Gd=/Z|[+-]\d\d:?\d\d/gi,Hd=/Z|[+-]\d\d(?::?\d\d)?/gi,Id=/[+-]?\d+(\.\d{1,3})?/,Jd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Kd={},Ld={},Md=0,Nd=1,Od=2,Pd=3,Qd=4,Rd=5,Sd=6,Td=7,Ud=8;md=Array.prototype.indexOf?Array.prototype.indexOf:function(a){var b;for(b=0;b<this.length;++b)if(this[b]===a)return b;return-1},R("M",["MM",2],"Mo",function(){return this.month()+1}),R("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),R("MMMM",0,0,function(a){return this.localeData().months(this,a)}),J("month","M"),W("M",yd),W("MM",yd,ud),W("MMM",function(a,b){return b.monthsShortRegex(a)}),W("MMMM",function(a,b){return b.monthsRegex(a)}),$(["M","MM"],function(a,b){b[Nd]=r(a)-1}),$(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[Nd]=e:j(c).invalidMonth=a});var Vd=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/,Wd="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Xd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),Yd=Jd,Zd=Jd,$d=/^\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)?)?/,_d=/^\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)?)?/,ae=/Z|[+-]\d\d(?::?\d\d)?/,be=[["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/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],ce=[["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/]],de=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=u("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),R("Y",0,0,function(){var a=this.year();return 9999>=a?""+a:"+"+a}),R(0,["YY",2],0,function(){return this.year()%100}),R(0,["YYYY",4],0,"year"),R(0,["YYYYY",5],0,"year"),R(0,["YYYYYY",6,!0],0,"year"),J("year","y"),W("Y",Fd),W("YY",yd,ud),W("YYYY",Cd,wd),W("YYYYY",Dd,xd),W("YYYYYY",Dd,xd),$(["YYYYY","YYYYYY"],Md),$("YYYY",function(b,c){c[Md]=2===b.length?a.parseTwoDigitYear(b):r(b)}),$("YY",function(b,c){c[Md]=a.parseTwoDigitYear(b)}),$("Y",function(a,b){b[Md]=parseInt(a,10)}),a.parseTwoDigitYear=function(a){return r(a)+(r(a)>68?1900:2e3)};var ee=M("FullYear",!0);a.ISO_8601=function(){};var fe=u("moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Ka.apply(null,arguments);return this.isValid()&&a.isValid()?this>a?this:a:l()}),ge=u("moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Ka.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:l()}),he=function(){return Date.now?Date.now():+new Date};Qa("Z",":"),Qa("ZZ",""),W("Z",Hd),W("ZZ",Hd),$(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ra(Hd,a)});var ie=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var je=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/,ke=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;db.fn=Oa.prototype;var le=ib(1,"add"),me=ib(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var ne=u("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});R(0,["gg",2],0,function(){return this.weekYear()%100}),R(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Pb("gggg","weekYear"),Pb("ggggg","weekYear"),Pb("GGGG","isoWeekYear"),Pb("GGGGG","isoWeekYear"),J("weekYear","gg"),J("isoWeekYear","GG"),W("G",Fd),W("g",Fd),W("GG",yd,ud),W("gg",yd,ud),W("GGGG",Cd,wd),W("gggg",Cd,wd),W("GGGGG",Dd,xd),W("ggggg",Dd,xd),_(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=r(a)}),_(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),R("Q",0,"Qo","quarter"),J("quarter","Q"),W("Q",td),$("Q",function(a,b){b[Nd]=3*(r(a)-1)}),R("w",["ww",2],"wo","week"),R("W",["WW",2],"Wo","isoWeek"),J("week","w"),J("isoWeek","W"),W("w",yd),W("ww",yd,ud),W("W",yd),W("WW",yd,ud),_(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=r(a)});var oe={dow:0,doy:6};R("D",["DD",2],"Do","date"),J("date","D"),W("D",yd),W("DD",yd,ud),W("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),$(["D","DD"],Od),$("Do",function(a,b){b[Od]=r(a.match(yd)[0],10)});var pe=M("Date",!0);R("d",0,"do","day"),R("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),R("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),R("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),R("e",0,0,"weekday"),R("E",0,0,"isoWeekday"),J("day","d"),J("weekday","e"),J("isoWeekday","E"),W("d",yd),W("e",yd),W("E",yd),W("dd",function(a,b){return b.weekdaysMinRegex(a)}),W("ddd",function(a,b){return b.weekdaysShortRegex(a)}),W("dddd",function(a,b){return b.weekdaysRegex(a)}),_(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict);null!=e?b.d=e:j(c).invalidWeekday=a}),_(["d","e","E"],function(a,b,c,d){b[d]=r(a)});var qe="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),re="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),se="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),te=Jd,ue=Jd,ve=Jd;R("DDD",["DDDD",3],"DDDo","dayOfYear"),J("dayOfYear","DDD"),W("DDD",Bd),W("DDDD",vd),$(["DDD","DDDD"],function(a,b,c){c._dayOfYear=r(a)}),R("H",["HH",2],0,"hour"),R("h",["hh",2],0,oc),R("k",["kk",2],0,pc),R("hmm",0,0,function(){return""+oc.apply(this)+Q(this.minutes(),2)}),R("hmmss",0,0,function(){return""+oc.apply(this)+Q(this.minutes(),2)+Q(this.seconds(),2)}),R("Hmm",0,0,function(){return""+this.hours()+Q(this.minutes(),2)}),R("Hmmss",0,0,function(){return""+this.hours()+Q(this.minutes(),2)+Q(this.seconds(),2)}),qc("a",!0),qc("A",!1),J("hour","h"),W("a",rc),W("A",rc),W("H",yd),W("h",yd),W("HH",yd,ud),W("hh",yd,ud),W("hmm",zd),W("hmmss",Ad),W("Hmm",zd),W("Hmmss",Ad),$(["H","HH"],Pd),$(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),$(["h","hh"],function(a,b,c){b[Pd]=r(a),j(c).bigHour=!0}),$("hmm",function(a,b,c){var d=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d)),j(c).bigHour=!0}),$("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d,2)),b[Rd]=r(a.substr(e)),j(c).bigHour=!0}),$("Hmm",function(a,b,c){var d=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d))}),$("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[Pd]=r(a.substr(0,d)),b[Qd]=r(a.substr(d,2)),b[Rd]=r(a.substr(e))});var we=/[ap]\.?m?\.?/i,xe=M("Hours",!0);R("m",["mm",2],0,"minute"),J("minute","m"),W("m",yd),W("mm",yd,ud),$(["m","mm"],Qd);var ye=M("Minutes",!1);R("s",["ss",2],0,"second"),J("second","s"),W("s",yd),W("ss",yd,ud),$(["s","ss"],Rd);var ze=M("Seconds",!1);R("S",0,0,function(){return~~(this.millisecond()/100)}),R(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),R(0,["SSS",3],0,"millisecond"),R(0,["SSSS",4],0,function(){return 10*this.millisecond()}),R(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),R(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),R(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),R(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),R(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),J("millisecond","ms"),W("S",Bd,td),W("SS",Bd,ud),W("SSS",Bd,vd);var Ae;for(Ae="SSSS";Ae.length<=9;Ae+="S")W(Ae,Ed);for(Ae="S";Ae.length<=9;Ae+="S")$(Ae,uc);var Be=M("Milliseconds",!1);R("z",0,0,"zoneAbbr"),R("zz",0,0,"zoneName");var Ce=o.prototype;Ce.add=le,Ce.calendar=kb,Ce.clone=lb,Ce.diff=sb,Ce.endOf=Eb,Ce.format=wb,Ce.from=xb,Ce.fromNow=yb,Ce.to=zb,Ce.toNow=Ab,Ce.get=P,Ce.invalidAt=Nb,Ce.isAfter=mb,Ce.isBefore=nb,Ce.isBetween=ob,Ce.isSame=pb,Ce.isSameOrAfter=qb,Ce.isSameOrBefore=rb,Ce.isValid=Lb,Ce.lang=ne,Ce.locale=Bb,Ce.localeData=Cb,Ce.max=ge,Ce.min=fe,Ce.parsingFlags=Mb,Ce.set=P,Ce.startOf=Db,Ce.subtract=me,Ce.toArray=Ib,Ce.toObject=Jb,Ce.toDate=Hb,Ce.toISOString=vb,Ce.toJSON=Kb,Ce.toString=ub,Ce.unix=Gb,Ce.valueOf=Fb,Ce.creationData=Ob,Ce.year=ee,Ce.isLeapYear=ta,Ce.weekYear=Qb,Ce.isoWeekYear=Rb,Ce.quarter=Ce.quarters=Wb,Ce.month=ha,Ce.daysInMonth=ia,Ce.week=Ce.weeks=$b,Ce.isoWeek=Ce.isoWeeks=_b,Ce.weeksInYear=Tb,Ce.isoWeeksInYear=Sb,Ce.date=pe,Ce.day=Ce.days=gc,Ce.weekday=hc,Ce.isoWeekday=ic,Ce.dayOfYear=nc,Ce.hour=Ce.hours=xe,Ce.minute=Ce.minutes=ye,Ce.second=Ce.seconds=ze,Ce.millisecond=Ce.milliseconds=Be,Ce.utcOffset=Ua,Ce.utc=Wa,Ce.local=Xa,Ce.parseZone=Ya,Ce.hasAlignedHourOffset=Za,Ce.isDST=$a,Ce.isDSTShifted=_a,Ce.isLocal=ab,Ce.isUtcOffset=bb,Ce.isUtc=cb,Ce.isUTC=cb,Ce.zoneAbbr=vc,Ce.zoneName=wc,Ce.dates=u("dates accessor is deprecated. Use date instead.",pe),Ce.months=u("months accessor is deprecated. Use month instead",ha),Ce.years=u("years accessor is deprecated. Use year instead",ee),Ce.zone=u("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Va);var De=Ce,Ee={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Fe={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"},Ge="Invalid date",He="%d",Ie=/\d{1,2}/,Je={future:"in %s",past:"%s ago",s:"a few 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"},Ke=A.prototype;Ke._calendar=Ee,Ke.calendar=zc,Ke._longDateFormat=Fe,Ke.longDateFormat=Ac,Ke._invalidDate=Ge,Ke.invalidDate=Bc,Ke._ordinal=He,Ke.ordinal=Cc,Ke._ordinalParse=Ie,Ke.preparse=Dc,Ke.postformat=Dc,Ke._relativeTime=Je,Ke.relativeTime=Ec,Ke.pastFuture=Fc,Ke.set=y,Ke.months=ca,Ke._months=Wd,Ke.monthsShort=da,Ke._monthsShort=Xd,Ke.monthsParse=fa,Ke._monthsRegex=Zd,Ke.monthsRegex=ka,Ke._monthsShortRegex=Yd,Ke.monthsShortRegex=ja,Ke.week=Xb,Ke._week=oe,Ke.firstDayOfYear=Zb,Ke.firstDayOfWeek=Yb,Ke.weekdays=bc,Ke._weekdays=qe,Ke.weekdaysMin=dc,Ke._weekdaysMin=se,Ke.weekdaysShort=cc,Ke._weekdaysShort=re,Ke.weekdaysParse=fc,Ke._weekdaysRegex=te,Ke.weekdaysRegex=jc,Ke._weekdaysShortRegex=ue,Ke.weekdaysShortRegex=kc,Ke._weekdaysMinRegex=ve,Ke.weekdaysMinRegex=lc,Ke.isPM=sc,Ke._meridiemParse=we,Ke.meridiem=tc,E("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===r(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=u("moment.lang is deprecated. Use moment.locale instead.",E),a.langData=u("moment.langData is deprecated. Use moment.localeData instead.",H);var Le=Math.abs,Me=Yc("ms"),Ne=Yc("s"),Oe=Yc("m"),Pe=Yc("h"),Qe=Yc("d"),Re=Yc("w"),Se=Yc("M"),Te=Yc("y"),Ue=$c("milliseconds"),Ve=$c("seconds"),We=$c("minutes"),Xe=$c("hours"),Ye=$c("days"),Ze=$c("months"),$e=$c("years"),_e=Math.round,af={s:45,m:45,h:22,d:26,M:11},bf=Math.abs,cf=Oa.prototype;cf.abs=Oc,cf.add=Qc,cf.subtract=Rc,cf.as=Wc,cf.asMilliseconds=Me,cf.asSeconds=Ne,cf.asMinutes=Oe,cf.asHours=Pe,cf.asDays=Qe,cf.asWeeks=Re,cf.asMonths=Se,cf.asYears=Te,cf.valueOf=Xc,cf._bubble=Tc,cf.get=Zc,cf.milliseconds=Ue,cf.seconds=Ve,cf.minutes=We,cf.hours=Xe,cf.days=Ye,cf.weeks=_c,cf.months=Ze,cf.years=$e,cf.humanize=dd,cf.toISOString=ed,cf.toString=ed,cf.toJSON=ed,cf.locale=Bb,cf.localeData=Cb,cf.toIsoString=u("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ed),cf.lang=ne,R("X",0,0,"unix"),R("x",0,0,"valueOf"),W("x",Fd),W("X",Id),$("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),$("x",function(a,b,c){c._d=new Date(r(a))}),a.version="2.13.0",b(Ka),a.fn=De,a.min=Ma,a.max=Na,a.now=he,a.utc=h,a.unix=xc,a.months=Jc,a.isDate=d,a.locale=E,a.invalid=l,a.duration=db,a.isMoment=p,a.weekdays=Lc,a.parseZone=yc,a.localeData=H,a.isDuration=Pa,a.monthsShort=Kc,a.weekdaysMin=Nc,a.defineLocale=F,a.updateLocale=G,a.locales=I,a.weekdaysShort=Mc,a.normalizeUnits=K,a.relativeTimeThreshold=cd,a.prototype=De;var df=a;return df}),function(a,b,c){"use strict";function d(a){var b,c=[];if(void 0===a)return void 0;for(Array.isArray(a)||(a=[a]),b=0;b<a.length;b+=1)"object"==typeof a[b]?c[b]=a[b].content:c[b]=a[b];return c}function e(a,b){var c;if("descending"===b)c=1;else{if("ascending"!==b)throw new TypeError("Query.sortFunction(): Argument 2 must be 'ascending' or 'descending'");c=-1}return function(b,e){var f,g;for(b=d(b[a])||[],e=d(e[a])||[],g=b.length>e.length?b.length:e.length,f=0;g>f;f+=1){if(void 0===b[f])return c;if(void 0===e[f])return-c;if(b[f]>e[f])return-c;if(b[f]<e[f])return c}return 0}}function f(a,b){var c;if(!Array.isArray(a))throw new TypeError("jioquery.sortOn(): Argument 1 is not of type 'array'");for(c=a.length-1;c>=0;c-=1)b.sort(e(a[c][0],a[c][1]));return b}function g(a,b){if(!Array.isArray(a))throw new TypeError("jioquery.limit(): Argument 1 is not of type 'array'");if(!Array.isArray(b))throw new TypeError("jioquery.limit(): Argument 2 is not of type 'array'");return b.splice(0,a[0]),a[1]&&b.splice(a[1]),b}function h(a,b){var c,d,e;if(!Array.isArray(a))throw new TypeError("jioquery.select(): Argument 1 is not of type Array");if(!Array.isArray(b))throw new TypeError("jioquery.select(): Argument 2 is not of type Array");for(c=0;c<b.length;c+=1){for(e={},d=0;d<a.length;d+=1)b[c].hasOwnProperty([a[d]])&&(e[a[d]]=b[c][a[d]]);for(d in e)if(e.hasOwnProperty(d)){b[c]=e;break}}return b}function i(){}function j(){}function k(a){return a.replace(t,"\\$&")}function l(a,b){a.super_=b,a.prototype=Object.create(b.prototype,{constructor:{configurable:!0,enumerable:!1,writable:!0,value:a}})}function m(a,b){if("string"!=typeof a)throw new TypeError("jioquery.searchTextToRegExp(): Argument 1 is not of type 'string'");return b===!1?new RegExp("^"+k(a)+"$"):new RegExp("^"+k(a).replace(u,".*").replace(v,".")+"$")}function n(a,b){i.call(this),this.operator=a.operator,this.query_list=a.query_list||[],this.query_list=this.query_list.map(function(a){return j.create(a,b)})}function o(a){var b=[];if("complex"===a.type)return b.push("("),(a.query_list||[]).forEach(function(c){b.push(o(c)),b.push(a.operator)}),b.length-=1,b.push(")"),b.join(" ");if("simple"===a.type)return(a.key?a.key+": ":"")+(a.operator||"")+' "'+a.value+'"';throw new TypeError("This object is not a query")}function p(a){var b;if(void 0!==a){if("object"!=typeof a)throw new TypeError("SimpleQuery().create(): key_schema is not of type 'object'");if(void 0===a.key_set)throw new TypeError("SimpleQuery().create(): key_schema has no 'key_set' property");for(b in a)if(a.hasOwnProperty(b))switch(b){case"key_set":case"cast_lookup":case"match_lookup":break;default:throw new TypeError("SimpleQuery().create(): key_schema has unknown property '"+b+"'")}}}function q(a,b){i.call(this),p(b),this._key_schema=b||{},this.operator=a.operator,this.key=a.key,this.value=a.value}function r(a){var b;if(void 0===a.read_from)throw new TypeError("Custom key is missing the read_from property");for(b in a)if(a.hasOwnProperty(b))switch(b){case"read_from":case"cast_to":case"equal_match":break;default:throw new TypeError("Custom key has unknown property '"+b+"'")}}var s={},t=/[\-\[\]{}()*+?.,\\\^$|#\s]/g,u=/%/g,v=/_/g,w=/^(?:AND|OR|NOT)$/i,x=/^(?:!?=|<=?|>=?)$/i;i.prototype.exec=function(b,c){if(!Array.isArray(b))throw new TypeError("Query().exec(): Argument 1 is not of type 'array'");if(void 0===c&&(c={}),"object"!=typeof c)throw new TypeError("Query().exec(): Optional argument 2 is not of type 'object'");var d,e=this;for(d=b.length-1;d>=0;d-=1)e.match(b[d])||b.splice(d,1);return c.sort_on&&f(c.sort_on,b),c.limit&&g(c.limit,b),h(c.select_list||[],b),(new a.Queue).push(function(){return b})},i.prototype.match=function(){return!0},i.prototype.parse=function(b){function c(b,d){function f(a){i.push(function(){return b.parsed=h.query_list[a],c(b,d)}).push(function(){h.query_list[a]=b.parsed})}var g,h=b.parsed,i=new a.Queue;if("complex"===h.type){for(g=0;g<h.query_list.length;g+=1)f(g);return i.push(function(){return b.parsed=h,e.onParseComplexQuery(b,d)})}return"simple"===h.type?e.onParseSimpleQuery(b,d):void 0}var d,e=this;return d={parsed:JSON.parse(JSON.stringify(e.serialized()))},(new a.Queue).push(function(){return e.onParseStart(d,b)}).push(function(){return c(d,b)}).push(function(){return e.onParseEnd(d,b)}).push(function(){return d.parsed})},i.prototype.toString=function(){return""},i.prototype.serialized=function(){return void 0},l(n,i),n.prototype.operator="AND",n.prototype.type="complex",n.prototype.match=function(a){var b=this.operator;return w.test(b)||(b="AND"),this[b.toUpperCase()](a)},n.prototype.toString=function(){var a=[],b=this.operator;return"NOT"===this.operator?(a.push("NOT ("),a.push(this.query_list[0].toString()),a.push(")"),a.join(" ")):(this.query_list.forEach(function(c){a.push("("),a.push(c.toString()),a.push(")"),a.push(b)}),a.length-=1,a.join(" "))},n.prototype.serialized=function(){var a={type:"complex",operator:this.operator,query_list:[]};return this.query_list.forEach(function(b){a.query_list.push("function"==typeof b.toJSON?b.toJSON():b)}),a},n.prototype.toJSON=n.prototype.serialized,n.prototype.AND=function(a){for(var b=!0,c=0;b&&c!==this.query_list.length;)b=this.query_list[c].match(a),c+=1;return b},n.prototype.OR=function(a){for(var b=!1,c=0;!b&&c!==this.query_list.length;)b=this.query_list[c].match(a),c+=1;return b},n.prototype.NOT=function(a){return!this.query_list[0].match(a)},j.create=function(a,b){if(""===a)return new i;if("string"==typeof a&&(a=c(a)),"string"==typeof(a||{}).type&&s[a.type])return new s[a.type](a,b);throw new TypeError("QueryFactory.create(): Argument 1 is not a search text or a parsable object")},l(q,i),q.prototype.type="simple",q.prototype.match=function(a){var b=null,c=null,d=null,e=null,f=this.operator,g=null,h=this.key;if(x.test(f)||(f=u.test(this.value)?"like":"="),e=this[f],this._key_schema.key_set&&void 0!==this._key_schema.key_set[h]&&(h=this._key_schema.key_set[h]),"object"==typeof h){if(r(h),b=a[h.read_from],c=h.equal_match,"string"==typeof c&&(c=this._key_schema.match_lookup[c]),void 0!==c&&(e="="===f||"like"===f?c:e),g=this.value,d=h.cast_to){"string"==typeof d&&(d=this._key_schema.cast_lookup[d]);try{g=d(g)}catch(i){g=void 0}try{b=d(b)}catch(i){b=void 0}}}else b=a[h],g=this.value;return void 0===b||void 0===g?!1:e(b,g)},q.prototype.toString=function(){return(this.key?this.key+":":"")+(this.operator?" "+this.operator:"")+' "'+this.value+'"'},q.prototype.serialized=function(){var a={type:"simple",key:this.key,value:this.value};return void 0!==this.operator&&(a.operator=this.operator),a},q.prototype.toJSON=q.prototype.serialized,q.prototype["="]=function(a,b){var c,d;for(Array.isArray(a)||(a=[a]),d=0;d<a.length;d+=1){if(c=a[d],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp)return 0===c.cmp(b);if(b.toString()===c.toString())return!0}return!1},q.prototype.like=function(a,b){var c,d;for(Array.isArray(a)||(a=[a]),d=0;d<a.length;d+=1){if(c=a[d],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp)return 0===c.cmp(b);if(m(b.toString()).test(c.toString()))return!0}return!1},q.prototype["!="]=function(a,b){var c,d;for(Array.isArray(a)||(a=[a]),d=0;d<a.length;d+=1){if(c=a[d],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp)return 0!==c.cmp(b);if(b.toString()===c.toString())return!1}return!0},q.prototype["<"]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)<0:b>c},q.prototype["<="]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)<=0:b>=c},q.prototype[">"]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)>0:c>b},q.prototype[">="]=function(a,b){var c;return Array.isArray(a)||(a=[a]),c=a[0],"object"==typeof c&&c.hasOwnProperty("content")&&(c=c.content),"function"==typeof c.cmp?c.cmp(b)>=0:c>=b},s.simple=q,s.complex=n,i.parseStringToObject=c,i.objectToSearchText=o,b.Query=i,b.SimpleQuery=q,b.ComplexQuery=n,b.QueryFactory=j}(RSVP,window,parseStringToObject),function(a,b){"use strict";var c,d="year",e="month",f="day",g="hour",h="minute",i="second",j="millisecond",k={year:0,month:1,day:2,hour:3,minute:4,second:5,millisecond:6},l=function(a,b){return k[a]<k[b]?a:b};c=function(a){if(!(this instanceof c))return new c(a);if(a instanceof c)return this.mom=a.mom.clone(),void(this._precision=a._precision);if(void 0===a)return this.mom=b(),void this.setPrecision(j);if(this.mom=null,this._str=a,a.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+\-][0-2]\d:[0-5]\d|Z)/)||a.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\.\d\d\d/)?(this.mom=b(a),this.setPrecision(j)):a.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+\-][0-2]\d:[0-5]\d|Z)/)||a.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/)?(this.mom=b(a),this.setPrecision(i)):a.match(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+\-][0-2]\d:[0-5]\d|Z)/)||a.match(/\d\d\d\d-\d\d-\d\d \d\d:\d\d/)?(this.mom=b(a),this.setPrecision(h)):a.match(/\d\d\d\d-\d\d-\d\d \d\d/)?(this.mom=b(a),this.setPrecision(g)):a.match(/\d\d\d\d-\d\d-\d\d/)?(this.mom=b(a),this.setPrecision(f)):a.match(/\d\d\d\d-\d\d/)?(this.mom=b(a),this.setPrecision(e)):a.match(/\d\d\d\d/)&&(this.mom=b(a,"YYYY"),this.setPrecision(d)),!this.mom)throw new Error("Cannot parse: "+a)},c.prototype.setPrecision=function(a){this._precision=a},c.prototype.getPrecision=function(){return this._precision},c.prototype.cmp=function(a){var b=this.mom,c=a.mom,d=l(this._precision,a._precision);return b.isBefore(c,d)?-1:b.isSame(c,d)?0:1},c.prototype.toPrecisionString=function(a){var b;if(a=a||this._precision,b={millisecond:"YYYY-MM-DD HH:mm:ss.SSS",second:"YYYY-MM-DD HH:mm:ss",minute:"YYYY-MM-DD HH:mm",hour:"YYYY-MM-DD HH",day:"YYYY-MM-DD",month:"YYYY-MM",year:"YYYY"}[a],!b)throw new TypeError("Unsupported precision value '"+a+"'");return this.mom.format(b)},c.prototype.toString=function(){return this._str},a.jiodate={JIODate:c,YEAR:d,MONTH:e,DAY:f,HOUR:g,MIN:h,SEC:i,MSEC:j}}(window,moment),function(a,b,c,d,e,f,g,h,i){"use strict";function j(a,b){if(void 0!==a&&"string"!=typeof a)throw new TypeError("You must pass a string.");this.message=a||"Default Message",this.status_code=b||500}function k(a){var c=new XMLHttpRequest;return new b.Promise(function(b,d,e){var f;if(c.open(a.type||"GET",a.url,!0),c.responseType=a.dataType||"","object"==typeof a.headers&&null!==a.headers)for(f in a.headers)a.headers.hasOwnProperty(f)&&c.setRequestHeader(f,a.headers[f]);if(c.addEventListener("load",function(a){return a.target.status>=400?d(a):void b(a)}),c.addEventListener("error",d),c.addEventListener("progress",e),"object"==typeof a.xhrFields&&null!==a.xhrFields)for(f in a.xhrFields)a.xhrFields.hasOwnProperty(f)&&(c[f]=a.xhrFields[f]);"function"==typeof a.beforeSend&&a.beforeSend(c),c.send(a.data)},function(){c.abort()})}function l(a,c){var d=new g;return new b.Promise(function(b,e,f){d.addEventListener("load",b),d.addEventListener("error",e),d.addEventListener("progress",f),d.readAsText(a,c)},function(){d.abort()})}function m(a){var c=new g;return new b.Promise(function(b,d,e){c.addEventListener("load",b),c.addEventListener("error",d),c.addEventListener("progress",e),c.readAsArrayBuffer(a)},function(){c.abort()})}function n(a){var c=new g;return new b.Promise(function(b,d,e){c.addEventListener("load",b),c.addEventListener("error",d),c.addEventListener("progress",e),c.readAsDataURL(a)},function(){c.abort()})}function o(a){var b,d=f(a.split(",")[1]),e=a.split(",")[0].split(":")[1],g=new h(d.length),j=new i(g);for(e=e.slice(0,e.length-";base64".length),b=0;b<d.length;b+=1)j[b]=d.charCodeAt(b);return new c([g],{type:e})}function p(a,b,c){if("string"!=typeof a[0]||""===a[0])throw new u.util.jIOError("Document id must be a non empty string on '"+b.__type+"."+c+"'.",400)}function q(a,b,c){if("string"!=typeof a[1]||""===a[1])throw new u.util.jIOError("Attachment id must be a non empty string on '"+b.__type+"."+c+"'.",400)}function r(a,c,d,e){return a.prototype[c]=function(){var a,f=arguments,g=this;return(new b.Queue).push(function(){return void 0!==d?d.apply(g.__storage,[f,g,c]):void 0}).push(function(b){var d=g.__storage[c];if(a=b,void 0===d)throw new u.util.jIOError("Capacity '"+c+"' is not implemented on '"+g.__type+"'",501);return d.apply(g.__storage,f)}).push(function(b){return void 0!==e?e.call(g,f,b,a):b})},this}function s(a,b){return this instanceof s?(this.__type=a,void(this.__storage=b)):new s}function t(){return this instanceof t?void(this.__storage_types={}):new t}var u,v={};j.prototype=new Error,j.prototype.constructor=j,v.jIOError=j,v.ajax=k,v.readBlobAsText=l,v.readBlobAsArrayBuffer=m,v.readBlobAsDataURL=n,v.dataURItoBlob=o,r(s,"put",p,function(a){return a[0]}),r(s,"get",p),r(s,"bulk"),r(s,"remove",p,function(a){return a[0]}),s.prototype.post=function(){var a=this,c=arguments;return(new b.Queue).push(function(){var b=a.__storage.post;if(void 0===b)throw new u.util.jIOError("Capacity 'post' is not implemented on '"+a.__type+"'",501);return a.__storage.post.apply(a.__storage,c)})},r(s,"putAttachment",function(a,b,d){p(a,b,d),q(a,b,d);var e=a[3]||{};if("string"==typeof a[2])a[2]=new c([a[2]],{type:e._content_type||e._mimetype||"text/plain;charset=utf-8"});else if(!(a[2]instanceof c))throw new u.util.jIOError("Attachment content is not a blob",400)}),r(s,"removeAttachment",function(a,b,c){p(a,b,c),q(a,b,c)}),r(s,"getAttachment",function(a,b,c){var d="blob";return p(a,b,c),q(a,b,c),void 0!==a[2]&&(d=a[2].format||d,delete a[2].format),d},function(a,d,e){var f;if(!(d instanceof c))throw new u.util.jIOError("'getAttachment' ("+a[0]+" , "+a[1]+") on '"+this.__type+"' does not return a Blob.",501);if("blob"===e)f=d;else if("data_url"===e)f=(new b.Queue).push(function(){return u.util.readBlobAsDataURL(d)}).push(function(a){return a.target.result});else if("array_buffer"===e)f=(new b.Queue).push(function(){return u.util.readBlobAsArrayBuffer(d)}).push(function(a){return a.target.result});else if("text"===e)f=(new b.Queue).push(function(){return u.util.readBlobAsText(d)}).push(function(a){return a.target.result});else{if("json"!==e)throw new u.util.jIOError(this.__type+".getAttachment format: '"+e+"' is not supported",400);f=(new b.Queue).push(function(){return u.util.readBlobAsText(d)}).push(function(a){return JSON.parse(a.target.result)})}return f}),s.prototype.buildQuery=function(){var a=this.__storage.buildQuery,c=this,d=arguments;if(void 0===a)throw new u.util.jIOError("Capacity 'buildQuery' is not implemented on '"+this.__type+"'",501);return(new b.Queue).push(function(){return a.apply(c.__storage,d)})},s.prototype.hasCapacity=function(a){var b=this.__storage.hasCapacity,c=this.__storage[a];if(void 0!==c)return!0;if(void 0===b||!b.apply(this.__storage,arguments))throw new u.util.jIOError("Capacity '"+a+"' is not implemented on '"+this.__type+"'",501);return!0},s.prototype.allDocs=function(a){var c=this;return void 0===a&&(a={}),(new b.Queue).push(function(){return!c.hasCapacity("list")||void 0!==a.query&&!c.hasCapacity("query")||void 0!==a.sort_on&&!c.hasCapacity("sort")||void 0!==a.select_list&&!c.hasCapacity("select")||void 0!==a.include_docs&&!c.hasCapacity("include")||void 0!==a.limit&&!c.hasCapacity("limit")?void 0:c.buildQuery(a)}).push(function(a){return{data:{rows:a,total_rows:a.length}}})},r(s,"allAttachments",p),r(s,"repair"),s.prototype.repair=function(){var a=this,c=arguments;return(new b.Queue).push(function(){var b=a.__storage.repair;return void 0!==b?a.__storage.repair.apply(a.__storage,c):void 0})},t.prototype.createJIO=function(a,b){if("string"!=typeof a.type)throw new TypeError("Invalid storage description");if(!this.__storage_types[a.type])throw new TypeError("Unknown storage '"+a.type+"'");return new s(a.type,new this.__storage_types[a.type](a,b))},t.prototype.addStorage=function(a,b){if("string"!=typeof a)throw new TypeError("jIO.addStorage(): Argument 1 is not of type 'string'");if("function"!=typeof b)throw new TypeError("jIO.addStorage(): Argument 2 is not of type 'function'");if(void 0!==this.__storage_types[a])throw new TypeError("jIO.addStorage(): Storage type already exists");this.__storage_types[a]=b},t.prototype.util=v,t.prototype.QueryFactory=d,t.prototype.Query=e,u=new t,a.jIO=u}(window,RSVP,Blob,QueryFactory,Query,atob,FileReader,ArrayBuffer,Uint8Array),function(){function a(a){"use strict";var d={fill:0},f=function(a){for(a+=9;a%64>0;a+=1);return a},g=function(a,b){for(var c=b>>2;c<a.length;c++)a[c]=0},h=function(a,b,c){a[b>>2]|=128<<24-(b%4<<3),a[((b>>2)+2&-16)+14]=c>>29,a[((b>>2)+2&-16)+15]=c<<3},i=function(a,b,c,d,e){var f,g=this,h=e%4,i=d%4,j=d-i;if(j>0)switch(h){case 0:a[e+3|0]=g.charCodeAt(c);case 1:a[e+2|0]=g.charCodeAt(c+1);case 2:a[e+1|0]=g.charCodeAt(c+2);case 3:a[0|e]=g.charCodeAt(c+3)}for(f=h;j>f;f=f+4|0)b[e+f>>2]=g.charCodeAt(c+f)<<24|g.charCodeAt(c+f+1)<<16|g.charCodeAt(c+f+2)<<8|g.charCodeAt(c+f+3);switch(i){case 3:a[e+j+1|0]=g.charCodeAt(c+j+2);case 2:a[e+j+2|0]=g.charCodeAt(c+j+1);case 1:a[e+j+3|0]=g.charCodeAt(c+j)}},j=function(a,b,c,d,e){var f,g=this,h=e%4,i=d%4,j=d-i;if(j>0)switch(h){case 0:a[e+3|0]=g[c];case 1:a[e+2|0]=g[c+1];case 2:a[e+1|0]=g[c+2];case 3:a[0|e]=g[c+3]}for(f=4-h;j>f;f=f+=4)b[e+f>>2]=g[c+f]<<24|g[c+f+1]<<16|g[c+f+2]<<8|g[c+f+3];switch(i){case 3:a[e+j+1|0]=g[c+j+2];case 2:a[e+j+2|0]=g[c+j+1];case 1:a[e+j+3|0]=g[c+j]}},k=function(a,b,d,e,f){var g,h=this,i=f%4,j=e%4,k=e-j,l=new Uint8Array(c.readAsArrayBuffer(h.slice(d,d+e)));if(k>0)switch(i){case 0:a[f+3|0]=l[0];case 1:a[f+2|0]=l[1];case 2:a[f+1|0]=l[2];case 3:a[0|f]=l[3]}for(g=4-i;k>g;g=g+=4)b[f+g>>2]=l[g]<<24|l[g+1]<<16|l[g+2]<<8|l[g+3];switch(j){case 3:a[f+k+1|0]=l[k+2];case 2:a[f+k+2|0]=l[k+1];case 1:a[f+k+3|0]=l[k]}},l=function(a){switch(e.getDataType(a)){case"string":
+return i.bind(a);case"array":return j.bind(a);case"buffer":return j.bind(a);case"arraybuffer":return j.bind(new Uint8Array(a));case"view":return j.bind(new Uint8Array(a.buffer,a.byteOffset,a.byteLength));case"blob":return k.bind(a)}},m=function(a){var b,c,d="0123456789abcdef",e=[],f=new Uint8Array(a);for(b=0;b<f.length;b++)c=f[b],e[b]=d.charAt(c>>4&15)+d.charAt(c>>0&15);return e.join("")},n=function(a){var b;if(65536>=a)return 65536;if(16777216>a)for(b=1;a>b;b<<=1);else for(b=16777216;a>b;b+=16777216);return b},o=function(a){if(a%64>0)throw new Error("Chunk size must be a multiple of 128 bit");d.maxChunkLen=a,d.padMaxChunkLen=f(a),d.heap=new ArrayBuffer(n(d.padMaxChunkLen+320+20)),d.h32=new Int32Array(d.heap),d.h8=new Int8Array(d.heap),d.core=b({Int32Array:Int32Array,DataView:DataView},{},d.heap),d.buffer=null};o(a||65536);var p=function(a,b){var c=new Int32Array(a,b+320,5);c[0]=1732584193,c[1]=-271733879,c[2]=-1732584194,c[3]=271733878,c[4]=-1009589776},q=function(a,b){var c=f(a),e=new Int32Array(d.heap,0,c>>2);return g(e,a),h(e,a,b),c},r=function(a,b,c){l(a)(d.h8,d.h32,b,c,0)},s=function(a,b,c,e,f){var g=c;f&&(g=q(c,e)),r(a,b,c),d.core.hash(g,d.padMaxChunkLen)},t=function(a,b){var c=new Int32Array(a,b+320,5),d=new Int32Array(5),e=new DataView(d.buffer);return e.setInt32(0,c[0],!1),e.setInt32(4,c[1],!1),e.setInt32(8,c[2],!1),e.setInt32(12,c[3],!1),e.setInt32(16,c[4],!1),d},u=this.rawDigest=function(a){var b=a.byteLength||a.length||a.size||0;p(d.heap,d.padMaxChunkLen);var c=0,e=d.maxChunkLen;for(c=0;b>c+e;c+=e)s(a,c,e,b,!1);return s(a,c,b-c,b,!0),t(d.heap,d.padMaxChunkLen)};this.digest=this.digestFromString=this.digestFromBuffer=this.digestFromArrayBuffer=function(a){return m(u(a).buffer)}}function b(a,b,c){"use asm";function d(a,b){a|=0,b|=0;var c=0,d=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;for(f=e[b+320>>2]|0,h=e[b+324>>2]|0,j=e[b+328>>2]|0,l=e[b+332>>2]|0,n=e[b+336>>2]|0,c=0;(c|0)<(a|0);c=c+64|0){for(g=f,i=h,k=j,m=l,o=n,d=0;(d|0)<64;d=d+4|0)q=e[c+d>>2]|0,p=((f<<5|f>>>27)+(h&j|~h&l)|0)+((q+n|0)+1518500249|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[a+d>>2]=q;for(d=a+64|0;(d|0)<(a+80|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h&j|~h&l)|0)+((q+n|0)+1518500249|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+80|0;(d|0)<(a+160|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h^j^l)|0)+((q+n|0)+1859775393|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+160|0;(d|0)<(a+240|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h&j|h&l|j&l)|0)+((q+n|0)-1894007588|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+240|0;(d|0)<(a+320|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h^j^l)|0)+((q+n|0)-899497514|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;f=f+g|0,h=h+i|0,j=j+k|0,l=l+m|0,n=n+o|0}e[b+320>>2]=f,e[b+324>>2]=h,e[b+328>>2]=j,e[b+332>>2]=l,e[b+336>>2]=n}var e=new a.Int32Array(c);return{hash:d}}if("undefined"!=typeof module?module.exports=a:"undefined"!=typeof window&&(window.Rusha=a),"undefined"!=typeof FileReaderSync){var c=new FileReaderSync,d=new a(4194304);self.onmessage=function(a){var b,c=a.data.data;try{b=d.digest(c),self.postMessage({id:a.data.id,hash:b})}catch(e){self.postMessage({id:a.data.id,error:e.name})}}}var e={getDataType:function(a){if("string"==typeof a)return"string";if(a instanceof Array)return"array";if("undefined"!=typeof global&&global.Buffer&&global.Buffer.isBuffer(a))return"buffer";if(a instanceof ArrayBuffer)return"arraybuffer";if(a.buffer instanceof ArrayBuffer)return"view";if(a instanceof Blob)return"blob";throw new Error("Unsupported data type.")}}}(),function(a,b,c){"use strict";function d(a){return f.digestFromString(a)}function e(b){if(this._query_options=b.query||{},this._local_sub_storage=a.createJIO(b.local_sub_storage),this._remote_sub_storage=a.createJIO(b.remote_sub_storage),this._signature_hash="_replicate_"+d(JSON.stringify(b.local_sub_storage)+JSON.stringify(b.remote_sub_storage)+JSON.stringify(this._query_options)),this._signature_sub_storage=a.createJIO({type:"document",document_id:this._signature_hash,sub_storage:b.local_sub_storage}),this._use_remote_post=b.use_remote_post||!1,this._conflict_handling=b.conflict_handling||0,this._conflict_handling!==g&&this._conflict_handling!==h&&this._conflict_handling!==i&&this._conflict_handling!==j)throw new a.util.jIOError("Unsupported conflict handling: "+this._conflict_handling,400);this._check_local_modification=b.check_local_modification,void 0===this._check_local_modification&&(this._check_local_modification=!0),this._check_local_creation=b.check_local_creation,void 0===this._check_local_creation&&(this._check_local_creation=!0),this._check_local_deletion=b.check_local_deletion,void 0===this._check_local_deletion&&(this._check_local_deletion=!0),this._check_remote_modification=b.check_remote_modification,void 0===this._check_remote_modification&&(this._check_remote_modification=!0),this._check_remote_creation=b.check_remote_creation,void 0===this._check_remote_creation&&(this._check_remote_creation=!0),this._check_remote_deletion=b.check_remote_deletion,void 0===this._check_remote_deletion&&(this._check_remote_deletion=!0)}var f=new c,g=0,h=1,i=2,j=3;e.prototype.remove=function(b){if(b===this._signature_hash)throw new a.util.jIOError(this._signature_hash+" is frozen",403);return this._local_sub_storage.remove.apply(this._local_sub_storage,arguments)},e.prototype.post=function(){return this._local_sub_storage.post.apply(this._local_sub_storage,arguments)},e.prototype.put=function(b){if(b===this._signature_hash)throw new a.util.jIOError(this._signature_hash+" is frozen",403);return this._local_sub_storage.put.apply(this._local_sub_storage,arguments)},e.prototype.get=function(){return this._local_sub_storage.get.apply(this._local_sub_storage,arguments)},e.prototype.hasCapacity=function(){return this._local_sub_storage.hasCapacity.apply(this._local_sub_storage,arguments)},e.prototype.buildQuery=function(){return this._local_sub_storage.buildQuery.apply(this._local_sub_storage,arguments)},e.prototype.repair=function(){function c(a,b,c,d,e,f){var g,h,i=!0;return void 0===f&&(f={}),g=f.use_post?b.post(c).push(function(b){return i=!1,h=b,a.put(h,c)}).push(function(){return a.remove(e)}).push(function(){return n._signature_sub_storage.remove(e)}).push(function(){return i=!0,n._signature_sub_storage.put(h,{hash:d})}).push(function(){p[h]=null}):b.put(e,c).push(function(){return n._signature_sub_storage.put(e,{hash:d})}),g.push(function(){i&&(p[e]=null)})}function e(b,e,f,g,h,i){var j;b.push(function(){return f.get(g)}).push(function(a){j=a},function(b){if(!(b instanceof a.util.jIOError&&404===b.status_code))throw b}).push(function(){return i(g)}).push(function(b){var i,k=d(JSON.stringify(b));if(void 0===j)return c(e,f,b,k,g,h);if(i=d(JSON.stringify(j)),k===i)return n._signature_sub_storage.put(g,{hash:k}).push(function(){p[g]=null});if(h.conflict_ignore!==!0){if(h.conflict_force===!0)return c(e,f,b,k,g,h);throw new a.util.jIOError("Conflict on '"+g+"': "+JSON.stringify(b)+" !== "+JSON.stringify(j),409)}})}function f(a,c,d,f,g){a.push(function(){return c.bulk(f)}).push(function(a){function h(b){return function(c){if(c!==f[b].parameter_list[0])throw new Error("Does not access expected ID "+c);return a[b]}}var i,j=new b.Queue;for(i=0;i<a.length;i+=1)e(j,c,d,f[i].parameter_list[0],g,h(i));return j})}function g(b,e,f,g){var h;b.push(function(){return n._signature_sub_storage.get(f)}).push(function(b){return h=b.hash,e.get(f).push(function(a){var b=d(JSON.stringify(a));return b===h?e.remove(f).push(function(){return n._signature_sub_storage.remove(f)}).push(function(){p[f]=null}):c(e,g,a,b,f)},function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return n._signature_sub_storage.remove(f).push(function(){p[f]=null});throw b})})}function k(e,f,g,h,i,j,k){e.push(function(){return b.all([k(h),n._signature_sub_storage.get(h)])}).push(function(b){var e=b[0],k=d(JSON.stringify(e)),l=b[1].hash;return k!==l?g.get(h).push(function(b){var m=d(JSON.stringify(b));if(m!==l){if(k===m)return n._signature_sub_storage.put(h,{hash:k}).push(function(){p[h]=null});if(j===!0)return;if(i!==!0)throw new a.util.jIOError("Conflict on '"+h+"': "+JSON.stringify(e)+" !== "+JSON.stringify(b),409)}return c(f,g,e,k,h)},function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return c(f,g,e,k,h);throw b}):void 0})}function l(a,c,d,e,f,g){a.push(function(){return c.bulk(e)}).push(function(a){function h(b){return function(c){if(c!==e[b].parameter_list[0])throw new Error("Does not access expected ID "+c);return a[b]}}var i,j=new b.Queue;for(i=0;i<a.length;i+=1)k(j,c,d,e[i].parameter_list[0],f,g,h(i));return j})}function m(a,c,d){var h=new b.Queue;return d.hasOwnProperty("use_post")||(d.use_post=!1),h.push(function(){return b.all([a.allDocs(n._query_options),n._signature_sub_storage.allDocs()])}).push(function(b){var i,j,m={},n=[],o=[],q={};for(i=0;i<b[0].data.total_rows;i+=1)p.hasOwnProperty(b[0].data.rows[i].id)||(m[b[0].data.rows[i].id]=i);for(i=0;i<b[1].data.total_rows;i+=1)p.hasOwnProperty(b[1].data.rows[i].id)||(q[b[1].data.rows[i].id]=i);if(d.check_creation===!0){for(j in m)m.hasOwnProperty(j)&&(q.hasOwnProperty(j)||(d.use_bulk_get===!0?n.push({method:"get",parameter_list:[j]}):e(h,a,c,j,d,a.get.bind(a))));d.use_bulk_get===!0&&0!==n.length&&f(h,a,c,n,d)}for(j in q)q.hasOwnProperty(j)&&(m.hasOwnProperty(j)?d.check_modification===!0&&(d.use_bulk_get===!0?o.push({method:"get",parameter_list:[j]}):k(h,a,c,j,d.conflict_force,d.conflict_ignore,a.get.bind(a))):d.check_deletion===!0&&g(h,c,j,a));d.use_bulk_get===!0&&0!==o.length&&l(h,a,c,o,d.conflict_force,d.conflict_ignore)})}var n=this,o=arguments,p={};return p[n._signature_hash]=null,(new b.Queue).push(function(){return n._signature_sub_storage.__storage._sub_storage.get(n._signature_hash)}).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return n._signature_sub_storage.__storage._sub_storage.put(n._signature_hash,{});throw b}).push(function(){return b.all([n._local_sub_storage.repair.apply(n._local_sub_storage,o),n._remote_sub_storage.repair.apply(n._remote_sub_storage,o)])}).push(function(){return n._check_local_modification||n._check_local_creation||n._check_local_deletion?m(n._local_sub_storage,n._remote_sub_storage,{use_post:n._use_remote_post,conflict_force:n._conflict_handling===h,conflict_ignore:n._conflict_handling===j||n._conflict_handling===i,check_modification:n._check_local_modification,check_creation:n._check_local_creation,check_deletion:n._check_local_deletion}):void 0}).push(function(){var b=!1;try{b=n._remote_sub_storage.hasCapacity("bulk")}catch(c){if(!(c instanceof a.util.jIOError&&501===c.status_code))throw c}return n._check_remote_modification||n._check_remote_creation||n._check_remote_deletion?m(n._remote_sub_storage,n._local_sub_storage,{use_bulk_get:b,conflict_force:n._conflict_handling===i,conflict_ignore:n._conflict_handling===j,check_modification:n._check_remote_modification,check_creation:n._check_remote_creation,check_deletion:n._check_remote_deletion}):void 0})},a.addStorage("replicate",e)}(jIO,RSVP,Rusha),function(a){"use strict";function b(a){this._sub_storage=jIO.createJIO(a.sub_storage)}var c=new a;b.prototype.post=function(a){return this._sub_storage.put(c.digestFromString(JSON.stringify(a)),a)},b.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},b.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},b.prototype.hasCapacity=function(){return this._sub_storage.hasCapacity.apply(this._sub_storage,arguments)},b.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},b.prototype.getAttachment=function(){return this._sub_storage.getAttachment.apply(this._sub_storage,arguments)},b.prototype.putAttachment=function(){return this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},b.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},b.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},b.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},jIO.addStorage("sha",b)}(Rusha),function(a){"use strict";function b(b){this._sub_storage=a.createJIO(b.sub_storage)}b.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},b.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},b.prototype.post=function(a){function b(){return("0000"+Math.floor(65536*Math.random()).toString(16)).slice(-4)}var c=b()+b()+"-"+b()+"-"+b()+"-"+b()+"-"+b()+b()+b();return this.put(c,a)},b.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},b.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},b.prototype.getAttachment=function(){return this._sub_storage.getAttachment.apply(this._sub_storage,arguments)},b.prototype.putAttachment=function(){return this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},b.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},b.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},b.prototype.hasCapacity=function(a){return this._sub_storage.hasCapacity(a)},b.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},a.addStorage("uuid",b)}(jIO),function(a,b,c){"use strict";function d(){this._database={}}d.prototype.put=function(a,c){return this._database.hasOwnProperty(a)||(this._database[a]={attachments:{}}),this._database[a].doc=b.stringify(c),a},d.prototype.get=function(c){try{return b.parse(this._database[c].doc)}catch(d){if(d instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+c,404);throw d}},d.prototype.allAttachments=function(b){var c,d={};try{for(c in this._database[b].attachments)this._database[b].attachments.hasOwnProperty(c)&&(d[c]={})}catch(e){if(e instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+b,404);throw e}return d},d.prototype.remove=function(a){return delete this._database[a],a},d.prototype.getAttachment=function(b,c){try{var d=this._database[b].attachments[c];if(void 0===d)throw new a.util.jIOError("Cannot find attachment: "+b+" , "+c,404);return a.util.dataURItoBlob(d)}catch(e){if(e instanceof TypeError)throw new a.util.jIOError("Cannot find attachment: "+b+" , "+c,404);throw e}},d.prototype.putAttachment=function(b,d,e){var f;try{f=this._database[b].attachments}catch(g){if(g instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+b,404);throw g}return(new c.Queue).push(function(){return a.util.readBlobAsDataURL(e)}).push(function(a){f[d]=a.target.result})},d.prototype.removeAttachment=function(b,c){try{delete this._database[b].attachments[c]}catch(d){if(d instanceof TypeError)throw new a.util.jIOError("Cannot find document: "+b,404);throw d}},d.prototype.hasCapacity=function(a){return"list"===a||"include"===a},d.prototype.buildQuery=function(a){var c,d=[];for(c in this._database)this._database.hasOwnProperty(c)&&(a.include_docs===!0?d.push({id:c,value:{},doc:b.parse(this._database[c].doc)}):d.push({id:c,value:{}}));return d},a.addStorage("memory",d)}(jIO,JSON,RSVP),function(a,b,c,d){"use strict";function e(a){this._sub_storage=jIO.createJIO(a.sub_storage)}function f(a,b){return a.indexOf(b)===a.length-b.length}var g="application/x-jio-utf16_lz_string";e.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},e.prototype.post=function(){return this._sub_storage.post.apply(this._sub_storage,arguments)},e.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},e.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},e.prototype.hasCapacity=function(){return this._sub_storage.hasCapacity.apply(this._sub_storage,arguments)},e.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},e.prototype.getAttachment=function(b,e){var f=this;return f._sub_storage.getAttachment(b,e).push(function(b){return b.type!==g?b:(new a.Queue).push(function(){return jIO.util.readBlobAsText(b,"utf16")}).push(function(a){var e=c.decompressFromUTF16(a.target.result);if(""===e)return b;try{return jIO.util.dataURItoBlob(e)}catch(f){if(f instanceof d)return b;throw f}})})},e.prototype.putAttachment=function(d,e,h){var i=this;return 0===h.type.indexOf("text/")||f(h.type,"xml")||f(h.type,"json")?(new a.Queue).push(function(){return jIO.util.readBlobAsDataURL(h)}).push(function(a){var f=c.compressToUTF16(a.target.result);return h=new b([f],{type:g}),i._sub_storage.putAttachment(d,e,h)}):this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},e.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},e.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},jIO.addStorage("zip",e)}(RSVP,Blob,LZString,DOMException),function(a,b,c,d){"use strict";function e(b){if(0!==b.indexOf("/"))throw new a.util.jIOError("id "+b+" is forbidden (no begin /)",400);if(b.lastIndexOf("/")!==b.length-1)throw new a.util.jIOError("id "+b+" is forbidden (no end /)",400);return b}function f(b){if(-1!==b.indexOf("/"))throw new a.util.jIOError("attachment "+b+" is forbidden",400)}function g(a){if("string"!=typeof a.access_token||!a.access_token)throw new TypeError("Access Token' must be a string which contains more than one character.");if("string"!=typeof a.root||!a.root||"dropbox"!==a.root&&"sandbox"!==a.root)throw new TypeError("root must be 'dropbox' or 'sandbox'");this._access_token=a.access_token,this._root=a.root}var h="https://content.dropboxapi.com/1/files_put/{+root}{+id}{+name}{?access_token}",i=d.parse(h),j="https://api.dropboxapi.com/1/fileops/create_folder{?access_token,root,path}",k=d.parse(j),l="https://api.dropboxapi.com/1/fileops/delete/{?access_token,root,path}",m=d.parse(l),n="https://content.dropboxapi.com/1/files{/root,id}{+name}{?access_token}",o=d.parse(n),p="https://api.dropboxapi.com/1/metadata{/root}{+id}{?access_token}",q=d.parse(p);g.prototype.put=function(c,d){var f=this;if(c=e(c),Object.getOwnPropertyNames(d).length>0)throw new a.util.jIOError("Can not store properties: "+Object.getOwnPropertyNames(d),400);return(new b.Queue).push(function(){return a.util.ajax({type:"POST",url:k.expand({access_token:f._access_token,root:f._root,path:c})})}).push(void 0,function(a){if(void 0===a.target||405!==a.target.status)throw a})},g.prototype.remove=function(b){return b=e(b),a.util.ajax({type:"POST",url:m.expand({access_token:this._access_token,root:this._root,path:b})})},g.prototype.get=function(c){var d=this;return"/"===c?{}:(c=e(c),(new b.Queue).push(function(){return a.util.ajax({type:"GET",url:q.expand({access_token:d._access_token,root:d._root,id:c})})}).push(function(b){var d=JSON.parse(b.target.response||b.target.responseText);if(d.is_dir)return{};throw new a.util.jIOError("Not a directory: "+c,404)},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document: "+c,404);throw b}))},g.prototype.allAttachments=function(c){var d=this;return c=e(c),(new b.Queue).push(function(){return a.util.ajax({type:"GET",url:q.expand({access_token:d._access_token,root:d._root,id:c})})}).push(function(b){var d,e=JSON.parse(b.target.response||b.target.responseText),f={};if(!e.is_dir)throw new a.util.jIOError("Not a directory: "+c,404);for(d=0;d<e.contents.length;d+=1)e.contents[d].is_dir||(f[e.contents[d].path.split("/").pop()]={});return f},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document: "+c,404);throw b})},g.prototype.putAttachment=function(b,c,d){return b=e(b),f(c),a.util.ajax({type:"PUT",url:i.expand({root:this._root,id:b,name:c,access_token:this._access_token}),dataType:d.type,data:d})},g.prototype.getAttachment=function(d,g){var h=this;return d=e(d),f(g),(new b.Queue).push(function(){return a.util.ajax({type:"GET",dataType:"blob",url:o.expand({root:h._root,id:d,name:g,access_token:h._access_token})})}).push(function(a){return new c([a.target.response||a.target.responseText],{type:a.target.getResponseHeader("Content-Type")||"application/octet-stream"})},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+d+", "+g,404);throw b})},g.prototype.removeAttachment=function(c,d){var g=this;return c=e(c),f(d),(new b.Queue).push(function(){return a.util.ajax({type:"POST",url:m.expand({access_token:g._access_token,root:g._root,path:c+d})})}).push(void 0,function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+c+", "+d,404);throw b})},a.addStorage("dropbox",g)}(jIO,RSVP,Blob,UriTemplate),function(a,b,c,d){"use strict";function e(c,d){return void 0===d&&(d={}),void 0!==c._authorization&&(void 0===d.headers&&(d.headers={}),d.headers.Authorization=c._authorization),void 0!==c._with_credentials&&(void 0===d.xhrFields&&(d.xhrFields={}),d.xhrFields.withCredentials=c._with_credentials),(new b.Queue).push(function(){return a.util.ajax(d)})}function f(b){if(0!==b.indexOf("/"))throw new a.util.jIOError("id "+b+" is forbidden (no begin /)",400);if(b.lastIndexOf("/")!==b.length-1)throw new a.util.jIOError("id "+b+" is forbidden (no end /)",400);return b}function g(b){if(-1!==b.indexOf("/"))throw new a.util.jIOError("attachment "+b+" is forbidden",400)}function h(a){if("string"!=typeof a.url)throw new TypeError("DavStorage 'url' is not of type string");this._url=a.url,"string"==typeof a.basic_login&&(this._authorization="Basic "+a.basic_login),this._with_credentials=a.with_credentials}h.prototype.put=function(c,d){var g=this;if(c=f(c),Object.getOwnPropertyNames(d).length>0)throw new a.util.jIOError("Can not store properties: "+Object.getOwnPropertyNames(d),400);return(new b.Queue).push(function(){return e(g,{type:"MKCOL",url:g._url+c})}).push(void 0,function(a){if(void 0===a.target||405!==a.target.status)throw a})},h.prototype.remove=function(a){return a=f(a),e(this,{type:"DELETE",url:this._url+a})},h.prototype.get=function(c){var d=this;return c=f(c),(new b.Queue).push(function(){return e(d,{type:"PROPFIND",url:d._url+c,dataType:"text",headers:{Depth:"1"}})}).push(function(){return{}},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document",404);throw b})},h.prototype.allAttachments=function(d){var g=this;return d=f(d),(new b.Queue).push(function(){return e(g,{type:"PROPFIND",url:g._url+d,dataType:"text",headers:{Depth:"1"}})}).push(function(a){var b,d,e={},f=(new c).parseFromString(a.target.responseText,"text/xml").querySelectorAll("D\\:response, response");for(b=1;b<f.length;b+=1)d=f[b].querySelector("D\\:href, href").textContent.split("/").slice(-1)[0],void 0!==d&&""!==d&&(e[d]={});return e},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document",404);throw b})},h.prototype.putAttachment=function(c,d,h){var i=this;return c=f(c),g(d),(new b.Queue).push(function(){return e(i,{type:"PUT",url:i._url+c+d,data:h})}).push(void 0,function(b){if(403===b.target.status||424===b.target.status)throw new a.util.jIOError("Cannot access subdocument",404);throw b})},h.prototype.getAttachment=function(c,h){var i=this;return c=f(c),g(h),(new b.Queue).push(function(){return e(i,{type:"GET",url:i._url+c+h,dataType:"blob"})}).push(function(a){return new d([a.target.response||a.target.responseText],{type:a.target.getResponseHeader("Content-Type")||"application/octet-stream"})},function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+c+" , "+h,404);throw b})},h.prototype.removeAttachment=function(c,d){var h=this;return c=f(c),g(d),(new b.Queue).push(function(){return e(h,{type:"DELETE",url:h._url+c+d})}).push(void 0,function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find attachment: "+c+" , "+d,404);throw b})},a.addStorage("dav",h)}(jIO,RSVP,DOMParser,Blob),function(a,b,c,d,e){"use strict";function f(b,c){if(404===b.target.status)throw new a.util.jIOError("Cannot find document: "+c,404);throw b}function g(b,d){var g,h;return(new c.Queue).push(function(){return a.util.ajax({type:"GET",url:s.expand({pageToken:b.nextPageToken||"",access_token:d})})}).push(function(a){for(h=e.parse(a.target.response||a.target.responseText),g=0;g<h.items.length;g+=1)h.items[g].value={},b.push(h.items[g]);return b.nextPageToken=h.nextPageToken,b},f)}function h(b){if("enclosure"!==b)throw new a.util.jIOError("Only support 'enclosure' attachment",400)}function i(a){if(void 0===a||void 0===a.access_token||"string"!=typeof a.access_token)throw new TypeError("Access Token must be a string which contains more than one character.");if(void 0!==a.trashing&&a.trashing!==!0&&a.trashing!==!1)throw new TypeError("trashing parameter must be a boolean (true or false)");this._trashing=a.trashing||!0,this._access_token=a.access_token}function j(a,b){return(new c.Queue).push(function(){return g(a,b)}).push(function(){return a.nextPageToken?j(a,b):a})}function k(b,d,g){var h="-------314159265358979323846";return(new c.Queue).push(function(){return a.util.ajax({type:b?"PUT":"POST",url:o.expand({access_token:g,id:b||[],upload:b?[]:"upload",uploadType:"multipart"}),headers:{"Content-Type":'multipart/related; boundary="'+h+'"'},data:"--"+h+"\nContent-Type: application/json; charset=UTF-8\n\n"+e.stringify(d)+"\n\n--"+h+"--"})}).push(function(a){var b=e.parse(a.target.responseText);return b.id},function(a){f(a,b)})}function l(b,d,g){return(new c.Queue).push(function(){return a.util.ajax({type:"PUT",url:o.expand({access_token:g,upload:"upload",id:b,uploadType:"media"}),data:d})}).push(function(b){if(b=e.parse(b.target.responseText),"application/vnd.google-apps.folder"===b.mimeType)throw new a.util.jIOError("cannot put attachments to folder",400);return b},function(a){f(a,b)})}function m(d,g,h){return(new c.Queue).push(function(){return a.util.ajax({type:"GET",dataType:g?"blob":"json",url:u.expand({id:d,alt:g?"media":[],access_token:h}),headers:{Authorization:"Bearer "+h}})}).push(function(a){return a.target.response||(g?new b([a.target.responseText],{type:a.target.responseHeaders["Content-Type"]}):e.parse(a.target.responseText))},function(a){f(a,d)})}var n="https://www.googleapis.com{/upload}/drive/v2/files{/id}{?uploadType,access_token}",o=d.parse(n),p="https://www.googleapis.com/drive/v2/files{/id,trash}{?access_token}",q=d.parse(p),r="https://www.googleapis.com/drive/v2/files?prettyPrint=false{&pageToken}&q=trashed=false&fields=nextPageToken,items(id){&access_token}",s=d.parse(r),t="https://www.googleapis.com/drive/v2/files{/id}{?alt}",u=d.parse(t);i.prototype.hasCapacity=function(a){return"list"===a},i.prototype.buildQuery=function(){return j([],this._access_token)},i.prototype.put=function(a,b){return k(a,b,this._access_token)},i.prototype.post=function(a){return k(void 0,a,this._access_token)},i.prototype.putAttachment=function(a,b,c){return h(b),l(a,c,this._access_token)},i.prototype.remove=function(b){var d=this;return(new c.Queue).push(function(){return a.util.ajax({type:d._trashing?"POST":"DELETE",url:q.expand({id:b,access_token:d._access_token,trash:d._trashing?"trash":[]})})}).push(void 0,function(a){f(a,b)})},i.prototype.get=function(a){return m(a,!1,this._access_token)},i.prototype.getAttachment=function(a,b){return h(b),m(a,!0,this._access_token)},i.prototype.allAttachments=function(a){var b=this._access_token;return(new c.Queue).push(function(){return m(a,!1,b)}).push(function(a){return"application/vnd.google-apps.folder"===a.mimeType?{}:{enclosure:{}}})},a.addStorage("gdrive",i)}(jIO,Blob,RSVP,UriTemplate,JSON),function(a,b){"use strict";function c(b){if(!Array.isArray(b.storage_list))throw new a.util.jIOError("storage_list is not an Array",400);var c;for(this._storage_list=[],c=0;c<b.storage_list.length;c+=1)this._storage_list.push(a.createJIO(b.storage_list[c]))}c.prototype._getWithStorageIndex=function(){function b(b){g.push(void 0,function(c){if(c instanceof a.util.jIOError&&404===c.status_code)return e._storage_list[b].get.apply(e._storage_list[b],f).push(function(a){return d=b,a});throw c})}var c,d=0,e=this,f=arguments,g=this._storage_list[0].get.apply(this._storage_list[0],f);for(c=1;c<this._storage_list.length;c+=1)b(c);return g.push(function(a){return[d,a]})},c.prototype.get=function(){return this._getWithStorageIndex.apply(this,arguments).push(function(a){return a[1]})},c.prototype.allAttachments=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.allAttachments.apply(d,a)})},c.prototype.post=function(){return this._storage_list[0].post.apply(this._storage_list[0],arguments)},c.prototype.put=function(){var b=arguments,c=this;return this._getWithStorageIndex(b[0]).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return[0];throw b}).push(function(a){var d=c._storage_list[a[0]];return d.put.apply(d,b)})},c.prototype.remove=function(){var a=arguments,b=this;return this._getWithStorageIndex(a[0]).push(function(c){var d=b._storage_list[c[0]];return d.remove.apply(d,a)})},c.prototype.buildQuery=function(){var a,c,d=[],e={},f=this._storage_list.length;for(a=0;f>a;a+=1)c=this._storage_list[a],d.push(c.buildQuery.apply(c,arguments));return(new b.Queue).push(function(){return b.all(d)}).push(function(b){var c,d,g,h=[];for(f=b.length,a=0;f>a;a+=1)for(c=b[a],d=c.length,g=0;d>g;g+=1)e.hasOwnProperty(c[g].id)||(e[c[g].id]=null,h.push(c[g]));return h})},c.prototype.hasCapacity=function(a){var b,c,d,e;if("list"===a||"query"===a||"select"===a){for(d=!0,c=this._storage_list.length,b=0;c>b;b+=1)e=this._storage_list[b],d=d&&e.hasCapacity(a);return d}return!1},c.prototype.repair=function(){var a,c=[];for(a=0;a<this._storage_list.length;a+=1)c.push(this._storage_list[a].repair.apply(this._storage_list[a],arguments));return b.all(c)},c.prototype.getAttachment=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.getAttachment.apply(d,a)})},c.prototype.putAttachment=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.putAttachment.apply(d,a)})},c.prototype.removeAttachment=function(){var a=arguments,b=this;return this._getWithStorageIndex.apply(this,arguments).push(function(c){var d=b._storage_list[c[0]];return d.removeAttachment.apply(d,a)})},a.addStorage("union",c)}(jIO,RSVP),function(a,b,c,d,e,f,g,h){"use strict";function i(b){return(new d.Queue).push(function(){return a.util.ajax({type:"GET",url:b._url,xhrFields:{withCredentials:!0}})}).push(function(a){return JSON.parse(a.target.responseText)})}function j(c,e,f){return void 0===f&&(f={}),i(c).push(function(c){return(new d.Queue).push(function(){return a.util.ajax({type:"GET",url:b.parse(c._links.traverse.href).expand({relative_url:e,view:f._view}),xhrFields:{withCredentials:!0}})}).push(void 0,function(b){if(void 0!==b.target&&404===b.target.status)throw new a.util.jIOError("Cannot find document: "+e,404);throw b})})}function k(a){return(new d.Queue).push(function(){var b,c,d,f,g=a._embedded._view,h={portal_type:a._links.type.name
+},i={};a._links.hasOwnProperty("parent")&&(h.parent_relative_url=new e(a._links.parent.href).segment(2)),i.form_id={key:[g.form_id.key],"default":g.form_id["default"]};for(c in g)g.hasOwnProperty(c)&&(b=g[c],d=0,0===c.indexOf("my_")&&b.editable&&(d=3),0===c.indexOf("your_")&&(d=5),0!==d&&q.hasOwnProperty(b.type)&&(i[c.substring(d)]={"default":b["default"],key:b.key},h[c.substring(d)]=b["default"]));return f={data:h,form_data:i},g.hasOwnProperty("_actions")&&g._actions.hasOwnProperty("put")&&(f.action_href=g._actions.put.href),f})}function l(b,c){return b.getAttachment(c,"view").push(function(b){return a.util.readBlobAsText(b)}).push(function(a){return JSON.parse(a.target.result)}).push(function(a){return k(a)})}function m(a){if("string"!=typeof a.url||!a.url)throw new TypeError("ERP5 'url' must be a string which contains more than one character.");this._url=a.url,this._default_view_reference=a.default_view_reference}function n(a){var b,c=a.data;for(b in c)c.hasOwnProperty(b)&&(c[b]||delete c[b]);return c}function o(a){return a instanceof g&&"local_roles"===a.key?a.value:void 0}function p(a){var b,c,d=!0,e=[];if(a instanceof h&&"OR"===a.operator){for(b=0;b<a.query_list.length;b+=1)c=a.query_list[b],c instanceof g&&"local_roles"===c.key?e.push(c.value):d=!1;if(d)return e}}var q={StringField:null,EmailField:null,IntegerField:null,FloatField:null,TextAreaField:null};m.prototype.get=function(a){return l(this,a).push(function(a){return n(a)})},m.prototype.bulk=function(b){var e,f=this,g=[];for(e=0;e<b.length;e+=1){if("get"!==b[e].method)throw new Error("ERP5Storage: not supported "+b[e].method+" in bulk");g.push({relative_url:b[e].parameter_list[0],view:f._default_view_reference})}return i(f).push(function(b){var d=new c;return d.append("bulk_list",JSON.stringify(g)),a.util.ajax({type:"POST",url:b._actions.bulk.href,data:d,xhrFields:{withCredentials:!0}})}).push(function(a){function b(a){return k(a).push(function(a){return n(a)})}var c=[],f=JSON.parse(a.target.responseText);for(e=0;e<f.result_list.length;e+=1)c.push(b(f.result_list[e]));return d.all(c)})},m.prototype.post=function(b){var d,f=this;return i(this).push(function(d){var e=new c;return e.append("portal_type",b.portal_type),e.append("parent_relative_url",b.parent_relative_url),a.util.ajax({type:"POST",url:d._actions.add.href,data:e,xhrFields:{withCredentials:!0}})}).push(function(a){var c=a.target.getResponseHeader("X-Location"),g=new e(c);return d=g.segment(2),f.put(d,b)}).push(function(){return d})},m.prototype.put=function(b,c){var d=this;return l(d,b).push(function(e){var g,h=e.form_data,i={};i[h.form_id.key]=h.form_id["default"];for(g in c)if(c.hasOwnProperty(g)){if("form_id"===g)throw new a.util.jIOError("ERP5: forbidden property: "+g,400);if("portal_type"!==g&&"parent_relative_url"!==g){if(!h.hasOwnProperty(g))throw new a.util.jIOError("ERP5: can not store property: "+g,400);i[h[g].key]=c[g]}}if(!e.hasOwnProperty("action_href"))throw new a.util.jIOError("ERP5: can not modify document: "+b,403);return d.putAttachment(b,e.action_href,new f([JSON.stringify(i)],{type:"application/json"}))})},m.prototype.allAttachments=function(a){var b=this;return j(this,a).push(function(){return void 0===b._default_view_reference?{links:{}}:{view:{},links:{}}})},m.prototype.getAttachment=function(b,c,e){if(void 0===e&&(e={}),"view"===c){if(void 0===this._default_view_reference)throw new a.util.jIOError("Cannot find attachment view for: "+b,404);return j(this,b,{_view:this._default_view_reference}).push(function(a){var b=JSON.parse(a.target.responseText);return new f([JSON.stringify(b)],{type:"application/hal+json"})})}if("links"===c)return j(this,b).push(function(a){return new f([JSON.stringify(JSON.parse(a.target.responseText))],{type:"application/hal+json"})});if(0===c.indexOf(this._url))return(new d.Queue).push(function(){var b,d,f,g={type:"GET",dataType:"blob",url:c,xhrFields:{withCredentials:!0}};if(void 0!==e.start||void 0!==e.end){if(b=e.start||0,d=e.end,void 0!==d&&0>d)throw new a.util.jIOError("end must be positive",400);if(0>b)f="bytes="+b;else if(void 0===d)f="bytes="+b+"-";else{if(b>d)throw new a.util.jIOError("start is greater than end",400);f="bytes="+b+"-"+d}g.headers={Range:f}}return a.util.ajax(g)}).push(function(a){return void 0===a.target.response?new f([a.target.responseText],{type:a.target.getResponseHeader("Content-Type")}):a.target.response});throw new a.util.jIOError("ERP5: not support get attachment: "+c,400)},m.prototype.putAttachment=function(b,e,f){if(0!==e.indexOf(this._url))throw new a.util.jIOError("Can not store outside ERP5: "+e,400);return(new d.Queue).push(function(){return a.util.readBlobAsText(f)}).push(function(b){var d,f,g,h,i=JSON.parse(b.target.result),j=new c;for(g in i)if(i.hasOwnProperty(g))for(d=Array.isArray(i[g])?i[g]:[i[g]],f=0;f<d.length;f+=1)h=d[f],"object"==typeof h?j.append(g,a.util.dataURItoBlob(h.url),h.file_name):j.append(g,h);return a.util.ajax({type:"POST",url:e,data:j,xhrFields:{withCredentials:!0}})})},m.prototype.hasCapacity=function(a){return"list"===a||"query"===a||"select"===a||"limit"===a||"sort"===a},m.prototype.buildQuery=function(c){return i(this).push(function(d){var e,f,g,i,j,k=c.query,l=[];if(c.query)if(f=a.QueryFactory.create(c.query),i=o(f))k=void 0,j=i;else if(i=p(f))k=void 0,j=i;else if(f instanceof h&&"AND"===f.operator)for(e=0;e<f.query_list.length;e+=1)g=f.query_list[e],i=o(g),i?(j=i,f.query_list.splice(e,1),k=a.Query.objectToSearchText(f),e=f.query_list.length):(i=p(g),i&&(j=i,f.query_list.splice(e,1),k=a.Query.objectToSearchText(f),e=f.query_list.length));if(c.sort_on){for(e=0;e<c.sort_on.length;e+=1)l.push(JSON.stringify(c.sort_on[e]));c.sort_on=l}return a.util.ajax({type:"GET",url:b.parse(d._links.raw_search.href).expand({query:k,select_list:c.select_list||["title","reference"],limit:c.limit,sort_on:c.sort_on,local_roles:j}),xhrFields:{withCredentials:!0}})}).push(function(a){return JSON.parse(a.target.responseText)}).push(function(a){var b,c,d,f=a._embedded.contents,g=f.length,h=[];for(b=0;g>b;b+=1)d=f[b],c=new e(d._links.self.href),delete d._links,h.push({id:c.segment(2),value:d});return h})},a.addStorage("erp5",m)}(jIO,UriTemplate,FormData,RSVP,URI,Blob,SimpleQuery,ComplexQuery),function(a,b){"use strict";function c(b){this._sub_storage=a.createJIO(b.sub_storage),this._key_schema=b.key_schema}c.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},c.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},c.prototype.post=function(){return this._sub_storage.post.apply(this._sub_storage,arguments)},c.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},c.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},c.prototype.getAttachment=function(){return this._sub_storage.getAttachment.apply(this._sub_storage,arguments)},c.prototype.putAttachment=function(){return this._sub_storage.putAttachment.apply(this._sub_storage,arguments)},c.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},c.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},c.prototype.hasCapacity=function(a){var b=["limit","sort","select","query"];return-1!==b.indexOf(a)?!0:"list"===a?this._sub_storage.hasCapacity(a):!1},c.prototype.buildQuery=function(c){var d=this._sub_storage,e=this,f={},g=!1,h=!1;if(d.hasCapacity("list")){try{void 0!==c.query&&!d.hasCapacity("query")||void 0!==c.sort_on&&!d.hasCapacity("sort")||void 0!==c.select_list&&!d.hasCapacity("select")||void 0!==c.limit&&!d.hasCapacity("limit")||(f.query=c.query,f.sort_on=c.sort_on,f.select_list=c.select_list,f.limit=c.limit)}catch(i){if(!(i instanceof a.util.jIOError&&501===i.status_code))throw i;g=!0}try{(g||c.include_docs===!0)&&d.hasCapacity("include")&&(f.include_docs=!0)}catch(i){if(!(i instanceof a.util.jIOError&&501===i.status_code))throw i;h=!0}return d.buildQuery(f).push(function(c){function e(b){var e=c[b].id;return d.get(e).push(function(a){return a._id=e,a},function(b){if(!(b instanceof a.util.jIOError&&404===b.status_code))throw b})}var f,g,i=[c];if(h){for(f=c.length,g=0;f>g;g+=1)i.push(e(g));c=b.all(i)}return c}).push(function(a){var b,c,d;if(h){for(b=a[0],c=b.length,d=0;c>d;d+=1)b[d].doc=a[d+1];a=b}return a}).push(function(b){var d,f,h=[];if(g){for(d=b.length,f=0;d>f;f+=1)b[f].doc.__id=b[f].id,h.push(b[f].doc);c.select_list&&c.select_list.push("__id"),b=a.QueryFactory.create(c.query||"",e._key_schema).exec(h,c)}return b}).push(function(a){var b,d,e,f=[];if(g){for(d=a.length,e=0;d>e;e+=1){if(b={id:a[e].__id,value:c.select_list?a[e]:{},doc:{}},c.select_list&&delete b.value.__id,c.include_docs)throw new Error("QueryStorage does not support include docs");f.push(b)}a=f}return a})}},a.addStorage("query",c)}(jIO,RSVP),function(a,b,c){"use strict";function d(b){this._sub_storage=a.createJIO(b.sub_storage)}function e(a,b){return-1!==a.indexOf(b,a.length-b.length)}var f=".json",g="/.jio_documents/",h="/";d.prototype.get=function(c){var d=this;return(new b.Queue).push(function(){return d._sub_storage.getAttachment(g,c+f,{format:"json"})}).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return d._sub_storage.allAttachments(h).push(function(b){if(b.hasOwnProperty(c))return{};throw new a.util.jIOError("Cannot find document "+c,404)});throw b})},d.prototype.allAttachments=function(b){var c=this;return c._sub_storage.allAttachments(h).push(function(d){return d.hasOwnProperty(b)?{enclosure:{}}:c._sub_storage.getAttachment(g,b+f).push(function(){return{}},function(c){if(c instanceof a.util.jIOError&&404===c.status_code)throw new a.util.jIOError("Cannot find document "+b,404);throw c})})},d.prototype.put=function(b,d){var e=this;return e._sub_storage.putAttachment(g,b+f,new c([JSON.stringify(d)],{type:"application/json"})).push(void 0,function(h){if(h instanceof a.util.jIOError&&404===h.status_code)return e._sub_storage.put(g,{}).push(function(){return e._sub_storage.putAttachment(g,b+f,new c([JSON.stringify(d)],{type:"application/json"}))});throw h}).push(function(){return b})},d.prototype.remove=function(c){var d=this,e=!1;return(new b.Queue).push(function(){return d._sub_storage.removeAttachment(h,c)}).push(void 0,function(b){if(b instanceof a.util.jIOError&&404===b.status_code)return void(e=!0);throw b}).push(function(){return d._sub_storage.removeAttachment(g,c+f)}).push(void 0,function(b){if(!e&&b instanceof a.util.jIOError&&404===b.status_code)return c;throw b})},d.prototype.hasCapacity=function(a){return"list"===a},d.prototype.buildQuery=function(){var c={},d=this;return(new b.Queue).push(function(){return d._sub_storage.allAttachments(g)}).push(function(a){var b;for(b in a)a.hasOwnProperty(b)&&e(b,f)&&(c[b.substring(0,b.length-f.length)]=null)},function(b){if(!(b instanceof a.util.jIOError&&404===b.status_code))throw b}).push(function(){return d._sub_storage.allAttachments(h)}).push(function(a){var b;for(b in a)a.hasOwnProperty(b)&&(c[b]=null)}).push(function(){var a,b=[];for(a in c)c.hasOwnProperty(a)&&b.push({id:a,value:{}});return b})},d.prototype.getAttachment=function(b,c){if("enclosure"!==c)throw new a.util.jIOError("Only support 'enclosure' attachment",400);return this._sub_storage.getAttachment(h,b)},d.prototype.putAttachment=function(b,c,d){if("enclosure"!==c)throw new a.util.jIOError("Only support 'enclosure' attachment",400);return this._sub_storage.putAttachment(h,b,d)},d.prototype.removeAttachment=function(b,c){if("enclosure"!==c)throw new a.util.jIOError("Only support 'enclosure' attachment",400);return this._sub_storage.removeAttachment(h,b)},d.prototype.repair=function(){return this._sub_storage.repair.apply(this._sub_storage,arguments)},a.addStorage("drivetojiomapping",d)}(jIO,RSVP,Blob),function(a,b,c,d,e){"use strict";function f(b){this._sub_storage=a.createJIO(b.sub_storage),this._document_id=b.document_id,this._repair_attachment=b.repair_attachment||!1}function g(a,b){return void 0===b?"jio_document/"+d(a)+h:"jio_attachment/"+d(a)+"/"+d(b)}var h=".json",i=new RegExp("^jio_document/([\\w=]+)"+h+"$"),j=new RegExp("^jio_attachment/([\\w=]+)/([\\w=]+)$");f.prototype.get=function(a){return this._sub_storage.getAttachment(this._document_id,g(a),{format:"json"})},f.prototype.allAttachments=function(a){return this._sub_storage.allAttachments(this._document_id).push(function(b){var d,e,f={};for(e in b)if(b.hasOwnProperty(e)&&j.test(e)){d=j.exec(e);try{c(d[1])===a&&(f[c(d[2])]={})}catch(g){if(!g instanceof ReferenceError)throw g}}return f})},f.prototype.put=function(a,c){return this._sub_storage.putAttachment(this._document_id,g(a),new b([JSON.stringify(c)],{type:"application/json"})).push(function(){return a})},f.prototype.remove=function(a){var b=this;return this.allAttachments(a).push(function(c){var d,f=[];for(d in c)c.hasOwnProperty(d)&&f.push(b.removeAttachment(a,d));return e.all(f)}).push(function(){return b._sub_storage.removeAttachment(b._document_id,g(a))}).push(function(){return a})},f.prototype.repair=function(){var a=this;return this._sub_storage.repair.apply(this._sub_storage,arguments).push(function(b){return a._repair_attachment?a._sub_storage.allAttachments(a._document_id).push(function(b){var d,f,g,h,k=[],l={},m={};for(h in b)if(b.hasOwnProperty(h))if(d=void 0,f=void 0,i.test(h)){try{d=c(i.exec(h)[1])}catch(n){if(!n instanceof ReferenceError)throw n}void 0!==d&&(l[d]=null)}else if(j.test(h)){g=j.exec(h);try{d=c(g[1]),f=c(g[2])}catch(n){if(!n instanceof ReferenceError)throw n}void 0!==f&&(l.hasOwnProperty(d)||(m.hasOwnProperty(d)||(m[d]={}),m[d][f]=null))}for(d in m)if(m.hasOwnProperty(d)&&!l.hasOwnProperty(d))for(f in m[d])m[d].hasOwnProperty(f)&&k.push(a.removeAttachment(d,f));return e.all(k)}):b})},f.prototype.hasCapacity=function(a){return"list"===a},f.prototype.buildQuery=function(){return this._sub_storage.allAttachments(this._document_id).push(function(a){var b,d=[];for(b in a)if(a.hasOwnProperty(b)&&i.test(b))try{d.push({id:c(i.exec(b)[1]),value:{}})}catch(e){if(!e instanceof ReferenceError)throw e}return d})},f.prototype.getAttachment=function(a,b){return this._sub_storage.getAttachment(this._document_id,g(a,b))},f.prototype.putAttachment=function(a,b,c){return this._sub_storage.putAttachment(this._document_id,g(a,b),c)},f.prototype.removeAttachment=function(a,b){return this._sub_storage.removeAttachment(this._document_id,g(a,b))},a.addStorage("document",f)}(jIO,Blob,atob,btoa,RSVP),function(a,b,c,d){"use strict";function e(a){a.sessiononly===!0?this._storage=b:this._storage=c}function f(b){if("/"!==b)throw new a.util.jIOError("id "+b+" is forbidden (!== /)",400)}e.prototype.get=function(a){return f(a),{}},e.prototype.allAttachments=function(a){f(a);var b,c={};for(b in this._storage)this._storage.hasOwnProperty(b)&&(c[b]={});return c},e.prototype.getAttachment=function(b,c){f(b);var d=this._storage.getItem(c);if(null===d)throw new a.util.jIOError("Cannot find attachment "+c,404);return a.util.dataURItoBlob(d)},e.prototype.putAttachment=function(b,c,e){var g=this;return f(b),(new d.Queue).push(function(){return a.util.readBlobAsDataURL(e)}).push(function(a){g._storage.setItem(c,a.target.result)})},e.prototype.removeAttachment=function(a,b){return f(a),this._storage.removeItem(b)},e.prototype.hasCapacity=function(a){return"list"===a},e.prototype.buildQuery=function(){return[{id:"/",value:{}}]},a.addStorage("local",e)}(jIO,sessionStorage,localStorage,RSVP),function(a,b,c,d,e,f){"use strict";function g(a){if("string"!=typeof a.database||""===a.database)throw new TypeError("IndexedDBStorage 'database' description property must be a non-empty string");this._database_name="jio:"+a.database}function h(a){return a.join("_")}function i(a){var b,c=a.target.result;b=c.createObjectStore("metadata",{keyPath:"_id",autoIncrement:!1}),b.createIndex("_id","_id",{unique:!0}),b=c.createObjectStore("attachment",{keyPath:"_key_path",autoIncrement:!1}),b.createIndex("_id","_id",{unique:!1}),b=c.createObjectStore("blob",{keyPath:"_key_path",autoIncrement:!1}),b.createIndex("_id_attachment",["_id","_attachment"],{unique:!1}),b.createIndex("_id","_id",{unique:!1})}function j(b){function d(b,c){var d=a.open(e);d.onerror=function(a){d.result&&d.result.close(),c(a)},d.onabort=function(){d.result.close(),c("Aborting connection to: "+e)},d.ontimeout=function(){d.result.close(),c("Connection to: "+e+" timeout")},d.onblocked=function(){d.result.close(),c("Connection to: "+e+" was blocked")},d.onupgradeneeded=i,d.onversionchange=function(){d.result.close(),c(e+" was upgraded")},d.onsuccess=function(){b(d.result)}}var e=b._database_name;return(new c.Queue).push(function(){return new c.Promise(d)})}function k(a,b,c,d){var e=a.transaction(b,c);return d!==!1&&(e.oncomplete=function(){a.close()}),e.onabort=function(){a.close()},e}function l(a,b){function d(c,d){a.onerror=function(b){a.transaction&&a.transaction.abort(),d(b)},a.onsuccess=function(a){var e=a.target.result;if(e){try{b(e)}catch(f){d(f)}e["continue"]()}else c()}}return new c.Promise(d)}function m(a){function d(c,d){a.onerror=d,a.onsuccess=function(){a.result&&c(a.result),d(new b.util.jIOError("Cannot find document",404))}}return new c.Promise(d)}function n(a){function b(b,c){a.onerror=c,a.onsuccess=function(){b(a.result)}}return new c.Promise(b)}function o(a){a["delete"]()}function p(a,b,d){return c.all([n(a.objectStore("attachment")["delete"](h([b,d]))),l(a.objectStore("blob").index("_id_attachment").openCursor(f.only([b,d])),o)])}var q=2e6;g.prototype.hasCapacity=function(a){return"list"===a||"include"===a},g.prototype.buildQuery=function(a){function b(a){d.push({id:a.key,value:{},doc:a.value.doc})}function c(a){d.push({id:a.key,value:{}})}var d=[];return j(this).push(function(d){var e=k(d,["metadata"],"readonly");return a.include_docs===!0?l(e.objectStore("metadata").index("_id").openCursor(),b):l(e.objectStore("metadata").index("_id").openKeyCursor(),c)}).push(function(){return d})},g.prototype.get=function(a){return j(this).push(function(b){var c=k(b,["metadata"],"readonly");return m(c.objectStore("metadata").get(a))}).push(function(a){return a.doc})},g.prototype.allAttachments=function(a){function b(a){d[a.value._attachment]={}}var d={};return j(this).push(function(d){var e=k(d,["metadata","attachment"],"readonly");return c.all([m(e.objectStore("metadata").get(a)),l(e.objectStore("attachment").index("_id").openCursor(f.only(a)),b)])}).push(function(){return d})},g.prototype.put=function(a,b){return j(this).push(function(c){var d=k(c,["metadata"],"readwrite");return n(d.objectStore("metadata").put({_id:a,doc:b}))})},g.prototype.remove=function(a){return j(this).push(function(b){var d=k(b,["metadata","attachment","blob"],"readwrite");return c.all([n(d.objectStore("metadata")["delete"](a)),l(d.objectStore("attachment").index("_id").openCursor(f.only(a)),o),l(d.objectStore("blob").index("_id").openCursor(f.only(a)),o)])})},g.prototype.getAttachment=function(a,f,g){var i,l,n,o;return void 0===g&&(g={}),j(this).push(function(b){return i=k(b,["attachment","blob"],"readonly"),m(i.objectStore("attachment").get(h([a,f])))}).push(function(d){var j,k,p,r=d.info.length,s=[],t=i.objectStore("blob");if(l=d.info.content_type,n=g.start||0,o=g.end||r,o>r&&(o=r),0>n||0>o)throw new b.util.jIOError("_start and _end must be positive",400);if(n>o)throw new b.util.jIOError("_start is greater than _end",400);for(k=e.floor(n/q),p=e.floor(o/q),o%q===0&&(p-=1),j=k;p>=j;j+=1)s.push(m(t.get(h([a,f,j]))));return c.all(s)}).push(function(a){var b,c,f,h=[],i=a.length;for(c=0;i>c;c+=1)h.push(a[c].blob);return void 0===g.start&&void 0===g.end?new d(h,{type:l}):(f=e.floor(n/q)*q,b=new d(h,{type:"application/octet-stream"}),b.slice(n-f,o-f,"application/octet-stream"))})},g.prototype.putAttachment=function(a,d,e){var f,g,i=[];return j(this).push(function(a){return g=a,b.util.readBlobAsArrayBuffer(e)}).push(function(b){for(var c=b.target.result,h=e.size,j=0;h>j;)i.push(c.slice(j,j+q)),j+=q;return f=k(g,["attachment","blob"],"readwrite"),p(f,a,d)}).push(function(){var b,g=[n(f.objectStore("attachment").put({_key_path:h([a,d]),_id:a,_attachment:d,info:{content_type:e.type,length:e.size}}))],j=i.length,k=f.objectStore("blob");for(b=0;j>b;b+=1)g.push(n(k.put({_key_path:h([a,d,b]),_id:a,_attachment:d,_part:b,blob:i[b]})));return c.all(g)})},g.prototype.removeAttachment=function(a,b){return j(this).push(function(c){var d=k(c,["attachment","blob"],"readwrite");return p(d,a,b)})},b.addStorage("indexeddb",g)}(indexedDB,jIO,RSVP,Blob,Math,IDBKeyRange),function(a,b,c,d,e,f,g){"use strict";function h(b){this._key=b.key,this._jsonKey=!0,this._sub_storage=a.createJIO(b.sub_storage)}function i(a){return(new b.Queue).push(function(){return e.subtle.importKey("jwk",a._key,"AES-GCM",!1,["encrypt","decrypt"])}).push(function(b){a._key=b,a._jsonKey=!1})}var j="application/x-jio-aes-gcm-encryption";h.prototype.get=function(){return this._sub_storage.get.apply(this._sub_storage,arguments)},h.prototype.post=function(){return this._sub_storage.post.apply(this._sub_storage,arguments)},h.prototype.put=function(){return this._sub_storage.put.apply(this._sub_storage,arguments)},h.prototype.remove=function(){return this._sub_storage.remove.apply(this._sub_storage,arguments)},h.prototype.hasCapacity=function(){return this._sub_storage.hasCapacity.apply(this._sub_storage,arguments)},h.prototype.buildQuery=function(){return this._sub_storage.buildQuery.apply(this._sub_storage,arguments)},h.prototype.putAttachment=function(c,h,k){var l=e.getRandomValues(new f(12)),m=this;return(new b.Queue).push(function(){return m._jsonKey===!0?i(m):void 0}).push(function(){return a.util.readBlobAsDataURL(k)}).push(function(a){var b,c=a.currentTarget.result.length,d=new g(c),h=new f(d);for(a=a.currentTarget.result,b=0;c>b;b+=1)h[b]=a.charCodeAt(b);return e.subtle.encrypt({name:"AES-GCM",iv:l},m._key,d)}).push(function(a){var b=new d([l,a],{type:j});return m._sub_storage.putAttachment(c,h,b)})},h.prototype.getAttachment=function(d,g){var h=this;return h._sub_storage.getAttachment(d,g).push(function(d){return d.type!==j?d:(new b.Queue).push(function(){return h._jsonKey===!0?i(h):void 0}).push(function(){return a.util.readBlobAsArrayBuffer(d)}).push(function(g){var i;return g=g.currentTarget.result,i=new f(g.slice(0,12)),(new b.Queue).push(function(){return e.subtle.decrypt({name:"AES-GCM",iv:i},h._key,g.slice(12))}).push(function(b){return b=String.fromCharCode.apply(null,new f(b)),a.util.dataURItoBlob(b)}).push(void 0,function(a){if(a instanceof c)return d;throw a})})})},h.prototype.removeAttachment=function(){return this._sub_storage.removeAttachment.apply(this._sub_storage,arguments)},h.prototype.allAttachments=function(){return this._sub_storage.allAttachments.apply(this._sub_storage,arguments)},a.addStorage("crypt",h)}(jIO,RSVP,DOMException,Blob,crypto,Uint8Array,ArrayBuffer),function(a,b,c,d){"use strict";function e(a,c,d){return new b.Promise(function(b,e){a.transaction(function(a){function f(a,c){j.push(c),j.length===i&&b(j)}function g(a,b){return e(b),!0}var h,i=c.length,j=[];for(h=0;i>h;h+=1)a.executeSql(c[h],d[h],f,g)},function(a,b){e(b)})})}function f(a){var c=["CREATE TABLE IF NOT EXISTS document(id VARCHAR PRIMARY KEY NOT NULL, data TEXT)","CREATE TABLE IF NOT EXISTS attachment(id VARCHAR, attachment VARCHAR, part INT, blob TEXT)","CREATE TRIGGER IF NOT EXISTS removeAttachment BEFORE DELETE ON document FOR EACH ROW BEGIN DELETE from attachment WHERE id = OLD.id;END;","CREATE INDEX IF NOT EXISTS index_document ON document (id);","CREATE INDEX IF NOT EXISTS index_attachment ON attachment (id, attachment);"];return(new b.Queue).push(function(){return e(a,c,[])})}function g(a){if("string"!=typeof a.database||!a.database)throw new TypeError("database must be a string which contains more than one character.");if(this._database=d("jio:"+a.database,"1.0","",2097152),a.blob_length&&("number"!=typeof a.blob_length||a.blob_length<20))throw new TypeError("blob_len parameter must be a number >= 20");this._blob_length=a.blob_length||2e6,this._init_db_promise=f(this._database)}function h(b,c,d,e){e.push(function(){return a.util.readBlobAsDataURL(b)}).push(function(a){c[d+2].push(a.currentTarget.result)})}g.prototype.put=function(a,c){var d=this._database,f=this,g=JSON.stringify(c);return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["INSERT OR REPLACE INTO document(id, data) VALUES(?,?)"],[[a,g]])}).push(function(){return a})},g.prototype.remove=function(c){var d=this._database,f=this;return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["DELETE FROM document WHERE id = ?"],[[c]])}).push(function(b){if(0===b[0].rowsAffected)throw new a.util.jIOError("Cannot find document",404);return c})},g.prototype.get=function(c){var d=this._database,f=this;return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["SELECT data FROM document WHERE id = ?"],[[c]])}).push(function(b){if(0===b[0].rows.length)throw new a.util.jIOError("Cannot find document",404);return JSON.parse(b[0].rows[0].data)})},g.prototype.allAttachments=function(c){var d=this._database,f=this;return(new b.Queue).push(function(){return f._init_db_promise}).push(function(){return e(d,["SELECT id FROM document WHERE id = ?","SELECT DISTINCT attachment FROM attachment WHERE id = ?"],[[c],[c]])}).push(function(b){if(0===b[0].rows.length)throw new a.util.jIOError("Cannot find document",404);var c,d=b[1].rows.length,e={};for(c=0;d>c;c+=1)e[b[1].rows[c].attachment]={};return e})},g.prototype.putAttachment=function(c,d,f){var g=this._database,i=this,j=this._blob_length;return(new b.Queue).push(function(){return i._init_db_promise}).push(function(){return e(g,["SELECT id FROM document WHERE id = ?"],[[c]])}).push(function(i){var k,l,m=[],n=[],o=f.size,p=new b.Queue;if(0===i[0].rows.length)throw new a.util.jIOError("Cannot access subdocument",404);for(m.push("DELETE FROM attachment WHERE id = ? AND attachment = ?"),n.push([c,d]),m.push("INSERT INTO attachment(id, attachment, part, blob)VALUES(?, ?, ?, ?)"),n.push([c,d,-1,f.type||"application/octet-stream"]),k=0,l=0;o>k;k+=j,l+=1)m.push("INSERT INTO attachment(id, attachment, part, blob)VALUES(?, ?, ?, ?)"),n.push([c,d,l]),h(f.slice(k,k+j),n,l,p);return p.push(function(){return e(g,m,n)}),p})},g.prototype.getAttachment=function(d,f,g){var h,i,j,k,l=this._database,m=this,n=this._blob_length;if(void 0===g&&(g={}),h=g.start||0,i=g.end||-1,0>h||void 0!==g.end&&g.end<0)throw new a.util.jIOError("_start and _end must be positive",400);if(h>i&&-1!==i)throw new a.util.jIOError("_start is greater than _end",400);return j=Math.floor(h/n),0===h&&(j-=1),k=Math.floor(i/n),i%n===0&&(k-=1),(new b.Queue).push(function(){return m._init_db_promise}).push(function(){var a="SELECT part, blob FROM attachment WHERE id = ? AND attachment = ? AND part >= ?",b=[d,f,j];return-1!==i&&(a+=" AND part <= ?",b.push(k)),e(l,[a],[b])}).push(function(b){var d,e,f,k,l=[];if(e=b[0].rows,0===e.length)throw new a.util.jIOError("Cannot find document",404);for(d=0;d<e.length;d+=1)-1===e[d].part?(k=e[d].blob,j+=1):l.push(a.util.dataURItoBlob(e[d].blob));return 0===h&&void 0===g.end?new c(l,{type:k}):(f=new c(l,{}),f.slice(h-j*n,-1===i?f.size:i-j*n,"application/octet-stream"))})},g.prototype.removeAttachment=function(c,d){var f=this._database,g=this;return(new b.Queue).push(function(){return g._init_db_promise}).push(function(){return e(f,["DELETE FROM attachment WHERE id = ? AND attachment = ?"],[[c,d]])}).push(function(b){if(0===b[0].rowsAffected)throw new a.util.jIOError("Cannot find document",404);return d})},g.prototype.hasCapacity=function(a){return"list"===a||"include"===a},g.prototype.buildQuery=function(a){var c=this._database,d=this,f="SELECT id";return(new b.Queue).push(function(){return d._init_db_promise}).push(function(){return void 0===a&&(a={}),a.include_docs===!0&&(f+=", data AS doc"),f+=" FROM document",e(c,[f],[[]])}).push(function(a){var b,c=[],d=a[0].rows.length;for(b=0;d>b;b+=1)c.push(a[0].rows[b]),c[b].value={},void 0!==c[b].doc&&(c[b].doc=JSON.parse(c[b].doc));return c})},a.addStorage("websql",g)}(jIO,RSVP,Blob,openDatabase);
\ No newline at end of file
diff --git a/package.json b/package.json
index 26a839bf5d079da14e3fe585ef03e0ed5ed5f6e6..d512203f6d9d5e257f58921d9474da442a17743e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "jio",
-  "version": "v3.10.2",
+  "version": "v3.11.0",
   "license": "LGPLv3",
   "author": "Nexedi SA",
   "contributors": [