Vendor libraries for time formatting.
authordsc <dsc@wikimedia.org>
Thu, 29 Mar 2012 16:22:30 +0000 (09:22 -0700)
committerdsc <dsc@wikimedia.org>
Thu, 29 Mar 2012 16:22:30 +0000 (09:22 -0700)
static/vendor/moment-1.4.0.js [new file with mode: 0644]
static/vendor/moment-1.4.0.min.js [new file with mode: 0644]
static/vendor/moment.js [new symlink]
static/vendor/moment.min.js [new symlink]
static/vendor/strftime.js [new file with mode: 0644]
static/vendor/strftime.min.js [new file with mode: 0644]

diff --git a/static/vendor/moment-1.4.0.js b/static/vendor/moment-1.4.0.js
new file mode 100644 (file)
index 0000000..8a0ad9d
--- /dev/null
@@ -0,0 +1,730 @@
+// moment.js
+// version : 1.4.0
+// author : Tim Wood
+// license : MIT
+// momentjs.com
+
+(function (Date, undefined) {
+
+    var moment,
+        round = Math.round,
+        languages = {},
+        hasModule = (typeof module !== 'undefined'),
+        paramsToParse = 'months|monthsShort|monthsParse|weekdays|weekdaysShort|longDateFormat|calendar|relativeTime|ordinal|meridiem'.split('|'),
+        i,
+        jsonRegex = /^\/?Date\((\-?\d+)/i,
+        charactersToReplace = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|zz?|ZZ?|LT|LL?L?L?)/g,
+        nonuppercaseLetters = /[^A-Z]/g,
+        timezoneRegex = /\([A-Za-z ]+\)|:[0-9]{2} [A-Z]{3} /g,
+        tokenCharacters = /(\\)?(MM?M?M?|dd?d?d|DD?D?D?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|ZZ?|T)/g,
+        inputCharacters = /(\\)?([0-9]+|([a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+|([\+\-]\d\d:?\d\d))/gi,
+        isoRegex = /\d{4}.\d\d.\d\d(T(\d\d(.\d\d(.\d\d)?)?)?([\+\-]\d\d:?\d\d)?)?/,
+        isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
+        isoTimes = [
+            ['HH:mm:ss', /T\d\d:\d\d:\d\d/],
+            ['HH:mm', /T\d\d:\d\d/],
+            ['HH', /T\d\d/]
+        ],
+        timezoneParseRegex = /([\+\-]|\d\d)/gi,
+        VERSION = "1.4.0",
+        shortcuts = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|');
+
+    // Moment prototype object
+    function Moment(date, isUTC) {
+        this._d = date;
+        this._isUTC = !!isUTC;
+    }
+
+    // left zero fill a number
+    // see http://jsperf.com/left-zero-filling for performance comparison
+    function leftZeroFill(number, targetLength) {
+        var output = number + '';
+        while (output.length < targetLength) {
+            output = '0' + output;
+        }
+        return output;
+    }
+
+    // helper function for _.addTime and _.subtractTime
+    function dateAddRemove(date, _input, adding, val) {
+        var isString = (typeof _input === 'string'),
+            input = isString ? {} : _input,
+            ms, d, M, currentDate;
+        if (isString && val) {
+            input[_input] = +val;
+        }
+        ms = (input.ms || input.milliseconds || 0) +
+            (input.s || input.seconds || 0) * 1e3 + // 1000
+            (input.m || input.minutes || 0) * 6e4 + // 1000 * 60
+            (input.h || input.hours || 0) * 36e5; // 1000 * 60 * 60
+        d = (input.d || input.days || 0) +
+            (input.w || input.weeks || 0) * 7;
+        M = (input.M || input.months || 0) +
+            (input.y || input.years || 0) * 12;
+        if (ms) {
+            date.setTime(+date + ms * adding);
+        }
+        if (d) {
+            date.setDate(date.getDate() + d * adding);
+        }
+        if (M) {
+            currentDate = date.getDate();
+            date.setDate(1);
+            date.setMonth(date.getMonth() + M * adding);
+            date.setDate(Math.min(new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(), currentDate));
+        }
+        return date;
+    }
+
+    // check if is an array
+    function isArray(input) {
+        return Object.prototype.toString.call(input) === '[object Array]';
+    }
+
+    // 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 dateFromArray(input) {
+        return new Date(input[0], input[1] || 0, input[2] || 1, input[3] || 0, input[4] || 0, input[5] || 0, input[6] || 0);
+    }
+
+    // format date using native date object
+    function formatMoment(m, inputString) {
+        var currentMonth = m.month(),
+            currentDate = m.date(),
+            currentYear = m.year(),
+            currentDay = m.day(),
+            currentHours = m.hours(),
+            currentMinutes = m.minutes(),
+            currentSeconds = m.seconds(),
+            currentZone = -m.zone(),
+            ordinal = moment.ordinal,
+            meridiem = moment.meridiem;
+        // check if the character is a format
+        // return formatted string or non string.
+        //
+        // uses switch/case instead of an object of named functions (like http://phpjs.org/functions/date:380)
+        // for minification and performance
+        // see http://jsperf.com/object-of-functions-vs-switch for performance comparison
+        function replaceFunction(input) {
+            // create a couple variables to be used later inside one of the cases.
+            var a, b;
+            switch (input) {
+                // MONTH
+            case 'M' :
+                return currentMonth + 1;
+            case 'Mo' :
+                return (currentMonth + 1) + ordinal(currentMonth + 1);
+            case 'MM' :
+                return leftZeroFill(currentMonth + 1, 2);
+            case 'MMM' :
+                return moment.monthsShort[currentMonth];
+            case 'MMMM' :
+                return moment.months[currentMonth];
+            // DAY OF MONTH
+            case 'D' :
+                return currentDate;
+            case 'Do' :
+                return currentDate + ordinal(currentDate);
+            case 'DD' :
+                return leftZeroFill(currentDate, 2);
+            // DAY OF YEAR
+            case 'DDD' :
+                a = new Date(currentYear, currentMonth, currentDate);
+                b = new Date(currentYear, 0, 1);
+                return ~~ (((a - b) / 864e5) + 1.5);
+            case 'DDDo' :
+                a = replaceFunction('DDD');
+                return a + ordinal(a);
+            case 'DDDD' :
+                return leftZeroFill(replaceFunction('DDD'), 3);
+            // WEEKDAY
+            case 'd' :
+                return currentDay;
+            case 'do' :
+                return currentDay + ordinal(currentDay);
+            case 'ddd' :
+                return moment.weekdaysShort[currentDay];
+            case 'dddd' :
+                return moment.weekdays[currentDay];
+            // WEEK OF YEAR
+            case 'w' :
+                a = new Date(currentYear, currentMonth, currentDate - currentDay + 5);
+                b = new Date(a.getFullYear(), 0, 4);
+                return ~~ ((a - b) / 864e5 / 7 + 1.5);
+            case 'wo' :
+                a = replaceFunction('w');
+                return a + ordinal(a);
+            case 'ww' :
+                return leftZeroFill(replaceFunction('w'), 2);
+            // YEAR
+            case 'YY' :
+                return leftZeroFill(currentYear % 100, 2);
+            case 'YYYY' :
+                return currentYear;
+            // AM / PM
+            case 'a' :
+                return currentHours > 11 ? meridiem.pm : meridiem.am;
+            case 'A' :
+                return currentHours > 11 ? meridiem.PM : meridiem.AM;
+            // 24 HOUR
+            case 'H' :
+                return currentHours;
+            case 'HH' :
+                return leftZeroFill(currentHours, 2);
+            // 12 HOUR
+            case 'h' :
+                return currentHours % 12 || 12;
+            case 'hh' :
+                return leftZeroFill(currentHours % 12 || 12, 2);
+            // MINUTE
+            case 'm' :
+                return currentMinutes;
+            case 'mm' :
+                return leftZeroFill(currentMinutes, 2);
+            // SECOND
+            case 's' :
+                return currentSeconds;
+            case 'ss' :
+                return leftZeroFill(currentSeconds, 2);
+            // TIMEZONE
+            case 'zz' :
+                // depreciating 'zz' fall through to 'z'
+            case 'z' :
+                return (m._d.toString().match(timezoneRegex) || [''])[0].replace(nonuppercaseLetters, '');
+            case 'Z' :
+                return (currentZone < 0 ? '-' : '+') + leftZeroFill(~~(Math.abs(currentZone) / 60), 2) + ':' + leftZeroFill(~~(Math.abs(currentZone) % 60), 2);
+            case 'ZZ' :
+                return (currentZone < 0 ? '-' : '+') + leftZeroFill(~~(10 * Math.abs(currentZone) / 6), 4);
+            // LONG DATES
+            case 'L' :
+            case 'LL' :
+            case 'LLL' :
+            case 'LLLL' :
+            case 'LT' :
+                return formatMoment(m, moment.longDateFormat[input]);
+            // DEFAULT
+            default :
+                return input.replace(/(^\[)|(\\)|\]$/g, "");
+            }
+        }
+        return inputString.replace(charactersToReplace, replaceFunction);
+    }
+
+    // date from string and format string
+    function makeDateFromStringAndFormat(string, format) {
+        var inArray = [0, 0, 1, 0, 0, 0, 0],
+            timezoneHours = 0,
+            timezoneMinutes = 0,
+            isUsingUTC = false,
+            inputParts = string.match(inputCharacters),
+            formatParts = format.match(tokenCharacters),
+            len = Math.min(inputParts.length, formatParts.length),
+            i,
+            isPm;
+
+        // function to convert string input to date
+        function addTime(format, input) {
+            var a;
+            switch (format) {
+            // MONTH
+            case 'M' :
+                // fall through to MM
+            case 'MM' :
+                inArray[1] = ~~input - 1;
+                break;
+            case 'MMM' :
+                // fall through to MMMM
+            case 'MMMM' :
+                for (a = 0; a < 12; a++) {
+                    if (moment.monthsParse[a].test(input)) {
+                        inArray[1] = a;
+                        break;
+                    }
+                }
+                break;
+            // DAY OF MONTH
+            case 'D' :
+                // fall through to DDDD
+            case 'DD' :
+                // fall through to DDDD
+            case 'DDD' :
+                // fall through to DDDD
+            case 'DDDD' :
+                inArray[2] = ~~input;
+                break;
+            // YEAR
+            case 'YY' :
+                input = ~~input;
+                inArray[0] = input + (input > 70 ? 1900 : 2000);
+                break;
+            case 'YYYY' :
+                inArray[0] = ~~Math.abs(input);
+                break;
+            // AM / PM
+            case 'a' :
+                // fall through to A
+            case 'A' :
+                isPm = (input.toLowerCase() === 'pm');
+                break;
+            // 24 HOUR
+            case 'H' :
+                // fall through to hh
+            case 'HH' :
+                // fall through to hh
+            case 'h' :
+                // fall through to hh
+            case 'hh' :
+                inArray[3] = ~~input;
+                break;
+            // MINUTE
+            case 'm' :
+                // fall through to mm
+            case 'mm' :
+                inArray[4] = ~~input;
+                break;
+            // SECOND
+            case 's' :
+                // fall through to ss
+            case 'ss' :
+                inArray[5] = ~~input;
+                break;
+            // TIMEZONE
+            case 'Z' :
+                // fall through to ZZ
+            case 'ZZ' :
+                isUsingUTC = true;
+                a = (input || '').match(timezoneParseRegex);
+                if (a && a[1]) {
+                    timezoneHours = ~~a[1];
+                }
+                if (a && a[2]) {
+                    timezoneMinutes = ~~a[2];
+                }
+                // reverse offsets
+                if (a && a[0] === '+') {
+                    timezoneHours = -timezoneHours;
+                    timezoneMinutes = -timezoneMinutes;
+                }
+                break;
+            }
+        }
+        for (i = 0; i < len; i++) {
+            addTime(formatParts[i], inputParts[i]);
+        }
+        // handle am pm
+        if (isPm && inArray[3] < 12) {
+            inArray[3] += 12;
+        }
+        // if is 12 am, change hours to 0
+        if (isPm === false && inArray[3] === 12) {
+            inArray[3] = 0;
+        }
+        // handle timezone
+        inArray[3] += timezoneHours;
+        inArray[4] += timezoneMinutes;
+        // return
+        return isUsingUTC ? new Date(Date.UTC.apply({}, inArray)) : dateFromArray(inArray);
+    }
+
+    // compare two arrays, return the number of differences
+    function compareArrays(array1, array2) {
+        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 (~~array1[i] !== ~~array2[i]) {
+                diffs++;
+            }
+        }
+        return diffs + lengthDiff;
+    }
+
+    // date from string and array of format strings
+    function makeDateFromStringAndArray(string, formats) {
+        var output,
+            inputParts = string.match(inputCharacters),
+            scores = [],
+            scoreToBeat = 99,
+            i,
+            curDate,
+            curScore;
+        for (i = 0; i < formats.length; i++) {
+            curDate = makeDateFromStringAndFormat(string, formats[i]);
+            curScore = compareArrays(inputParts, formatMoment(new Moment(curDate), formats[i]).match(inputCharacters));
+            if (curScore < scoreToBeat) {
+                scoreToBeat = curScore;
+                output = curDate;
+            }
+        }
+        return output;
+    }
+
+    // date from iso format
+    function makeDateFromString(string) {
+        var format = 'YYYY-MM-DDT',
+            i;
+        if (isoRegex.exec(string)) {
+            for (i = 0; i < 3; i++) {
+                if (isoTimes[i][1].exec(string)) {
+                    format += isoTimes[i][0];
+                    break;
+                }
+            }
+            return makeDateFromStringAndFormat(string, format + 'Z');
+        }
+        return new Date(string);
+    }
+
+    // helper function for _date.from() and _date.fromNow()
+    function substituteTimeAgo(string, number, withoutSuffix) {
+        var rt = moment.relativeTime[string];
+        return (typeof rt === 'function') ?
+            rt(number || 1, !!withoutSuffix, string) :
+            rt.replace(/%d/i, number || 1);
+    }
+
+    function relativeTime(milliseconds, withoutSuffix) {
+        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;
+        return substituteTimeAgo.apply({}, args);
+    }
+
+    moment = function (input, format) {
+        if (input === null || input === '') {
+            return null;
+        }
+        var date,
+            matched;
+        // parse Moment object
+        if (input && input._d instanceof Date) {
+            date = new Date(+input._d);
+        // parse string and format
+        } else if (format) {
+            if (isArray(format)) {
+                date = makeDateFromStringAndArray(input, format);
+            } else {
+                date = makeDateFromStringAndFormat(input, format);
+            }
+        // evaluate it as a JSON-encoded date
+        } else {
+            matched = jsonRegex.exec(input);
+            date = input === undefined ? new Date() :
+                matched ? new Date(+matched[1]) :
+                input instanceof Date ? input :
+                isArray(input) ? dateFromArray(input) :
+                typeof input === 'string' ? makeDateFromString(input) :
+                new Date(input);
+        }
+        return new Moment(date);
+    };
+
+    // creating with utc
+    moment.utc = function (input, format) {
+        if (isArray(input)) {
+            return new Moment(new Date(Date.UTC.apply({}, input)), true);
+        }
+        return (format && input) ? moment(input + ' 0', format + ' Z').utc() : moment(input).utc();
+    };
+
+    // humanizeDuration
+    moment.humanizeDuration = function (num, type, withSuffix) {
+        var difference = +num,
+            rel = moment.relativeTime,
+            output;
+        switch (type) {
+        case "seconds" :
+            difference *= 1000; // 1000
+            break;
+        case "minutes" :
+            difference *= 60000; // 60 * 1000
+            break;
+        case "hours" :
+            difference *= 3600000; // 60 * 60 * 1000
+            break;
+        case "days" :
+            difference *= 86400000; // 24 * 60 * 60 * 1000
+            break;
+        case "weeks" :
+            difference *= 604800000; // 7 * 24 * 60 * 60 * 1000
+            break;
+        case "months" :
+            difference *= 2592000000; // 30 * 24 * 60 * 60 * 1000
+            break;
+        case "years" :
+            difference *= 31536000000; // 365 * 24 * 60 * 60 * 1000
+            break;
+        default :
+            withSuffix = !!type;
+            break;
+        }
+        output = relativeTime(difference, !withSuffix);
+        return withSuffix ? (difference <= 0 ? rel.past : rel.future).replace(/%s/i, output) : output;
+    };
+
+    // version number
+    moment.version = VERSION;
+
+    // default format
+    moment.defaultFormat = isoFormat;
+
+    // language switching and caching
+    moment.lang = function (key, values) {
+        var i,
+            param,
+            req,
+            parse = [];
+        if (values) {
+            for (i = 0; i < 12; i++) {
+                parse[i] = new RegExp('^' + values.months[i] + '|^' + values.monthsShort[i].replace('.', ''), 'i');
+            }
+            values.monthsParse = values.monthsParse || parse;
+            languages[key] = values;
+        }
+        if (languages[key]) {
+            for (i = 0; i < paramsToParse.length; i++) {
+                param = paramsToParse[i];
+                moment[param] = languages[key][param] || moment[param];
+            }
+        } else {
+            if (hasModule) {
+                req = require('./lang/' + key);
+                moment.lang(key, req);
+            }
+        }
+    };
+
+    // set default language
+    moment.lang('en', {
+        months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
+        monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
+        weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
+        weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
+        longDateFormat : {
+            LT : "h:mm A",
+            L : "MM/DD/YYYY",
+            LL : "MMMM D YYYY",
+            LLL : "MMMM D YYYY LT",
+            LLLL : "dddd, MMMM D YYYY LT"
+        },
+        meridiem : {
+            AM : 'AM',
+            am : 'am',
+            PM : 'PM',
+            pm : 'pm'
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        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"
+        },
+        ordinal : function (number) {
+            var b = number % 10;
+            return (~~ (number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+        }
+    });
+
+    // shortcut for prototype
+    moment.fn = Moment.prototype = {
+
+        clone : function () {
+            return moment(this);
+        },
+
+        valueOf : function () {
+            return +this._d;
+        },
+
+        'native' : function () {
+            return this._d;
+        },
+
+        toString : function () {
+            return this._d.toString();
+        },
+
+        toDate : function () {
+            return this._d;
+        },
+
+        utc : function () {
+            this._isUTC = true;
+            return this;
+        },
+
+        local : function () {
+            this._isUTC = false;
+            return this;
+        },
+
+        format : function (inputString) {
+            return formatMoment(this, inputString ? inputString : moment.defaultFormat);
+        },
+
+        add : function (input, val) {
+            this._d = dateAddRemove(this._d, input, 1, val);
+            return this;
+        },
+
+        subtract : function (input, val) {
+            this._d = dateAddRemove(this._d, input, -1, val);
+            return this;
+        },
+
+        diff : function (input, val, asFloat) {
+            var inputMoment = moment(input),
+                zoneDiff = (this.zone() - inputMoment.zone()) * 6e4,
+                diff = this._d - inputMoment._d - zoneDiff,
+                year = this.year() - inputMoment.year(),
+                month = this.month() - inputMoment.month(),
+                date = this.date() - inputMoment.date(),
+                output;
+            if (val === 'months') {
+                output = year * 12 + month + date / 30;
+            } else if (val === 'years') {
+                output = year + month / 12;
+            } else {
+                output = val === 'seconds' ? diff / 1e3 : // 1000
+                    val === 'minutes' ? diff / 6e4 : // 1000 * 60
+                    val === 'hours' ? diff / 36e5 : // 1000 * 60 * 60
+                    val === 'days' ? diff / 864e5 : // 1000 * 60 * 60 * 24
+                    val === 'weeks' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
+                    diff;
+            }
+            return asFloat ? output : round(output);
+        },
+
+        from : function (time, withoutSuffix) {
+            return moment.humanizeDuration(this.diff(time), !withoutSuffix);
+        },
+
+        fromNow : function (withoutSuffix) {
+            return this.from(moment(), withoutSuffix);
+        },
+
+        calendar : function () {
+            var diff = this.diff(moment().sod(), 'days', true),
+                calendar = moment.calendar,
+                allElse = calendar.sameElse,
+                format = diff < -6 ? allElse :
+                diff < -1 ? calendar.lastWeek :
+                diff < 0 ? calendar.lastDay :
+                diff < 1 ? calendar.sameDay :
+                diff < 2 ? calendar.nextDay :
+                diff < 7 ? calendar.nextWeek : allElse;
+            return this.format(typeof format === 'function' ? format.apply(this) : format);
+        },
+
+        isLeapYear : function () {
+            var year = this.year();
+            return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+        },
+
+        isDST : function () {
+            return (this.zone() < moment([this.year()]).zone() || 
+                this.zone() < moment([this.year(), 5]).zone());
+        },
+
+        day : function (input) {
+            var day = this._d.getDay();
+            return input == null ? day :
+                this.add({ d : input - day });
+        },
+
+        sod: function () {
+            return this.clone()
+                .hours(0)
+                .minutes(0)
+                .seconds(0)
+                .milliseconds(0);
+        },
+
+        eod: function () {
+            // end of day = start of day plus 1 day, minus 1 millisecond
+            return this.sod().add({
+                d : 1,
+                ms : -1
+            });
+        },
+
+        zone : function () {
+            return this._isUTC ? 0 : this._d.getTimezoneOffset();
+        },
+
+        daysInMonth : function () {
+            return this.clone().month(this.month() + 1).date(0).date();
+        }
+    };
+
+    // helper for adding shortcuts
+    function makeShortcut(name, key) {
+        moment.fn[name] = function (input) {
+            var utc = this._isUTC ? 'UTC' : '';
+            if (input != null) {
+                this._d['set' + utc + key](input);
+                return this;
+            } else {
+                return this._d['get' + utc + key]();
+            }
+        };
+    }
+
+    // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
+    for (i = 0; i < shortcuts.length; i ++) {
+        makeShortcut(shortcuts[i].toLowerCase(), shortcuts[i]);
+    }
+
+    // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
+    makeShortcut('year', 'FullYear');
+
+    // CommonJS module is defined
+    if (hasModule) {
+        module.exports = moment;
+    }
+    if (typeof window !== 'undefined') {
+        window.moment = moment;
+    }
+    /*global define:false */
+    if (typeof define === "function" && define.amd) {
+        define("moment", [], function () {
+            return moment;
+        });
+    }
+})(Date);
diff --git a/static/vendor/moment-1.4.0.min.js b/static/vendor/moment-1.4.0.min.js
new file mode 100644 (file)
index 0000000..c8708cd
--- /dev/null
@@ -0,0 +1,6 @@
+// moment.js
+// version : 1.4.0
+// author : Tim Wood
+// license : MIT
+// momentjs.com
+(function(a,b){function u(a,b){this._d=a,this._isUTC=!!b}function v(a,b){var c=a+"";while(c.length<b)c="0"+c;return c}function w(b,c,d,e){var f=typeof c=="string",g=f?{}:c,h,i,j,k;return f&&e&&(g[c]=+e),h=(g.ms||g.milliseconds||0)+(g.s||g.seconds||0)*1e3+(g.m||g.minutes||0)*6e4+(g.h||g.hours||0)*36e5,i=(g.d||g.days||0)+(g.w||g.weeks||0)*7,j=(g.M||g.months||0)+(g.y||g.years||0)*12,h&&b.setTime(+b+h*d),i&&b.setDate(b.getDate()+i*d),j&&(k=b.getDate(),b.setDate(1),b.setMonth(b.getMonth()+j*d),b.setDate(Math.min((new a(b.getFullYear(),b.getMonth()+1,0)).getDate(),k))),b}function x(a){return Object.prototype.toString.call(a)==="[object Array]"}function y(b){return new a(b[0],b[1]||0,b[2]||1,b[3]||0,b[4]||0,b[5]||0,b[6]||0)}function z(b,d){function r(d){var j,s;switch(d){case"M":return e+1;case"Mo":return e+1+p(e+1);case"MM":return v(e+1,2);case"MMM":return c.monthsShort[e];case"MMMM":return c.months[e];case"D":return f;case"Do":return f+p(f);case"DD":return v(f,2);case"DDD":return j=new a(g,e,f),s=new a(g,0,1),~~((j-s)/864e5+1.5);case"DDDo":return j=r("DDD"),j+p(j);case"DDDD":return v(r("DDD"),3);case"d":return h;case"do":return h+p(h);case"ddd":return c.weekdaysShort[h];case"dddd":return c.weekdays[h];case"w":return j=new a(g,e,f-h+5),s=new a(j.getFullYear(),0,4),~~((j-s)/864e5/7+1.5);case"wo":return j=r("w"),j+p(j);case"ww":return v(r("w"),2);case"YY":return v(g%100,2);case"YYYY":return g;case"a":return i>11?q.pm:q.am;case"A":return i>11?q.PM:q.AM;case"H":return i;case"HH":return v(i,2);case"h":return i%12||12;case"hh":return v(i%12||12,2);case"m":return m;case"mm":return v(m,2);case"s":return n;case"ss":return v(n,2);case"zz":case"z":return(b._d.toString().match(l)||[""])[0].replace(k,"");case"Z":return(o<0?"-":"+")+v(~~(Math.abs(o)/60),2)+":"+v(~~(Math.abs(o)%60),2);case"ZZ":return(o<0?"-":"+")+v(~~(10*Math.abs(o)/6),4);case"L":case"LL":case"LLL":case"LLLL":case"LT":return z(b,c.longDateFormat[d]);default:return d.replace(/(^\[)|(\\)|\]$/g,"")}}var e=b.month(),f=b.date(),g=b.year(),h=b.day(),i=b.hours(),m=b.minutes(),n=b.seconds(),o=-b.zone(),p=c.ordinal,q=c.meridiem;return d.replace(j,r)}function A(b,d){function p(a,b){var d;switch(a){case"M":case"MM":e[1]=~~b-1;break;case"MMM":case"MMMM":for(d=0;d<12;d++)if(c.monthsParse[d].test(b)){e[1]=d;break}break;case"D":case"DD":case"DDD":case"DDDD":e[2]=~~b;break;case"YY":b=~~b,e[0]=b+(b>70?1900:2e3);break;case"YYYY":e[0]=~~Math.abs(b);break;case"a":case"A":o=b.toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":e[3]=~~b;break;case"m":case"mm":e[4]=~~b;break;case"s":case"ss":e[5]=~~b;break;case"Z":case"ZZ":h=!0,d=(b||"").match(r),d&&d[1]&&(f=~~d[1]),d&&d[2]&&(g=~~d[2]),d&&d[0]==="+"&&(f=-f,g=-g)}}var e=[0,0,1,0,0,0,0],f=0,g=0,h=!1,i=b.match(n),j=d.match(m),k=Math.min(i.length,j.length),l,o;for(l=0;l<k;l++)p(j[l],i[l]);return o&&e[3]<12&&(e[3]+=12),o===!1&&e[3]===12&&(e[3]=0),e[3]+=f,e[4]+=g,h?new a(a.UTC.apply({},e)):y(e)}function B(a,b){var c=Math.min(a.length,b.length),d=Math.abs(a.length-b.length),e=0,f;for(f=0;f<c;f++)~~a[f]!==~~b[f]&&e++;return e+d}function C(a,b){var c,d=a.match(n),e=[],f=99,g,h,i;for(g=0;g<b.length;g++)h=A(a,b[g]),i=B(d,z(new u(h),b[g]).match(n)),i<f&&(f=i,c=h);return c}function D(b){var c="YYYY-MM-DDT",d;if(o.exec(b)){for(d=0;d<3;d++)if(q[d][1].exec(b)){c+=q[d][0];break}return A(b,c+"Z")}return new a(b)}function E(a,b,d){var e=c.relativeTime[a];return typeof e=="function"?e(b||1,!!d,a):e.replace(/%d/i,b||1)}function F(a,b){var c=d(Math.abs(a)/1e3),e=d(c/60),f=d(e/60),g=d(f/24),h=d(g/365),i=c<45&&["s",c]||e===1&&["m"]||e<45&&["mm",e]||f===1&&["h"]||f<22&&["hh",f]||g===1&&["d"]||g<=25&&["dd",g]||g<=45&&["M"]||g<345&&["MM",d(g/30)]||h===1&&["y"]||["yy",h];return i[2]=b,E.apply({},i)}function G(a,b){c.fn[a]=function(a){var c=this._isUTC?"UTC":"";return a!=null?(this._d["set"+c+b](a),this):this._d["get"+c+b]()}}var c,d=Math.round,e={},f=typeof module!="undefined",g="months|monthsShort|monthsParse|weekdays|weekdaysShort|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),h,i=/^\/?Date\((\-?\d+)/i,j=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|zz?|ZZ?|LT|LL?L?L?)/g,k=/[^A-Z]/g,l=/\([A-Za-z ]+\)|:[0-9]{2} [A-Z]{3} /g,m=/(\\)?(MM?M?M?|dd?d?d|DD?D?D?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|ZZ?|T)/g,n=/(\\)?([0-9]+|([a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+|([\+\-]\d\d:?\d\d))/gi,o=/\d{4}.\d\d.\d\d(T(\d\d(.\d\d(.\d\d)?)?)?([\+\-]\d\d:?\d\d)?)?/,p="YYYY-MM-DDTHH:mm:ssZ",q=[["HH:mm:ss",/T\d\d:\d\d:\d\d/],["HH:mm",/T\d\d:\d\d/],["HH",/T\d\d/]],r=/([\+\-]|\d\d)/gi,s="1.4.0",t="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|");c=function(c,d){if(c===null||c==="")return null;var e,f;return c&&c._d instanceof a?e=new a(+c._d):d?x(d)?e=C(c,d):e=A(c,d):(f=i.exec(c),e=c===b?new a:f?new a(+f[1]):c instanceof a?c:x(c)?y(c):typeof c=="string"?D(c):new a(c)),new u(e)},c.utc=function(b,d){return x(b)?new u(new a(a.UTC.apply({},b)),!0):d&&b?c(b+" 0",d+" Z").utc():c(b).utc()},c.humanizeDuration=function(a,b,d){var e=+a,f=c.relativeTime,g;switch(b){case"seconds":e*=1e3;break;case"minutes":e*=6e4;break;case"hours":e*=36e5;break;case"days":e*=864e5;break;case"weeks":e*=6048e5;break;case"months":e*=2592e6;break;case"years":e*=31536e6;break;default:d=!!b}return g=F(e,!d),d?(e<=0?f.past:f.future).replace(/%s/i,g):g},c.version=s,c.defaultFormat=p,c.lang=function(a,b){var d,h,i,j=[];if(b){for(d=0;d<12;d++)j[d]=new RegExp("^"+b.months[d]+"|^"+b.monthsShort[d].replace(".",""),"i");b.monthsParse=b.monthsParse||j,e[a]=b}if(e[a])for(d=0;d<g.length;d++)h=g[d],c[h]=e[a][h]||c[h];else f&&(i=require("./lang/"+a),c.lang(a,i))},c.lang("en",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},meridiem:{AM:"AM",am:"am",PM:"PM",pm:"pm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},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"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}}),c.fn=u.prototype={clone:function(){return c(this)},valueOf:function(){return+this._d},"native":function(){return this._d},toString:function(){return this._d.toString()},toDate:function(){return this._d},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(a){return z(this,a?a:c.defaultFormat)},add:function(a,b){return this._d=w(this._d,a,1,b),this},subtract:function(a,b){return this._d=w(this._d,a,-1,b),this},diff:function(a,b,e){var f=c(a),g=(this.zone()-f.zone())*6e4,h=this._d-f._d-g,i=this.year()-f.year(),j=this.month()-f.month(),k=this.date()-f.date(),l;return b==="months"?l=i*12+j+k/30:b==="years"?l=i+j/12:l=b==="seconds"?h/1e3:b==="minutes"?h/6e4:b==="hours"?h/36e5:b==="days"?h/864e5:b==="weeks"?h/6048e5:h,e?l:d(l)},from:function(a,b){return c.humanizeDuration(this.diff(a),!b)},fromNow:function(a){return this.from(c(),a)},calendar:function(){var a=this.diff(c().sod(),"days",!0),b=c.calendar,d=b.sameElse,e=a<-6?d:a<-1?b.lastWeek:a<0?b.lastDay:a<1?b.sameDay:a<2?b.nextDay:a<7?b.nextWeek:d;return this.format(typeof e=="function"?e.apply(this):e)},isLeapYear:function(){var a=this.year();return a%4===0&&a%100!==0||a%400===0},isDST:function(){return this.zone()<c([this.year()]).zone()||this.zone()<c([this.year(),5]).zone()},day:function(a){var b=this._d.getDay();return a==null?b:this.add({d:a-b})},sod:function(){return this.clone().hours(0).minutes(0).seconds(0).milliseconds(0)},eod:function(){return this.sod().add({d:1,ms:-1})},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return this.clone().month(this.month()+1).date(0).date()}};for(h=0;h<t.length;h++)G(t[h].toLowerCase(),t[h]);G("year","FullYear"),f&&(module.exports=c),typeof window!="undefined"&&(window.moment=c),typeof define=="function"&&define.amd&&define("moment",[],function(){return c})})(Date);
\ No newline at end of file
diff --git a/static/vendor/moment.js b/static/vendor/moment.js
new file mode 120000 (symlink)
index 0000000..8c19962
--- /dev/null
@@ -0,0 +1 @@
+moment-1.4.0.js
\ No newline at end of file
diff --git a/static/vendor/moment.min.js b/static/vendor/moment.min.js
new file mode 120000 (symlink)
index 0000000..5a9dec9
--- /dev/null
@@ -0,0 +1 @@
+moment-1.4.0.min.js
\ No newline at end of file
diff --git a/static/vendor/strftime.js b/static/vendor/strftime.js
new file mode 100644 (file)
index 0000000..a5659b8
--- /dev/null
@@ -0,0 +1,106 @@
+// version 0.11 by Daniel Rench
+// More information: http://dren.ch/strftime/
+// This is public domain software
+
+Number.prototype.pad =
+       function (n,p) {
+               var s = '' + this;
+               p = p || '0';
+               while (s.length < n) s = p + s;
+               return s;
+       };
+
+Date.prototype.months = [
+               'January', 'February', 'March', 'April', 'May', 'June', 'July',
+               'August', 'September', 'October', 'November', 'December'
+       ];
+Date.prototype.weekdays = [
+               'Sunday', 'Monday', 'Tuesday', 'Wednesday',
+               'Thursday', 'Friday', 'Saturday'
+       ];
+Date.prototype.dpm = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
+
+Date.prototype.strftime_f = {
+               A: function (d) { return d.weekdays[d.getDay()] },
+               a: function (d) { return d.weekdays[d.getDay()].substring(0,3) },
+               B: function (d) { return d.months[d.getMonth()] },
+               b: function (d) { return d.months[d.getMonth()].substring(0,3) },
+               C: function (d) { return Math.floor(d.getFullYear()/100); },
+               c: function (d) { return d.toString() },
+               D: function (d) {
+                               return d.strftime_f.m(d) + '/' +
+                                       d.strftime_f.d(d) + '/' + d.strftime_f.y(d);
+                       },
+               d: function (d) { return d.getDate().pad(2,'0') },
+               e: function (d) { return d.getDate().pad(2,' ') },
+               F: function (d) {
+                               return d.strftime_f.Y(d) + '-' + d.strftime_f.m(d) + '-' +
+                                       d.strftime_f.d(d);
+                       },
+               H: function (d) { return d.getHours().pad(2,'0') },
+               I: function (d) { return ((d.getHours() % 12 || 12).pad(2)) },
+               j: function (d) {
+                               var t = d.getDate();
+                               var m = d.getMonth() - 1;
+                               if (m > 1) {
+                                       var y = d.getYear();
+                                       if (((y % 100) == 0) && ((y % 400) == 0)) ++t;
+                                       else if ((y % 4) == 0) ++t;
+                               }
+                               while (m > -1) t += d.dpm[m--];
+                               return t.pad(3,'0');
+                       },
+               k: function (d) { return d.getHours().pad(2,' ') },
+               l: function (d) { return ((d.getHours() % 12 || 12).pad(2,' ')) },
+               M: function (d) { return d.getMinutes().pad(2,'0') },
+               m: function (d) { return (d.getMonth()+1).pad(2,'0') },
+               n: function (d) { return "\n" },
+               p: function (d) { return (d.getHours() > 11) ? 'PM' : 'AM' },
+               R: function (d) { return d.strftime_f.H(d) + ':' + d.strftime_f.M(d) },
+               r: function (d) {
+                               return d.strftime_f.I(d) + ':' + d.strftime_f.M(d) + ':' +
+                                       d.strftime_f.S(d) + ' ' + d.strftime_f.p(d);
+                       },
+               S: function (d) { return d.getSeconds().pad(2,'0') },
+               s: function (d) { return Math.floor(d.getTime()/1000) },
+               T: function (d) {
+                               return d.strftime_f.H(d) + ':' + d.strftime_f.M(d) + ':' +
+                                       d.strftime_f.S(d);
+                       },
+               t: function (d) { return "\t" },
+/*             U: function (d) { return false }, */
+               u: function (d) { return(d.getDay() || 7) },
+/*             V: function (d) { return false }, */
+               v: function (d) {
+                               return d.strftime_f.e(d) + '-' + d.strftime_f.b(d) + '-' +
+                                       d.strftime_f.Y(d);
+                       },
+/*             W: function (d) { return false }, */
+               w: function (d) { return d.getDay() },
+               X: function (d) { return d.toTimeString() }, // wrong?
+               x: function (d) { return d.toDateString() }, // wrong?
+               Y: function (d) { return d.getFullYear() },
+               y: function (d) { return (d.getYear() % 100).pad(2) },
+//             Z: function (d) { return d.toString().match(/\((.+)\)$/)[1]; },
+//             z: function (d) { return d.getTimezoneOffset() }, // wrong
+//             z: function (d) { return d.toString().match(/\sGMT([+-]\d+)/)[1]; },
+               '%': function (d) { return '%' }
+       };
+
+Date.prototype.strftime_f['+'] = Date.prototype.strftime_f.c;
+Date.prototype.strftime_f.h = Date.prototype.strftime_f.b;
+
+Date.prototype.strftime =
+       function (fmt) {
+               var r = '';
+               var n = 0;
+               while(n < fmt.length) {
+                       var c = fmt.substring(n, n+1);
+                       if (c == '%') {
+                               c = fmt.substring(++n, n+1);
+                               r += (this.strftime_f[c]) ? this.strftime_f[c](this) : c;
+                       } else r += c;
+                       ++n;
+               }
+               return r;
+       };
diff --git a/static/vendor/strftime.min.js b/static/vendor/strftime.min.js
new file mode 100644 (file)
index 0000000..50a9444
--- /dev/null
@@ -0,0 +1 @@
+Number.prototype.pad=function(c,b){var a=""+this;b=b||"0";while(a.length<c){a=b+a}return a};Date.prototype.months=["January","February","March","April","May","June","July","August","September","October","November","December"];Date.prototype.weekdays=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];Date.prototype.dpm=[31,28,31,30,31,30,31,31,30,31,30,31];Date.prototype.strftime_f={A:function(a){return a.weekdays[a.getDay()]},a:function(a){return a.weekdays[a.getDay()].substring(0,3)},B:function(a){return a.months[a.getMonth()]},b:function(a){return a.months[a.getMonth()].substring(0,3)},C:function(a){return Math.floor(a.getFullYear()/100)},c:function(a){return a.toString()},D:function(a){return a.strftime_f.m(a)+"/"+a.strftime_f.d(a)+"/"+a.strftime_f.y(a)},d:function(a){return a.getDate().pad(2,"0")},e:function(a){return a.getDate().pad(2," ")},F:function(a){return a.strftime_f.Y(a)+"-"+a.strftime_f.m(a)+"-"+a.strftime_f.d(a)},H:function(a){return a.getHours().pad(2,"0")},I:function(a){return((a.getHours()%12||12).pad(2))},j:function(c){var b=c.getDate();var a=c.getMonth()-1;if(a>1){var e=c.getYear();if(((e%100)==0)&&((e%400)==0)){++b}else{if((e%4)==0){++b}}}while(a>-1){b+=c.dpm[a--]}return b.pad(3,"0")},k:function(a){return a.getHours().pad(2," ")},l:function(a){return((a.getHours()%12||12).pad(2," "))},M:function(a){return a.getMinutes().pad(2,"0")},m:function(a){return(a.getMonth()+1).pad(2,"0")},n:function(a){return"\n"},p:function(a){return(a.getHours()>11)?"PM":"AM"},R:function(a){return a.strftime_f.H(a)+":"+a.strftime_f.M(a)},r:function(a){return a.strftime_f.I(a)+":"+a.strftime_f.M(a)+":"+a.strftime_f.S(a)+" "+a.strftime_f.p(a)},S:function(a){return a.getSeconds().pad(2,"0")},s:function(a){return Math.floor(a.getTime()/1000)},T:function(a){return a.strftime_f.H(a)+":"+a.strftime_f.M(a)+":"+a.strftime_f.S(a)},t:function(a){return"\t"},u:function(a){return(a.getDay()||7)},v:function(a){return a.strftime_f.e(a)+"-"+a.strftime_f.b(a)+"-"+a.strftime_f.Y(a)},w:function(a){return a.getDay()},X:function(a){return a.toTimeString()},x:function(a){return a.toDateString()},Y:function(a){return a.getFullYear()},y:function(a){return(a.getYear()%100).pad(2)},"%":function(a){return"%"}};Date.prototype.strftime_f["+"]=Date.prototype.strftime_f.c;Date.prototype.strftime_f.h=Date.prototype.strftime_f.b;Date.prototype.strftime=function(a){var b="";var e=0;while(e<a.length){var d=a.substring(e,e+1);if(d=="%"){d=a.substring(++e,e+1);b+=(this.strftime_f[d])?this.strftime_f[d](this):d}else{b+=d}++e}return b};
\ No newline at end of file