<commit_before>define(function (require) {

    'use strict';

    var zrUtil = require('zrender/core/util');
    var graphic = require('../../util/graphic');
    var formatUtil = require('../../util/format');
    var numberUtil = require('../../util/number');

    var MONTH_TEXT = {
        EN: [
                'Jan', 'Feb', 'Mar',
                'Apr', 'May', 'Jun',
                'Jul', 'Aug', 'Sep',
                'Oct', 'Nov', 'Dec'
            ],
        CN: [
                '一月', '二月', '三月',
                '四月', '五月', '六月',
                '七月', '八月', '九月',
                '十月', '十一月', '十二月'
            ]
    };

    var WEEK_TEXT = {
        EN: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
        CN: ['日', '一', '二', '三', '四', '五', '六']
    };

    return require('../../echarts').extendComponentView({

        type: 'calendar',

        /**
         * top/left line points
         *  @private
         */
        _tlpoints: null,

        /**
         * bottom/right line points
         *  @private
         */
        _blpoints: null,

        /**
         * first day of month
         *  @private
         */
        _firstDayOfMonth: null,

        /**
         * first day point of month
         *  @private
         */
        _firstDayPoints: null,

        render: function (calendarModel, ecModel, api) {

            var group = this.group;

            group.removeAll();

            var coordSys = calendarModel.coordinateSystem;

            // range info
            var rangeData = coordSys.getRangeInfo();
            var orient = coordSys.getOrient();

            this._renderDayRect(calendarModel, rangeData, group);

            // _renderLines must be called prior to following function
            this._renderLines(calendarModel, rangeData, orient, group);

            this._renderYearText(calendarModel, rangeData, orient, group);

            this._renderMonthText(calendarModel, orient, group);

            this._renderWeekText(calendarModel, rangeData, orient, group);
        },

        // render day rect
        _renderDayRect: function (calendarModel, rangeData, group) {
            var coordSys = calendarModel.coordinateSystem;
            var itemRectStyleModel = calendarModel.getModel('itemStyle.normal').getItemStyle();
            var sw = coordSys.getCellWidth();
            var sh = coordSys.getCellHeight();

            for (var i = rangeData.start.time;
                i <= rangeData.end.time;
                i = coordSys.getNextNDay(i, 1).time
            ) {

                var point = coordSys.dataToRect([i], false).tl;

                // every rect
                var rect = new graphic.Rect({
                    shape: {
                        x: point[0],
                        y: point[1],
                        width: sw,
                        height: sh
                    },
                    cursor: 'default',
                    style: itemRectStyleModel
                });

                group.add(rect);
            }

        },

        // render separate line
        _renderLines: function (calendarModel, rangeData, orient, group) {

            var self = this;

            var coordSys = calendarModel.coordinateSystem;

            var lineStyleModel = calendarModel.getModel('splitLine.lineStyle').getLineStyle();
            var show = calendarModel.get('splitLine.show');

            var lineWidth = lineStyleModel.lineWidth;

            this._tlpoints = [];
            this._blpoints = [];
            this._firstDayOfMonth = [];
            this._firstDayPoints = [];

            var firstDay = rangeData.start;

            for (var i = 0; firstDay.time <= rangeData.end.time; i++) {
                addPoints(firstDay.formatedDate);

                if (i === 0) {
                    firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m);
                }

                var date = firstDay.date;
                date.setMonth(date.getMonth() + 1);
                firstDay = coordSys.getDateInfo(date);
            }

            addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate);

            function addPoints(date) {

                self._firstDayOfMonth.push(coordSys.getDateInfo(date));
                self._firstDayPoints.push(coordSys.dataToRect([date], false).tl);

                var points = self._getLinePointsOfOneWeek(calendarModel, date, orient);

                self._tlpoints.push(points[0]);
                self._blpoints.push(points[points.length - 1]);

                show && self._drawSplitline(points, lineStyleModel, group);
            }

            // render top/left line
            show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group);

            // render bottom/right line
            show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group);

        },

        // get points at both ends
        _getEdgesPoints: function (points, lineWidth, orient) {
            var rs = [points[0].slice(), points[points.length - 1].slice()];
            var idx = orient === 'horizontal' ? 0 : 1;

            // both ends of the line are extend half lineWidth
            rs[0][idx] = rs[0][idx] - lineWidth / 2;
            rs[1][idx] = rs[1][idx] + lineWidth / 2;

            return rs;
        },

        // render split line
        _drawSplitline: function (points, lineStyleModel, group) {

            var poyline = new graphic.Polyline({
                z2: 20,
                shape: {
                    points: points
                },
                style: lineStyleModel
            });

            group.add(poyline);
        },

        // render month line of one week points
        _getLinePointsOfOneWeek: function (calendarModel, date, orient) {

            var coordSys = calendarModel.coordinateSystem;
            date = coordSys.getDateInfo(date);

            var points = [];

            for (var i = 0; i < 7; i++) {

                var tmpD = coordSys.getNextNDay(date.time, i);
                var point = coordSys.dataToRect([tmpD.time], false);

                points[2 * tmpD.day] = point.tl;
                points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr'];
            }

            return points;

        },

        _formatterLabel: function (formatter, params) {

            if (typeof formatter === 'string' && formatter) {
                return formatUtil.formatTplSimple(formatter, params);
            }

            if (typeof formatter === 'function') {
                return formatter(params);
            }

            return params.nameMap;

        },

        _yearTextPositionControl: function (point, orient, position, margin) {

            point = point.slice();
            var aligns = ['center', 'bottom'];

            if (position === 'top') {
                point[1] -= margin;
            }
            if (position === 'bottom') {
                point[1] += margin;
                aligns = ['center', 'top'];
            }
            if (position === 'left') {
                point[0] -= margin;
            }
            if (position === 'right') {
                point[0] += margin;
                aligns = ['center', 'top'];
            }

            var rotate = 0;
            if (position === 'left' || position === 'right') {
                rotate = Math.PI / 2;
            }

            return {
                rotation: rotate,
                origin: point,
                style: {
                    x: point[0],
                    y: point[1],
                    textAlign: aligns[0],
                    textVerticalAlign: aligns[1]
                }
            };
        },

        // render year
        _renderYearText: function (calendarModel, rangeData, orient, group) {
            var yearLabel = calendarModel.getModel('yearLabel');

            if (!yearLabel.get('show')) {
                return;
            }

            var margin = yearLabel.get('margin');
            var pos = yearLabel.get('position');

            if (!pos) {
                pos = orient !== 'horizontal' ? 'top' : 'left';
            }

            var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]];
            var xc = (points[0][0] + points[1][0]) / 2;
            var yc = (points[0][1] + points[1][1]) / 2;

            var idx = orient === 'horizontal' ? 0 : 1;

            var posPoints = {
                top: [xc, points[idx][1]],
                bottom: [xc, points[1 - idx][1]],
                left: [points[1 - idx][0], yc],
                right: [points[idx][0], yc]
            };

            var name = rangeData.start.y;

            if (+rangeData.end.y > +rangeData.start.y) {
                name = name + '-' + rangeData.end.y;
            }

            var formatter = yearLabel.get('formatter');

            var params = {
                start: rangeData.start.y,
                end: rangeData.end.y,
                nameMap: name
            };

            var content = this._formatterLabel(formatter, params);

            var yearText = new graphic.Text(
                zrUtil.merge(
                    {z2: 30},
                    this._yearTextPositionControl(posPoints[pos], orient, pos, margin)
                )
            );
            graphic.setTextStyle(yearText.style, yearLabel, {text: content});

            group.add(yearText);
        },

        _monthTextPositionControl: function (point, isCenter, orient, position, margin) {
            var align = 'left';
            var vAlign = 'top';
            var x = point[0];
            var y = point[1];

            if (orient === 'horizontal') {
                y = y + margin;

                if (isCenter) {
                    align = 'center';
                }

                if (position === 'start') {
                    vAlign = 'bottom';
                }
            }
            else {
                x = x + margin;

                if (isCenter) {
                    vAlign = 'middle';
                }

                if (position === 'start') {
                    align = 'right';
                }
            }

            return {
                x: x,
                y: y,
                textAlign: align,
                textVerticalAlign: vAlign
            };
        },

        // render month and year text
        _renderMonthText: function (calendarModel, orient, group) {
            var monthLabel = calendarModel.getModel('monthLabel');

            if (!monthLabel.get('show')) {
                return;
            }

            var nameMap = monthLabel.get('nameMap');
            var margin = monthLabel.get('margin');
            var pos = monthLabel.get('position');
            var align = monthLabel.get('align');

            var termPoints = [this._tlpoints, this._blpoints];

            if (zrUtil.isString(nameMap)) {
                nameMap = MONTH_TEXT[nameMap.toUpperCase()] || [];
            }

            var idx = pos === 'start' ? 0 : 1;
            var axis = orient === 'horizontal' ? 0 : 1;
            margin = pos === 'start' ? -margin : margin;
            var isCenter = (align === 'center');

            for (var i = 0; i < termPoints[idx].length - 1; i++) {

                var tmp = termPoints[idx][i].slice();
                var firstDay = this._firstDayOfMonth[i];

                if (isCenter) {
                    var firstDayPoints = this._firstDayPoints[i];
                    tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2;
                }

                var formatter = monthLabel.get('formatter');
                var name = nameMap[+firstDay.m - 1];
                var params = {
                    yyyy: firstDay.y,
                    yy: (firstDay.y + '').slice(2),
                    MM: firstDay.m,
                    M: +firstDay.m,
                    nameMap: name
                };

                var content = this._formatterLabel(formatter, params);

                var monthText = new graphic.Text({z2: 30});
                zrUtil.extend(
                    graphic.setTextStyle(monthText.style, monthLabel, {text: content}),
                    this._monthTextPositionControl(tmp, isCenter, orient, pos, margin)
                );

                group.add(monthText);
            }
        },

        _weekTextPositionControl: function (point, orient, position, margin, cellSize) {
            var align = 'center';
            var vAlign = 'middle';
            var x = point[0];
            var y = point[1];
            var isStart = position === 'start';

            if (orient === 'horizontal') {
                x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2;
                align = isStart ? 'right' : 'left';
            }
            else {
                y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2;
                vAlign = isStart ? 'bottom' : 'top';
            }

            return {
                x: x,
                y: y,
                textAlign: align,
                textVerticalAlign: vAlign
            };
        },

        // render weeks
        _renderWeekText: function (calendarModel, rangeData, orient, group) {
            var dayLabel = calendarModel.getModel('dayLabel');

            if (!dayLabel.get('show')) {
                return;
            }

            var coordSys = calendarModel.coordinateSystem;
            var pos = dayLabel.get('position');
            var nameMap = dayLabel.get('nameMap');
            var margin = dayLabel.get('margin');
            var firstDayOfWeek = coordSys.getFirstDayOfWeek();

            if (zrUtil.isString(nameMap)) {
                nameMap = WEEK_TEXT[nameMap.toUpperCase()] || [];
            }

            var start = coordSys.getNextNDay(
                rangeData.end.time, (7 - rangeData.lweek)
            ).time;

            var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()];
            margin = numberUtil.parsePercent(margin, cellSize[orient === 'horizontal' ? 0 : 1]);

            if (pos === 'start') {
                start = coordSys.getNextNDay(
                    rangeData.start.time, -(7 + rangeData.fweek)
                ).time;
                margin = -margin;
            }

            for (var i = 0; i < 7; i++) {

                var tmpD = coordSys.getNextNDay(start, i);
                var point = coordSys.dataToRect([tmpD.time], false).center;
                var day = i;
                day = Math.abs((i + firstDayOfWeek) % 7);
                var weekText = new graphic.Text({z2: 30});

                zrUtil.extend(
                    graphic.setTextStyle(weekText.style, dayLabel, {text: nameMap[day]}),
                    this._weekTextPositionControl(point, orient, pos, margin, cellSize)
                );
                group.add(weekText);
            }
        }
    });
});
<commit_msg>fix calendar year text.<commit_after>define(function (require) {

    'use strict';

    var zrUtil = require('zrender/core/util');
    var graphic = require('../../util/graphic');
    var formatUtil = require('../../util/format');
    var numberUtil = require('../../util/number');

    var MONTH_TEXT = {
        EN: [
                'Jan', 'Feb', 'Mar',
                'Apr', 'May', 'Jun',
                'Jul', 'Aug', 'Sep',
                'Oct', 'Nov', 'Dec'
            ],
        CN: [
                '一月', '二月', '三月',
                '四月', '五月', '六月',
                '七月', '八月', '九月',
                '十月', '十一月', '十二月'
            ]
    };

    var WEEK_TEXT = {
        EN: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
        CN: ['日', '一', '二', '三', '四', '五', '六']
    };

    return require('../../echarts').extendComponentView({

        type: 'calendar',

        /**
         * top/left line points
         *  @private
         */
        _tlpoints: null,

        /**
         * bottom/right line points
         *  @private
         */
        _blpoints: null,

        /**
         * first day of month
         *  @private
         */
        _firstDayOfMonth: null,

        /**
         * first day point of month
         *  @private
         */
        _firstDayPoints: null,

        render: function (calendarModel, ecModel, api) {

            var group = this.group;

            group.removeAll();

            var coordSys = calendarModel.coordinateSystem;

            // range info
            var rangeData = coordSys.getRangeInfo();
            var orient = coordSys.getOrient();

            this._renderDayRect(calendarModel, rangeData, group);

            // _renderLines must be called prior to following function
            this._renderLines(calendarModel, rangeData, orient, group);

            this._renderYearText(calendarModel, rangeData, orient, group);

            this._renderMonthText(calendarModel, orient, group);

            this._renderWeekText(calendarModel, rangeData, orient, group);
        },

        // render day rect
        _renderDayRect: function (calendarModel, rangeData, group) {
            var coordSys = calendarModel.coordinateSystem;
            var itemRectStyleModel = calendarModel.getModel('itemStyle.normal').getItemStyle();
            var sw = coordSys.getCellWidth();
            var sh = coordSys.getCellHeight();

            for (var i = rangeData.start.time;
                i <= rangeData.end.time;
                i = coordSys.getNextNDay(i, 1).time
            ) {

                var point = coordSys.dataToRect([i], false).tl;

                // every rect
                var rect = new graphic.Rect({
                    shape: {
                        x: point[0],
                        y: point[1],
                        width: sw,
                        height: sh
                    },
                    cursor: 'default',
                    style: itemRectStyleModel
                });

                group.add(rect);
            }

        },

        // render separate line
        _renderLines: function (calendarModel, rangeData, orient, group) {

            var self = this;

            var coordSys = calendarModel.coordinateSystem;

            var lineStyleModel = calendarModel.getModel('splitLine.lineStyle').getLineStyle();
            var show = calendarModel.get('splitLine.show');

            var lineWidth = lineStyleModel.lineWidth;

            this._tlpoints = [];
            this._blpoints = [];
            this._firstDayOfMonth = [];
            this._firstDayPoints = [];

            var firstDay = rangeData.start;

            for (var i = 0; firstDay.time <= rangeData.end.time; i++) {
                addPoints(firstDay.formatedDate);

                if (i === 0) {
                    firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m);
                }

                var date = firstDay.date;
                date.setMonth(date.getMonth() + 1);
                firstDay = coordSys.getDateInfo(date);
            }

            addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate);

            function addPoints(date) {

                self._firstDayOfMonth.push(coordSys.getDateInfo(date));
                self._firstDayPoints.push(coordSys.dataToRect([date], false).tl);

                var points = self._getLinePointsOfOneWeek(calendarModel, date, orient);

                self._tlpoints.push(points[0]);
                self._blpoints.push(points[points.length - 1]);

                show && self._drawSplitline(points, lineStyleModel, group);
            }

            // render top/left line
            show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group);

            // render bottom/right line
            show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group);

        },

        // get points at both ends
        _getEdgesPoints: function (points, lineWidth, orient) {
            var rs = [points[0].slice(), points[points.length - 1].slice()];
            var idx = orient === 'horizontal' ? 0 : 1;

            // both ends of the line are extend half lineWidth
            rs[0][idx] = rs[0][idx] - lineWidth / 2;
            rs[1][idx] = rs[1][idx] + lineWidth / 2;

            return rs;
        },

        // render split line
        _drawSplitline: function (points, lineStyleModel, group) {

            var poyline = new graphic.Polyline({
                z2: 20,
                shape: {
                    points: points
                },
                style: lineStyleModel
            });

            group.add(poyline);
        },

        // render month line of one week points
        _getLinePointsOfOneWeek: function (calendarModel, date, orient) {

            var coordSys = calendarModel.coordinateSystem;
            date = coordSys.getDateInfo(date);

            var points = [];

            for (var i = 0; i < 7; i++) {

                var tmpD = coordSys.getNextNDay(date.time, i);
                var point = coordSys.dataToRect([tmpD.time], false);

                points[2 * tmpD.day] = point.tl;
                points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr'];
            }

            return points;

        },

        _formatterLabel: function (formatter, params) {

            if (typeof formatter === 'string' && formatter) {
                return formatUtil.formatTplSimple(formatter, params);
            }

            if (typeof formatter === 'function') {
                return formatter(params);
            }

            return params.nameMap;

        },

        _yearTextPositionControl: function (textEl, point, orient, position, margin) {

            point = point.slice();
            var aligns = ['center', 'bottom'];

            if (position === 'bottom') {
                point[1] += margin;
                aligns = ['center', 'top'];
            }
            else if (position === 'left') {
                point[0] -= margin;
            }
            else if (position === 'right') {
                point[0] += margin;
                aligns = ['center', 'top'];
            }
            else { // top
                point[1] -= margin;
            }

            var rotate = 0;
            if (position === 'left' || position === 'right') {
                rotate = Math.PI / 2;
            }

            return {
                rotation: rotate,
                position: point,
                style: {
                    textAlign: aligns[0],
                    textVerticalAlign: aligns[1]
                }
            };
        },

        // render year
        _renderYearText: function (calendarModel, rangeData, orient, group) {
            var yearLabel = calendarModel.getModel('yearLabel');

            if (!yearLabel.get('show')) {
                return;
            }

            var margin = yearLabel.get('margin');
            var pos = yearLabel.get('position');

            if (!pos) {
                pos = orient !== 'horizontal' ? 'top' : 'left';
            }

            var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]];
            var xc = (points[0][0] + points[1][0]) / 2;
            var yc = (points[0][1] + points[1][1]) / 2;

            var idx = orient === 'horizontal' ? 0 : 1;

            var posPoints = {
                top: [xc, points[idx][1]],
                bottom: [xc, points[1 - idx][1]],
                left: [points[1 - idx][0], yc],
                right: [points[idx][0], yc]
            };

            var name = rangeData.start.y;

            if (+rangeData.end.y > +rangeData.start.y) {
                name = name + '-' + rangeData.end.y;
            }

            var formatter = yearLabel.get('formatter');

            var params = {
                start: rangeData.start.y,
                end: rangeData.end.y,
                nameMap: name
            };

            var content = this._formatterLabel(formatter, params);

            var yearText = new graphic.Text({z2: 30});
            graphic.setTextStyle(yearText.style, yearLabel, {text: content}),
            yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin));

            group.add(yearText);
        },

        _monthTextPositionControl: function (point, isCenter, orient, position, margin) {
            var align = 'left';
            var vAlign = 'top';
            var x = point[0];
            var y = point[1];

            if (orient === 'horizontal') {
                y = y + margin;

                if (isCenter) {
                    align = 'center';
                }

                if (position === 'start') {
                    vAlign = 'bottom';
                }
            }
            else {
                x = x + margin;

                if (isCenter) {
                    vAlign = 'middle';
                }

                if (position === 'start') {
                    align = 'right';
                }
            }

            return {
                x: x,
                y: y,
                textAlign: align,
                textVerticalAlign: vAlign
            };
        },

        // render month and year text
        _renderMonthText: function (calendarModel, orient, group) {
            var monthLabel = calendarModel.getModel('monthLabel');

            if (!monthLabel.get('show')) {
                return;
            }

            var nameMap = monthLabel.get('nameMap');
            var margin = monthLabel.get('margin');
            var pos = monthLabel.get('position');
            var align = monthLabel.get('align');

            var termPoints = [this._tlpoints, this._blpoints];

            if (zrUtil.isString(nameMap)) {
                nameMap = MONTH_TEXT[nameMap.toUpperCase()] || [];
            }

            var idx = pos === 'start' ? 0 : 1;
            var axis = orient === 'horizontal' ? 0 : 1;
            margin = pos === 'start' ? -margin : margin;
            var isCenter = (align === 'center');

            for (var i = 0; i < termPoints[idx].length - 1; i++) {

                var tmp = termPoints[idx][i].slice();
                var firstDay = this._firstDayOfMonth[i];

                if (isCenter) {
                    var firstDayPoints = this._firstDayPoints[i];
                    tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2;
                }

                var formatter = monthLabel.get('formatter');
                var name = nameMap[+firstDay.m - 1];
                var params = {
                    yyyy: firstDay.y,
                    yy: (firstDay.y + '').slice(2),
                    MM: firstDay.m,
                    M: +firstDay.m,
                    nameMap: name
                };

                var content = this._formatterLabel(formatter, params);

                var monthText = new graphic.Text({z2: 30});
                zrUtil.extend(
                    graphic.setTextStyle(monthText.style, monthLabel, {text: content}),
                    this._monthTextPositionControl(tmp, isCenter, orient, pos, margin)
                );

                group.add(monthText);
            }
        },

        _weekTextPositionControl: function (point, orient, position, margin, cellSize) {
            var align = 'center';
            var vAlign = 'middle';
            var x = point[0];
            var y = point[1];
            var isStart = position === 'start';

            if (orient === 'horizontal') {
                x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2;
                align = isStart ? 'right' : 'left';
            }
            else {
                y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2;
                vAlign = isStart ? 'bottom' : 'top';
            }

            return {
                x: x,
                y: y,
                textAlign: align,
                textVerticalAlign: vAlign
            };
        },

        // render weeks
        _renderWeekText: function (calendarModel, rangeData, orient, group) {
            var dayLabel = calendarModel.getModel('dayLabel');

            if (!dayLabel.get('show')) {
                return;
            }

            var coordSys = calendarModel.coordinateSystem;
            var pos = dayLabel.get('position');
            var nameMap = dayLabel.get('nameMap');
            var margin = dayLabel.get('margin');
            var firstDayOfWeek = coordSys.getFirstDayOfWeek();

            if (zrUtil.isString(nameMap)) {
                nameMap = WEEK_TEXT[nameMap.toUpperCase()] || [];
            }

            var start = coordSys.getNextNDay(
                rangeData.end.time, (7 - rangeData.lweek)
            ).time;

            var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()];
            margin = numberUtil.parsePercent(margin, cellSize[orient === 'horizontal' ? 0 : 1]);

            if (pos === 'start') {
                start = coordSys.getNextNDay(
                    rangeData.start.time, -(7 + rangeData.fweek)
                ).time;
                margin = -margin;
            }

            for (var i = 0; i < 7; i++) {

                var tmpD = coordSys.getNextNDay(start, i);
                var point = coordSys.dataToRect([tmpD.time], false).center;
                var day = i;
                day = Math.abs((i + firstDayOfWeek) % 7);
                var weekText = new graphic.Text({z2: 30});

                zrUtil.extend(
                    graphic.setTextStyle(weekText.style, dayLabel, {text: nameMap[day]}),
                    this._weekTextPositionControl(point, orient, pos, margin, cellSize)
                );
                group.add(weekText);
            }
        }
    });
});
<|endoftext|>


<commit_before>(function() {
  'use strict';

  var module = angular.module(
    'communityshare.controllers.user',
    [
      'communityshare.services.user',
      'communityshare.directives.user',
      'communityshare.directives.institutions',
      'angularFileUpload'
    ]);

  // User Views

  module.controller(
    'UserController',
    function($scope, $routeParams, User, Session, Question, Conversation,
             Evnt, startConversation) {
      $scope.Session = Session;
      var userId = $routeParams.userId;
      var userPromise = User.get(userId);
      $scope.message = 'Loading user...';
      $scope.startConversation = startConversation;
      userPromise.then(
        function(user) {
          $scope.message = '';
          $scope.user = user;
          if ($scope.communityPartnerViewMethods.onUserUpdate) {
            $scope.communityPartnerViewMethods.onUserUpdate(user);
          }
          if ($scope.educatorViewMethods.onUserUpdate) {
            $scope.educatorViewMethods.onUserUpdate(user);
          }
        },
        function(response) {
          $scope.message = 'Could not find user with id=' + userId;
        });
      $scope.communityPartnerViewMethods = {};
      $scope.educatorViewMethods = {};
      var question_types = [];
      var questionsPromise = Question.get_many_with_answers(
        userId,
        {'question_type.in': ['signup_community_partner', 'signup', 'signup_educator']}
      );
      if ($scope.Session.activeUser && $scope.Session.activeUser.is_administrator) {
        var conversationsPromise = Conversation.get_many({user_id: userId});
        conversationsPromise.then(
          function(conversations) {
            $scope.conversations = conversations;
          });
        var eventsPromise = Evnt.get_many({user_id: userId});
        eventsPromise.then(
          function(events) {
            $scope.events = events;
          });
      }
      questionsPromise.then(
        function(questions) {
          $scope.questions = [];
          for (var i=0; i<questions.length; i++) {
            var question = questions[i];
            if (question.answer.text) {
              $scope.questions.push(question);
            }
          }
        });
    });

  // User Signups

  var commonSignupLogic = function($scope, user, search, Messages, $location,
                                   $q, Question, Answer) {
    $scope.user = user;
    $scope.search = search;
    $scope.institutionMethods = {};

    // Get questions to display during signup.
    $scope.questions = [];
    var questionsPromise = Question.get_many({
      'question_type.in': ['signup_community_partner', 'signup', 'signup_educator']
    });
    questionsPromise.then(
      function(questions) {
        $scope.questions = questions;
        for (var i=0; i<$scope.questions.length; i++) {
          var question = $scope.questions[i];
          question.answer = new Answer({question_id: question.id});
        }
      });

    $scope.submit = function() {
      // Save changes made to user.
      var userPromise = user.save();
      var allPromises = [userPromise];
      // And save the answers to questions.
      for (var i=0; i<$scope.questions.length; i++) {
        var question = $scope.questions[i];
        if (question.answer.text) {
          allPromises.push(question.answer.save());
        }
      }
      $q.all(allPromises).then(
        function(data) {
          var search = data[0];
          $location.path('/signup/personal');
        },
        function(message) {
          Messages.error(message);
        });

      $scope.readyToSubmit = function() {
        var ready = false;
        if ($scope.institutionMethods.isValid && $scope.institutionMethods.isValid()) {
          ready = true;
        }
        return ready;
      };
    };
  };

  module.controller(
    'SignupCommunityPartnerController',
    function($scope, Session, Messages, $location, $q, Search,
             Question, Answer) {
      $scope.Session = Session;
      var user = Session.activeUser;
      var search;
      if (user) {
        search = user.community_partner_profile_search;
      }
      $scope.isCommunityPartner = true;
      // Signup logic common to Community Partners and Educators
      commonSignupLogic($scope, user, search, Messages, $location, $q,
                       Question, Answer);
    });

  module.controller(
    'SignupPersonalController',
    function($scope, Session, $fileUploader, $http, $location) {
      $scope.Session = Session;
      $scope.user = Session.activeUser;
      $scope.submit = function() {
        var userPromise = $scope.user.save();
        userPromise.then(
          function(user) {
            $location.path('matches');
          },
          function(errorMessage) {
            $scope.errorMessage = errorMessage;
          });
      };
      $scope.validImage = true;
      var uploader = $scope.uploader = $fileUploader.create({
        scope: $scope,
        url: '/api/user/'+$scope.user.id+'/picture',
        headers: $http.defaults.headers.common,
        filters: [
          function (item) {
            var is_image = (item.type.substring(0, 5) == 'image');
            $scope.validImage = is_image;
            uploader.queue.splice(0, uploader.queue.length);
            return is_image;
          }
        ]
      });

      // Make sure we only have one file in the uploader queue
      uploader.bind('afteraddingfile', function (event, item) {
        if (uploader.queue.length > 1) {
          uploader.queue.splice(0, uploader.queue.length-1);
        }
      });
    });

  module.controller(
    'SignupEducatorController',
    function($scope, Session, Messages, $location, $q, Search,
            Question, Answer) {
      $scope.Session = Session;
      var user = Session.activeUser;
      var search;
      if (user) {
        search = user.educator_profile_search;
      }
      $scope.isEducator = true;
      $scope.questions = [];
      // Signup logic common to Community Partners and Educators
      commonSignupLogic($scope, user, search, Messages, $location, $q,
                       Question, Answer);
    });

  // Settings Controller

  module.controller(
    'SettingsController',
    function($scope, $location, Session, Messages, $q,
             Question, Answer, $fileUploader, $http, makeDialog, Authenticator, $rootScope) {

      var turnOffLocationChangeHandler;

      var onLocationChange = function(event, newUrl, oldUrl) {
        if (($scope.personalSettingsForm && $scope.personalSettingsForm.$dirty) ||
            ($scope.accountSettingsForm && $scope.accountSettingsForm.$dirty) ||
            ($scope.user.community_partner_profile_search &&
             $scope.user.community_partner_profile_search.dirty) ||
            ($scope.user.educator_profile_search &&
             $scope.user.educator_profile_search.dirty))
            {
          var title = 'Changes not Saved';
          var msg = 'Do you really want to leave this page without saving your changes?';
          var btns = [{result:'yes', label: 'Yes'},
                      {result:'no', label: 'No', cssClass: 'btn-primary'}];
          var d = makeDialog(title, msg, btns);
          d.result.then(
            function(result) {
              if (result === 'yes') {
                turnOffLocationChangeHandler();
                var relUrl = newUrl.replace(/^.*\#/, "");
                $location.path(relUrl);
              }
            });
          event.preventDefault();
        }
      };

      turnOffLocationChangeHandler = $rootScope.$on('$locationChangeStart', onLocationChange);

      $scope.Session = Session;
      if (!Session.activeUser) {
        return;
      }
      $scope.user = Session.activeUser;
      $scope.isCommunityPartner = $scope.user.is_community_partner;
      $scope.isEducator = $scope.user.is_educator;
      $scope.properties = {};
      $scope.settingsTabSet = {};
      // passwordMethods hooks up the password matching directives.
      $scope.passwordMethods = {};
      // Get the questions
      if ($scope.user) {
        var questionsPromise = Question.get_many_with_answers(
          $scope.user.id,
          {'question_type.in': ['signup_community_partner', 'signup_educator']}
        );
        questionsPromise.then(
          function(questions) {
            $scope.questions = questions;
          });
      }

      $scope.$on('personalSettingsForm', function(event, value) {
        $scope.personalSettingsForm = value.personalSettingsForm;
      });
      $scope.$on('accountSettingsForm', function(event, value) {
        $scope.accountSettingsForm = value.accountSettingsForm;
      });

      var onError = function(message) {
        var msg = 'Failed to update settings';
        if (message) {
          msg += ': ' + message;
        }
        $scope.errorMessage = msg;
        $scope.successMessage = '';
      };

      $scope.validImage = true;
      var uploader = $scope.uploader = $fileUploader.create({
        scope: $scope,
        url: '/api/user/'+$scope.user.id+'/picture',
        headers: $http.defaults.headers.common,
        filters: [
          function (item) {
            var is_image = (item.type.substring(0, 5) == 'image');
            $scope.validImage = is_image;
            uploader.queue.splice(0, uploader.queue.length);
            return is_image;
          }
        ]
      });

      // Make sure we only have one file in the uploader queue
      uploader.bind('afteraddingfile', function (event, item) {
        if (uploader.queue.length > 1) {
          uploader.queue.splice(0, uploader.queue.length-1);
        }
      });

      $scope.deleteAccount = function() {
        var title = 'Delete Account';
          var msg = 'Do you really want to delete your Community Share account?';
        var btns = [{result:'yes', label: 'Yes'},
                    {result:'no', label: 'No', cssClass: 'btn-primary'}];
        var d = makeDialog(title, msg, btns);
        d.result.then(
          function(result) {
            if (result === 'yes') {
              var deletePromise = Session.activeUser.destroy();
              deletePromise.then(
                function() {
                  Authenticator.clean();
                  $location.path('/');
                },
                function(message) {
                    Messages.error(message);
                });
            }
          });
      };

      $scope.resendEmailConfirmation = function() {
        var emailConfirmPromise = Authenticator.requestConfirmEmail();
        emailConfirmPromise.then(
          function() {
            Messages.info('Sent email confirmation email.');
          },
          function(errorMessage) {
            Messages.error(errorMessage);
          });
      };

      $scope.save = function() {
        var saveUserPromise = $scope.user.save();
        var savedImages = uploader.uploadAll();
        var allPromises = [saveUserPromise];
        if ($scope.questions) {
          var saveAnswerPromises = [];
          for (var i=0; i<$scope.questions.length; i++) {
            var answer = $scope.questions[i].answer;
            if (answer.text) {
              var saveAnswerPromise = answer.save();
              saveAnswerPromises.push(saveAnswerPromise);
              allPromises.push(saveAnswerPromise);
            }
          }
        }
        var combinedPromise = $q.all(allPromises);
        saveUserPromise.then(
          function(user) {
            Session.activeUser.updateFromData(user.toData());
          },
          onError);
        combinedPromise.then(
          function() {
            $location.path('/');
          });
      };

    });

})();
<commit_msg>Don't pop up warning dialog when saving.<commit_after>(function() {
  'use strict';

  var module = angular.module(
    'communityshare.controllers.user',
    [
      'communityshare.services.user',
      'communityshare.directives.user',
      'communityshare.directives.institutions',
      'angularFileUpload'
    ]);

  // User Views

  module.controller(
    'UserController',
    function($scope, $routeParams, User, Session, Question, Conversation,
             Evnt, startConversation) {
      $scope.Session = Session;
      var userId = $routeParams.userId;
      var userPromise = User.get(userId);
      $scope.message = 'Loading user...';
      $scope.startConversation = startConversation;
      userPromise.then(
        function(user) {
          $scope.message = '';
          $scope.user = user;
          if ($scope.communityPartnerViewMethods.onUserUpdate) {
            $scope.communityPartnerViewMethods.onUserUpdate(user);
          }
          if ($scope.educatorViewMethods.onUserUpdate) {
            $scope.educatorViewMethods.onUserUpdate(user);
          }
        },
        function(response) {
          $scope.message = 'Could not find user with id=' + userId;
        });
      $scope.communityPartnerViewMethods = {};
      $scope.educatorViewMethods = {};
      var question_types = [];
      var questionsPromise = Question.get_many_with_answers(
        userId,
        {'question_type.in': ['signup_community_partner', 'signup', 'signup_educator']}
      );
      if ($scope.Session.activeUser && $scope.Session.activeUser.is_administrator) {
        var conversationsPromise = Conversation.get_many({user_id: userId});
        conversationsPromise.then(
          function(conversations) {
            $scope.conversations = conversations;
          });
        var eventsPromise = Evnt.get_many({user_id: userId});
        eventsPromise.then(
          function(events) {
            $scope.events = events;
          });
      }
      questionsPromise.then(
        function(questions) {
          $scope.questions = [];
          for (var i=0; i<questions.length; i++) {
            var question = questions[i];
            if (question.answer.text) {
              $scope.questions.push(question);
            }
          }
        });
    });

  // User Signups

  var commonSignupLogic = function($scope, user, search, Messages, $location,
                                   $q, Question, Answer) {
    $scope.user = user;
    $scope.search = search;
    $scope.institutionMethods = {};

    // Get questions to display during signup.
    $scope.questions = [];
    var questionsPromise = Question.get_many({
      'question_type.in': ['signup_community_partner', 'signup', 'signup_educator']
    });
    questionsPromise.then(
      function(questions) {
        $scope.questions = questions;
        for (var i=0; i<$scope.questions.length; i++) {
          var question = $scope.questions[i];
          question.answer = new Answer({question_id: question.id});
        }
      });

    $scope.submit = function() {
      // Save changes made to user.
      var userPromise = user.save();
      var allPromises = [userPromise];
      // And save the answers to questions.
      for (var i=0; i<$scope.questions.length; i++) {
        var question = $scope.questions[i];
        if (question.answer.text) {
          allPromises.push(question.answer.save());
        }
      }
      $q.all(allPromises).then(
        function(data) {
          var search = data[0];
          $location.path('/signup/personal');
        },
        function(message) {
          Messages.error(message);
        });

      $scope.readyToSubmit = function() {
        var ready = false;
        if ($scope.institutionMethods.isValid && $scope.institutionMethods.isValid()) {
          ready = true;
        }
        return ready;
      };
    };
  };

  module.controller(
    'SignupCommunityPartnerController',
    function($scope, Session, Messages, $location, $q, Search,
             Question, Answer) {
      $scope.Session = Session;
      var user = Session.activeUser;
      var search;
      if (user) {
        search = user.community_partner_profile_search;
      }
      $scope.isCommunityPartner = true;
      // Signup logic common to Community Partners and Educators
      commonSignupLogic($scope, user, search, Messages, $location, $q,
                       Question, Answer);
    });

  module.controller(
    'SignupPersonalController',
    function($scope, Session, $fileUploader, $http, $location) {
      $scope.Session = Session;
      $scope.user = Session.activeUser;
      $scope.submit = function() {
        var userPromise = $scope.user.save();
        userPromise.then(
          function(user) {
            $location.path('matches');
          },
          function(errorMessage) {
            $scope.errorMessage = errorMessage;
          });
      };
      $scope.validImage = true;
      var uploader = $scope.uploader = $fileUploader.create({
        scope: $scope,
        url: '/api/user/'+$scope.user.id+'/picture',
        headers: $http.defaults.headers.common,
        filters: [
          function (item) {
            var is_image = (item.type.substring(0, 5) == 'image');
            $scope.validImage = is_image;
            uploader.queue.splice(0, uploader.queue.length);
            return is_image;
          }
        ]
      });

      // Make sure we only have one file in the uploader queue
      uploader.bind('afteraddingfile', function (event, item) {
        if (uploader.queue.length > 1) {
          uploader.queue.splice(0, uploader.queue.length-1);
        }
      });
    });

  module.controller(
    'SignupEducatorController',
    function($scope, Session, Messages, $location, $q, Search,
            Question, Answer) {
      $scope.Session = Session;
      var user = Session.activeUser;
      var search;
      if (user) {
        search = user.educator_profile_search;
      }
      $scope.isEducator = true;
      $scope.questions = [];
      // Signup logic common to Community Partners and Educators
      commonSignupLogic($scope, user, search, Messages, $location, $q,
                       Question, Answer);
    });

  // Settings Controller

  module.controller(
    'SettingsController',
    function($scope, $location, Session, Messages, $q,
             Question, Answer, $fileUploader, $http, makeDialog, Authenticator, $rootScope) {

      var justSaved = false;

      var turnOffLocationChangeHandler;

      var onLocationChange = function(event, newUrl, oldUrl) {
        if (!justSaved && (($scope.personalSettingsForm && $scope.personalSettingsForm.$dirty) ||
            ($scope.accountSettingsForm && $scope.accountSettingsForm.$dirty) ||
            ($scope.user.community_partner_profile_search &&
             $scope.user.community_partner_profile_search.dirty) ||
            ($scope.user.educator_profile_search &&
             $scope.user.educator_profile_search.dirty)))
        {
          var title = 'Changes not Saved';
          var msg = 'Do you really want to leave this page without saving your changes?';
          var btns = [{result:'yes', label: 'Yes'},
                      {result:'no', label: 'No', cssClass: 'btn-primary'}];
          var d = makeDialog(title, msg, btns);
          d.result.then(
            function(result) {
              if (result === 'yes') {
                turnOffLocationChangeHandler();
                var relUrl = newUrl.replace(/^.*\#/, "");
                $location.path(relUrl);
              }
            });
          event.preventDefault();
        }
      };

      turnOffLocationChangeHandler = $rootScope.$on('$locationChangeStart', onLocationChange);

      $scope.Session = Session;
      if (!Session.activeUser) {
        return;
      }
      $scope.user = Session.activeUser;
      $scope.isCommunityPartner = $scope.user.is_community_partner;
      $scope.isEducator = $scope.user.is_educator;
      $scope.properties = {};
      $scope.settingsTabSet = {};
      // passwordMethods hooks up the password matching directives.
      $scope.passwordMethods = {};
      // Get the questions
      if ($scope.user) {
        var questionsPromise = Question.get_many_with_answers(
          $scope.user.id,
          {'question_type.in': ['signup_community_partner', 'signup_educator']}
        );
        questionsPromise.then(
          function(questions) {
            $scope.questions = questions;
          });
      }

      $scope.$on('personalSettingsForm', function(event, value) {
        $scope.personalSettingsForm = value.personalSettingsForm;
      });
      $scope.$on('accountSettingsForm', function(event, value) {
        $scope.accountSettingsForm = value.accountSettingsForm;
      });

      var onError = function(message) {
        var msg = 'Failed to update settings';
        if (message) {
          msg += ': ' + message;
        }
        $scope.errorMessage = msg;
        $scope.successMessage = '';
      };

      $scope.validImage = true;
      var uploader = $scope.uploader = $fileUploader.create({
        scope: $scope,
        url: '/api/user/'+$scope.user.id+'/picture',
        headers: $http.defaults.headers.common,
        filters: [
          function (item) {
            var is_image = (item.type.substring(0, 5) == 'image');
            $scope.validImage = is_image;
            uploader.queue.splice(0, uploader.queue.length);
            return is_image;
          }
        ]
      });

      // Make sure we only have one file in the uploader queue
      uploader.bind('afteraddingfile', function (event, item) {
        if (uploader.queue.length > 1) {
          uploader.queue.splice(0, uploader.queue.length-1);
        }
      });

      $scope.deleteAccount = function() {
        var title = 'Delete Account';
          var msg = 'Do you really want to delete your Community Share account?';
        var btns = [{result:'yes', label: 'Yes'},
                    {result:'no', label: 'No', cssClass: 'btn-primary'}];
        var d = makeDialog(title, msg, btns);
        d.result.then(
          function(result) {
            if (result === 'yes') {
              var deletePromise = Session.activeUser.destroy();
              deletePromise.then(
                function() {
                  Authenticator.clean();
                  $location.path('/');
                },
                function(message) {
                    Messages.error(message);
                });
            }
          });
      };

      $scope.resendEmailConfirmation = function() {
        var emailConfirmPromise = Authenticator.requestConfirmEmail();
        emailConfirmPromise.then(
          function() {
            Messages.info('Sent email confirmation email.');
          },
          function(errorMessage) {
            Messages.error(errorMessage);
          });
      };

      $scope.save = function() {
        var saveUserPromise = $scope.user.save();
        var savedImages = uploader.uploadAll();
        var allPromises = [saveUserPromise];
        if ($scope.questions) {
          var saveAnswerPromises = [];
          for (var i=0; i<$scope.questions.length; i++) {
            var answer = $scope.questions[i].answer;
            if (answer.text) {
              var saveAnswerPromise = answer.save();
              saveAnswerPromises.push(saveAnswerPromise);
              allPromises.push(saveAnswerPromise);
            }
          }
        }
        var combinedPromise = $q.all(allPromises);
        saveUserPromise.then(
          function(user) {
            Session.activeUser.updateFromData(user.toData());
          },
          onError);
        combinedPromise.then(
          function() {
            justSaved = true;
            $location.path('/');
          });
      };

    });

})();
<|endoftext|>


<commit_before>import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import Button from './Button';
import Result from './Result';
import { connect } from 'react-redux';

class Content extends React.Component {
  render() {
    const { onButtonPress, onResultPress, destination } = this.props
    return (
      <View style={styles.contentContainerStyle}>
        <Button
          onPress={onButtonPress}
          style={styles.buttonStyle}>
            Where should we eat?
        </Button>
        <Result
          destination={destination}
          onResultPress={onResultPress} />
      </View>
    )
  }
};

const styles = StyleSheet.create({
  contentContainerStyle: {
    marginTop: 10,
    marginLeft: 5,
    marginRight: 5,
    flex: 2
  }
});

export default Content
<commit_msg>Conditionally shows the results component.<commit_after>import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import Button from './Button';
import Result from './Result';
import { connect } from 'react-redux';

class Content extends React.Component {
  render() {
    const { onButtonPress, onResultPress, destination } = this.props
    return (
      <View style={styles.contentContainerStyle}>
        <Button
          onPress={onButtonPress}
          style={styles.buttonStyle}>
            Where should we eat?
        </Button>
        {
          destination ?
          <Result
            destination={destination}
            onResultPress={onResultPress} /> : null
        }
      </View>
    )
  }
};

const styles = StyleSheet.create({
  contentContainerStyle: {
    marginTop: 10,
    marginLeft: 5,
    marginRight: 5,
    flex: 2
  }
});

export default Content
<|endoftext|>


<commit_before>var convert = document.getElementById("convert");
var fileInput = document.getElementById("fileInput");
var reverseTypeface = document.getElementById("reverseTypeface");
convert.onclick = function(){

    [].forEach.call(fileInput.files,function(file){
        var reader = new FileReader();
        reader.addEventListener( 'load', function ( event ) {
            var font = opentype.parse(event.target.result);
            var result = convert(font);
            exportString(result,font.familyName + "_" + font.styleName  + ".js");
        }, false );
        reader.readAsArrayBuffer( file );
    });
};

var exportString = function ( output, filename ) {

		var blob = new Blob( [ output ], { type: 'text/plain' } );
		var objectURL = URL.createObjectURL( blob );

		var link = document.createElement( 'a' );
		link.href = objectURL;
		link.download = filename || 'data.json';
		link.target = '_blank';
		link.click();

	};

var convert =function(font){

    console.log(font);

    var scale = (1000 * 100) / ( (font.unitsPerEm || 2048) *72);
    var result = {};
    result.glyphs = {};

    font.glyphs.forEach(function(glyph){
        if (glyph.unicode !== undefined) {

            var token = {};
            token.ha = Math.round(glyph.advanceWidth * scale);
            token.x_min = Math.round(glyph.xMin * scale);
            token.x_max = Math.round(glyph.xMax * scale);
            token.o = ""
            if (reverseTypeface.checked) {glyph.path.commands = reverseCommands(glyph.path.commands);}
            glyph.path.commands.forEach(function(command,i){
                if (command.type.toLowerCase() === "c") {command.type = "b";}
                token.o += command.type.toLowerCase();
                token.o += " "
                if (command.x !== undefined && command.y !== undefined){
                    token.o += Math.round(command.x * scale);
                    token.o += " "
                    token.o += Math.round(command.y * scale);
                    token.o += " "
                }
                if (command.x1 !== undefined && command.y1 !== undefined){
                    token.o += Math.round(command.x1 * scale);
                    token.o += " "
                    token.o += Math.round(command.y1 * scale);
                    token.o += " "
                }
                if (command.x2 !== undefined && command.y2 !== undefined){
                    token.o += Math.round(command.x2 * scale);
                    token.o += " "
                    token.o += Math.round(command.y2 * scale);
                    token.o += " "
                }
            });
            result.glyphs[String.fromCharCode(glyph.unicode)] = token;
        };
    });
    result.familyName = font.familyName;
    result.ascender = Math.round(font.ascender * scale);
    result.descender = Math.round(font.descender * scale);
    result.underlinePosition = font.tables.post.underlinePosition;
    result.underlineThickness = font.tables.post.underlineThickness;
    result.boundingBox = {
        "yMin": font.tables.head.yMin,
        "xMin": font.tables.head.xMin,
        "yMax": font.tables.head.yMax,
        "xMax": font.tables.head.xMax
    };
    result.resolution = 1000;
    result.original_font_information = font.tables.name;
    if (font.styleName.toLowerCase().indexOf("bold") > -1){
        result.cssFontWeight = "bold";
    } else {
        result.cssFontWeight = "normal";
    };

    if (font.styleName.toLowerCase().indexOf("italic") > -1){
        result.cssFontStyle = "italic";
    } else {
        result.cssFontStyle = "normal";
    };
    return "if (_typeface_js && _typeface_js.loadFace) _typeface_js.loadFace("+ JSON.stringify(result) + ");"
};

var reverseCommands = function(commands){

    var paths = [];
    var path;

    commands.forEach(function(c){
        if (c.type.toLowerCase() === "m"){
            path = [c];
            paths.push(path);
        } else if (c.type.toLowerCase() !== "z") {
            path.push(c);
        }
    });

    var reversed = [];
    paths.forEach(function(p){
        var result = {"type":"m" , "x" : p[p.length-1].x, "y": p[p.length-1].y};
        reversed.push(result);

        for(var i = p.length - 1;i > 0; i-- ){
            var command = p[i];
            result = {"type":command.type};
            if (command.x2 !== undefined && command.y2 !== undefined){
                result.x1 = command.x2;
                result.y1 = command.y2;
                result.x2 = command.x1;
                result.y2 = command.y1;
            } else if (command.x1 !== undefined && command.y1 !== undefined){
                result.x1 = command.x1;
                result.y1 = command.y1;
            }
            result.x =  p[i-1].x;
            result.y =  p[i-1].y;
            reversed.push(result);
        }

    });

    return reversed;

};<commit_msg>make this also work in firefox<commit_after>var convert = document.getElementById("convert");
var fileInput = document.getElementById("fileInput");
var reverseTypeface = document.getElementById("reverseTypeface");
convert.onclick = function(){

    [].forEach.call(fileInput.files,function(file){
        var reader = new FileReader();
        reader.addEventListener( 'load', function ( event ) {
            var font = opentype.parse(event.target.result);
            var result = convert(font);
            exportString(result,font.familyName + "_" + font.styleName  + ".js");
        }, false );
        reader.readAsArrayBuffer( file );
    });
};

var exportString = function ( output, filename ) {

		var blob = new Blob( [ output ], { type: 'text/plain' } );
		var objectURL = URL.createObjectURL( blob );

		var link = document.createElement( 'a' );
		link.href = objectURL;
		link.download = filename || 'data.json';
		link.target = '_blank';
		//link.click();

		var event = document.createEvent("MouseEvents");
			event.initMouseEvent(
				"click", true, false, window, 0, 0, 0, 0, 0
				, false, false, false, false, 0, null
			);
			link.dispatchEvent(event);

	};

var convert = function(font){

    console.log(font);

    var scale = (1000 * 100) / ( (font.unitsPerEm || 2048) *72);
    var result = {};
    result.glyphs = {};

    font.glyphs.forEach(function(glyph){
        if (glyph.unicode !== undefined) {

            var token = {};
            token.ha = Math.round(glyph.advanceWidth * scale);
            token.x_min = Math.round(glyph.xMin * scale);
            token.x_max = Math.round(glyph.xMax * scale);
            token.o = ""
            if (reverseTypeface.checked) {glyph.path.commands = reverseCommands(glyph.path.commands);}
            glyph.path.commands.forEach(function(command,i){
                if (command.type.toLowerCase() === "c") {command.type = "b";}
                token.o += command.type.toLowerCase();
                token.o += " "
                if (command.x !== undefined && command.y !== undefined){
                    token.o += Math.round(command.x * scale);
                    token.o += " "
                    token.o += Math.round(command.y * scale);
                    token.o += " "
                }
                if (command.x1 !== undefined && command.y1 !== undefined){
                    token.o += Math.round(command.x1 * scale);
                    token.o += " "
                    token.o += Math.round(command.y1 * scale);
                    token.o += " "
                }
                if (command.x2 !== undefined && command.y2 !== undefined){
                    token.o += Math.round(command.x2 * scale);
                    token.o += " "
                    token.o += Math.round(command.y2 * scale);
                    token.o += " "
                }
            });
            result.glyphs[String.fromCharCode(glyph.unicode)] = token;
        };
    });
    result.familyName = font.familyName;
    result.ascender = Math.round(font.ascender * scale);
    result.descender = Math.round(font.descender * scale);
    result.underlinePosition = font.tables.post.underlinePosition;
    result.underlineThickness = font.tables.post.underlineThickness;
    result.boundingBox = {
        "yMin": font.tables.head.yMin,
        "xMin": font.tables.head.xMin,
        "yMax": font.tables.head.yMax,
        "xMax": font.tables.head.xMax
    };
    result.resolution = 1000;
    result.original_font_information = font.tables.name;
    if (font.styleName.toLowerCase().indexOf("bold") > -1){
        result.cssFontWeight = "bold";
    } else {
        result.cssFontWeight = "normal";
    };

    if (font.styleName.toLowerCase().indexOf("italic") > -1){
        result.cssFontStyle = "italic";
    } else {
        result.cssFontStyle = "normal";
    };
    return "if (_typeface_js && _typeface_js.loadFace) _typeface_js.loadFace("+ JSON.stringify(result) + ");"
};

var reverseCommands = function(commands){

    var paths = [];
    var path;

    commands.forEach(function(c){
        if (c.type.toLowerCase() === "m"){
            path = [c];
            paths.push(path);
        } else if (c.type.toLowerCase() !== "z") {
            path.push(c);
        }
    });

    var reversed = [];
    paths.forEach(function(p){
        var result = {"type":"m" , "x" : p[p.length-1].x, "y": p[p.length-1].y};
        reversed.push(result);

        for(var i = p.length - 1;i > 0; i-- ){
            var command = p[i];
            result = {"type":command.type};
            if (command.x2 !== undefined && command.y2 !== undefined){
                result.x1 = command.x2;
                result.y1 = command.y2;
                result.x2 = command.x1;
                result.y2 = command.y1;
            } else if (command.x1 !== undefined && command.y1 !== undefined){
                result.x1 = command.x1;
                result.y1 = command.y1;
            }
            result.x =  p[i-1].x;
            result.y =  p[i-1].y;
            reversed.push(result);
        }

    });

    return reversed;

};<|endoftext|>


<commit_before>"use strict";

var P = require('bluebird');
var uuid = require('cassandra-uuid').TimeUuid;
var mwUtil = require('../lib/mwUtil');
var HTTPError = require('../lib/exports').HTTPError;
var URI = require('swagger-router').URI;
var preq = require('preq');

var yaml = require('js-yaml');
var fs = require('fs');
var spec = yaml.safeLoad(fs.readFileSync(__dirname + '/key_rev_value.yaml'));

/**
 * The chunk size to use for data slicing
 * @type {number}
 * @const
 */
var CHUNK_SIZE = 31000;

/**
 * The grace_ttl parameter for a revision policy
 * @type {number}
 * @const
 */
var GRACE_TTL = 86400;

function range(N) {
    return Array.apply(null, { length: N }).map(Number.call, Number);
}

function ChunkedBucket(options) {
    this.log = options.log || function() {};
}

ChunkedBucket.prototype._sliceData = function(data) {
    var slicer;
    if (Buffer.isBuffer(data)) {
        slicer = Buffer.prototype.slice;
    } else {
        data = data.toString();
        slicer = String.prototype.substring;
    }
    var result = [];
    for (var index = 0; index < data.length; index += CHUNK_SIZE) {
        result.push(slicer.call(data, index, index + CHUNK_SIZE));
    }
    return result;
};

ChunkedBucket.prototype._joinData = function(dataParts) {
    if (!dataParts || !dataParts.length) {
        return '';
    } else if (Buffer.isBuffer(dataParts[0])) {
        return Buffer.concat(dataParts);
    } else {
        return ''.concat(dataParts);
    }
};

ChunkedBucket.prototype._metaTableName = function(req) {
    return req.params.bucket + '_meta';
};

ChunkedBucket.prototype._chunksTableName = function(req) {
    return req.params.bucket + '_chunks';
};

ChunkedBucket.prototype._makeMetaSchema = function(opts) {
    var schemaVersionMajor = 1;

    return {
        version: schemaVersionMajor * 1000 + (opts.version || 0),
        options: {
            compression: opts.compression || [
                {
                    algorithm: 'deflate',
                    block_size: 128
                }
            ]
        },
        attributes: {
            key: opts.keyType || 'string',
            rev: 'int',
            tid: 'timeuuid',
            num: 'int',
            headers: 'json'
        },
        index: [
            { attribute: 'key', type: 'hash' },
            { attribute: 'rev', type: 'range', order: 'desc' },
            { attribute: 'tid', type: 'range', order: 'desc' }
        ]
    };
};

ChunkedBucket.prototype._makeChunksSchema = function(opts) {
    var schemaVersionMajor = 1;

    return {
        version: schemaVersionMajor * 1000 + (opts.version || 0),
        options: {
            compression: opts.compression || [
                {
                    algorithm: 'deflate',
                    block_size: 1024
                }
            ]
        },
        attributes: {
            key: opts.keyType || 'string',
            chunk_id: 'int',
            tid: 'timeuuid',
            value: opts.valueType || 'blob'
        },
        index: [
            { attribute: 'key', type: 'hash' },
            { attribute: 'chunk_id', type: 'hash' },
            { attribute: 'tid', type: 'range', order: 'desc' }
        ]
    };
};

ChunkedBucket.prototype.createBucket = function(restbase, req) {
    var metaSchema = this._makeMetaSchema(req.body || {});
    var dataSchema = this._makeChunksSchema(req.body || {});
    metaSchema.table = this._metaTableName(req);
    dataSchema.table = this._chunksTableName(req);
    return P.join(
        restbase.put({
            uri: new URI([req.params.domain, 'sys', 'table', metaSchema.table]),
            body: metaSchema
        }),
        restbase.put({
            uri: new URI([req.params.domain, 'sys', 'table', dataSchema.table]),
            body: dataSchema
        }))
    .then(function() { return { status: 201 }; });
};

// Format a revision response. Shared between different ways to retrieve a
// revision (latest & with explicit revision).
function returnRevision(req, metadata) {
    return function(dbResult) {
        if (dbResult.body && dbResult.body.items && dbResult.body.items.length) {
            var row = dbResult.body.items[0];
            return {
                status: 200,
                headers: metadata.headers,
                body: row.value
            };
        } else {
            throw new HTTPError({
                status: 404,
                body: {
                    type: 'not_found',
                    uri: req.uri,
                    method: req.method
                }
            });
        }
    };
}

function coerceTid(tidString) {
    if (uuid.test(tidString)) {
        return tidString;
    }

    // Out of luck
    throw new HTTPError({
        status: 400,
        body: {
            type: 'key_rev_value/invalid_tid',
            title: 'Invalid tid parameter',
            tid: tidString
        }
    });
}

function parseRevision(rev) {
    if (!/^[0-9]+/.test(rev)) {
        throw new HTTPError({
            status: 400,
            body: {
                type: 'key_rev_value/invalid_revision',
                title: 'Invalid revision parameter',
                rev: rev
            }
        });
    }

    return parseInt(rev);
}

ChunkedBucket.prototype._getMetadata = function(restbase, req) {
    var rp = req.params;
    var metadataReq = {
        uri: new URI([rp.domain, 'sys', 'table', this._metaTableName(req), '']),
        body: {
            table: this._metaTableName(req),
            attributes: {
                key: rp.key
            },
            limit: 1
        }
    };
    if (rp.revision) {
        metadataReq.body.attributes.rev = parseRevision(rp.revision);
        if (rp.tid) {
            metadataReq.body.attributes.tid = coerceTid(rp.tid);
        }
    }
    return restbase.get(metadataReq)
    .then(function(metadataRes) {
        return metadataRes.body.items[0];
    });
};

ChunkedBucket.prototype.getRevision = function(restbase, req) {
    var rp = req.params;
    var self = this;
    return this._getMetadata(restbase, req)
    .then(function(metadata) {
        return P.all(range(metadata.num).map(function(chunkId) {
            return restbase.get({
                uri: new URI([rp.domain, 'sys', 'table', self._chunksTableName(req), '']),
                body: {
                    table: self._chunksTableName(req),
                    attributes: {
                        key: rp.key,
                        chunk_id: chunkId,
                        tid: {
                            le: metadata.tid
                        }
                    },
                    limit: 1
                }
            });
        }))
        .map(function(res) { return res.body.items[0].value; })
        .then(function(sections) {
            metadata.value = self._joinData(sections);
            return {
                status: 200,
                body: {
                    items: [ metadata ]
                }
            };
        })
        .then(returnRevision(req, metadata));
    });
};

function getLimit(restbase, req) {
    if (req.body && req.body.limit) {
        return req.body.limit;
    } else if (req.query && req.query.limit) {
        return req.query.limit;
    }
    return restbase.rb_config.default_page_size;
}

ChunkedBucket.prototype.listRevisions = function(restbase, req) {
    var rp = req.params;
    return restbase.get({
        uri: new URI([rp.domain, 'sys', 'table', this._metaTableName(req), '']),
        body: {
            table: this._metaTableName(req),
            attributes: {
                key: req.params.key
            },
            proj: ['rev', 'tid'],
            limit: getLimit(restbase, req)
        }
    })
    .then(function(res) {
        return {
            status: 200,
            headers: {
                'content-type': 'application/json'
            },
            body: {
                items: res.body.items.map(function(row) {
                    return { revision: row.rev, tid: row.tid };
                }),
                next: res.body.next
            }
        };
    });
};

ChunkedBucket.prototype._retentionPolicyUpdate = function(restbase, req, key, rev, tid) {
    var self = this;
    return restbase.get({
        uri: new URI([req.params.domain, 'sys', 'table', self._metaTableName(req), '']),
        body: {
            table: self._metaTableName(req),
            attributes: {
                key: key,
                rev: rev,
                tid: { lt: tid }
            },
            limit: 4,
            _withTTL: true
        }
    })
    .catch({ status: 404 }, function() {
        // Nothing to update, ignore
    })
    .then(function(res) {
        var rows = res && res.body && res.body.items;
        if (rows && rows.length) {
            var toRemove = rows.filter(function(row) { return !row._ttl; });
            return P.each(toRemove, function(row) {
                return restbase.put({
                    uri: new URI([req.params.domain, 'sys', 'table', self._metaTableName(req), '']),
                    body: {
                        table: self._metaTableName(req),
                        attributes: Object.assign({}, row, { _ttl: GRACE_TTL })
                    }
                })
                .then(function() {
                    return P.all(range(row.num).map(function(chunkId) {
                        return restbase.get({
                            uri: new URI([req.params.domain, 'sys', 'table',
                                self._chunksTableName(req), '']),
                            body: {
                                table: self._chunksTableName(req),
                                attributes: {
                                    key: key,
                                    chunk_id: chunkId,
                                    tid: row.tid
                                }
                            }
                        })
                        .then(function(res) {
                            var value = res.body.items[0];
                            return restbase.put({
                                uri: new URI([req.params.domain, 'sys', 'table',
                                    self._chunksTableName(req), '']),
                                body: {
                                    table: self._chunksTableName(req),
                                    attributes: Object.assign(value, { _ttl: GRACE_TTL })
                                }
                            });
                        });
                    }));
                });
            });
        }
    });
};

ChunkedBucket.prototype.putRevision = function(restbase, req) {
    var rp = req.params;
    var self = this;
    var rev = parseRevision(rp.revision);
    var tid = rp.tid && coerceTid(rp.tid) || uuid.now().toString();
    if (req.headers['last-modified']) {
        // XXX: require elevated rights for passing in the revision time
        tid = mwUtil.tidFromDate(req.headers['last-modified']);
    }

    var chunks = this._sliceData(req.body);
    return P.all(chunks.map(function(chunk, index) {
        return restbase.put({
            uri: new URI([rp.domain, 'sys', 'table', self._chunksTableName(req), '']),
            body: {
                table: self._chunksTableName(req),
                attributes: {
                    key: rp.key,
                    chunk_id: index,
                    tid: tid,
                    value: chunk
                }
            }
        });
    }))
    .then(function() {
        var headers = Object.assign({}, req.headers);
        headers.etag = headers.etag || mwUtil.makeETag(rev, tid);
        return restbase.put({
            uri: new URI([rp.domain, 'sys', 'table', self._metaTableName(req), '']),
            body: {
                table: self._metaTableName(req),
                attributes: {
                    key: rp.key,
                    rev: rev,
                    tid: tid,
                    num: chunks.length,
                    headers: headers
                }
            }
        });
    })
    .then(function(res) {
        if (res.status === 201) {
            // Do the retention policy update
            return self._retentionPolicyUpdate(restbase, req, rp.key, rev, tid)
            .thenReturn({
                status: 201,
                headers: {
                    etag: mwUtil.makeETag(rp.revision, tid)
                },
                body: {
                    message: "Created.",
                    tid: rp.revision
                }
            });
        } else {
            throw res;
        }
    })
    .catch(function(error) {
        restbase.log('error/krlv/putRevision', error);
        return { status: 400 };
    });
};

module.exports = function(options) {
    var chunkedBucket = new ChunkedBucket(options);

    return {
        spec: spec, // Re-export from spec module
        operations: {
            createBucket: chunkedBucket.createBucket.bind(chunkedBucket),
            listRevisions: chunkedBucket.listRevisions.bind(chunkedBucket),
            getRevision: chunkedBucket.getRevision.bind(chunkedBucket),
            putRevision: chunkedBucket.putRevision.bind(chunkedBucket)
        }
    };
};
<commit_msg>Rebased and addressed comments<commit_after>"use strict";

var P = require('bluebird');
var uuid = require('cassandra-uuid').TimeUuid;
var mwUtil = require('../lib/mwUtil');
var HTTPError = require('../lib/exports').HTTPError;
var URI = require('swagger-router').URI;
var preq = require('preq');

var yaml = require('js-yaml');
var fs = require('fs');
var spec = yaml.safeLoad(fs.readFileSync(__dirname + '/key_rev_value.yaml'));

/**
 * The chunk size to use for data slicing
 * @type {number}
 * @const
 */
var CHUNK_SIZE = 31000;

/**
 * The grace_ttl parameter for a revision policy
 * @type {number}
 * @const
 */
var GRACE_TTL = 86400;

function range(N) {
    return Array.apply(null, { length: N }).map(Number.call, Number);
}

function ChunkedBucket(options) {
    this.log = options.log || function() {};
}

ChunkedBucket.prototype._sliceData = function(data) {
    var slicer;
    if (Buffer.isBuffer(data)) {
        slicer = Buffer.prototype.slice;
    } else {
        data = data.toString();
        slicer = String.prototype.substring;
    }
    var result = [];
    for (var index = 0; index < data.length; index += CHUNK_SIZE) {
        result.push(slicer.call(data, index, index + CHUNK_SIZE));
    }
    return result;
};

ChunkedBucket.prototype._joinData = function(dataParts) {
    if (!dataParts || !dataParts.length) {
        return '';
    } else if (Buffer.isBuffer(dataParts[0])) {
        return Buffer.concat(dataParts);
    } else {
        return dataParts.join('');
    }
};

ChunkedBucket.prototype._metaTableName = function(req) {
    return req.params.bucket + '_meta';
};

ChunkedBucket.prototype._chunksTableName = function(req) {
    return req.params.bucket + '_chunks';
};

ChunkedBucket.prototype._makeMetaSchema = function(opts) {
    var schemaVersionMajor = 1;

    return {
        version: schemaVersionMajor * 1000 + (opts.version || 0),
        options: {
            compression: opts.compression || [
                {
                    algorithm: 'deflate',
                    block_size: 128
                }
            ]
        },
        attributes: {
            key: opts.keyType || 'string',
            rev: 'int',
            tid: 'timeuuid',
            num_chunks: 'int',
            headers: 'json'
        },
        index: [
            { attribute: 'key', type: 'hash' },
            { attribute: 'rev', type: 'range', order: 'desc' },
            { attribute: 'tid', type: 'range', order: 'desc' }
        ]
    };
};

ChunkedBucket.prototype._makeChunksSchema = function(opts) {
    var schemaVersionMajor = 1;

    return {
        version: schemaVersionMajor * 1000 + (opts.version || 0),
        options: {
            compression: opts.compression || [
                {
                    algorithm: 'deflate',
                    block_size: 1024
                }
            ]
        },
        attributes: {
            key: opts.keyType || 'string',
            chunk_id: 'int',
            tid: 'timeuuid',
            value: opts.valueType || 'blob'
        },
        index: [
            { attribute: 'key', type: 'hash' },
            { attribute: 'chunk_id', type: 'hash' },
            { attribute: 'tid', type: 'range', order: 'desc' }
        ]
    };
};

ChunkedBucket.prototype._validateSchemaOptions = function(req) {
    var options = req.body || {};

    if (options.retention_policy) {
        throw new Error('key_rev_large_value does not support revision_policy option');
    }

    if (options.compression) {
        throw new Error('key_rev_large_value does not support compression option');
    }
};

ChunkedBucket.prototype.createBucket = function(hyper, req) {
    this._validateSchemaOptions(req);
    var metaSchema = this._makeMetaSchema(req.body || {});
    var dataSchema = this._makeChunksSchema(req.body || {});
    metaSchema.table = this._metaTableName(req);
    dataSchema.table = this._chunksTableName(req);
    return P.join(
        hyper.put({
            uri: new URI([req.params.domain, 'sys', 'table', metaSchema.table]),
            body: metaSchema
        }),
        hyper.put({
            uri: new URI([req.params.domain, 'sys', 'table', dataSchema.table]),
            body: dataSchema
        }))
    .then(function() { return { status: 201 }; });
};

// Format a revision response. Shared between different ways to retrieve a
// revision (latest & with explicit revision).
function returnRevision(req, metadata) {
    return function(dbResult) {
        if (dbResult.body && dbResult.body.items && dbResult.body.items.length) {
            var row = dbResult.body.items[0];
            return {
                status: 200,
                headers: metadata.headers,
                body: row.value
            };
        } else {
            throw new HTTPError({
                status: 404,
                body: {
                    type: 'not_found',
                    uri: req.uri,
                    method: req.method
                }
            });
        }
    };
}

function coerceTid(tidString) {
    if (uuid.test(tidString)) {
        return tidString;
    }

    // Out of luck
    throw new HTTPError({
        status: 400,
        body: {
            type: 'key_rev_value/invalid_tid',
            title: 'Invalid tid parameter',
            tid: tidString
        }
    });
}

function parseRevision(rev) {
    if (!/^[0-9]+/.test(rev)) {
        throw new HTTPError({
            status: 400,
            body: {
                type: 'key_rev_value/invalid_revision',
                title: 'Invalid revision parameter',
                rev: rev
            }
        });
    }

    return parseInt(rev);
}

ChunkedBucket.prototype._getMetadata = function(hyper, req) {
    var rp = req.params;
    var metadataReq = {
        uri: new URI([rp.domain, 'sys', 'table', this._metaTableName(req), '']),
        body: {
            table: this._metaTableName(req),
            attributes: {
                key: rp.key
            },
            limit: 1
        }
    };
    if (rp.revision) {
        metadataReq.body.attributes.rev = parseRevision(rp.revision);
        if (rp.tid) {
            metadataReq.body.attributes.tid = coerceTid(rp.tid);
        }
    }
    return hyper.get(metadataReq)
    .then(function(metadataRes) {
        return metadataRes.body.items[0];
    });
};

ChunkedBucket.prototype.getRevision = function(hyper, req) {
    var rp = req.params;
    var self = this;
    return this._getMetadata(hyper, req)
    .then(function(metadata) {
        return P.all(range(metadata.num_chunks).map(function(chunkId) {
            return hyper.get({
                uri: new URI([rp.domain, 'sys', 'table', self._chunksTableName(req), '']),
                body: {
                    table: self._chunksTableName(req),
                    attributes: {
                        key: rp.key,
                        chunk_id: chunkId,
                        tid: metadata.tid
                    },
                    limit: 1
                }
            });
        }))
        .map(function(res) { return res.body.items[0].value; })
        .then(function(sections) {
            metadata.value = self._joinData(sections);
            return {
                status: 200,
                body: {
                    items: [ metadata ]
                }
            };
        })
        .then(returnRevision(req, metadata));
    });
};

function getLimit(hyper, req) {
    if (req.body && req.body.limit) {
        return req.body.limit;
    } else if (req.query && req.query.limit) {
        return req.query.limit;
    }
    return hyper.rb_config.default_page_size;
}

ChunkedBucket.prototype.listRevisions = function(hyper, req) {
    var rp = req.params;
    return hyper.get({
        uri: new URI([rp.domain, 'sys', 'table', this._metaTableName(req), '']),
        body: {
            table: this._metaTableName(req),
            attributes: {
                key: req.params.key
            },
            proj: ['rev', 'tid'],
            limit: getLimit(hyper, req)
        }
    })
    .then(function(res) {
        return {
            status: 200,
            headers: {
                'content-type': 'application/json'
            },
            body: {
                items: res.body.items.map(function(row) {
                    return { revision: row.rev, tid: row.tid };
                }),
                next: res.body.next
            }
        };
    });
};

ChunkedBucket.prototype._setRowTTLs = function(hyper, req, row) {
    var self = this;
    return hyper.put({
        uri: new URI([req.params.domain, 'sys', 'table', self._metaTableName(req), '']),
        body: {
            table: self._metaTableName(req),
            attributes: Object.assign({}, row, { _ttl: GRACE_TTL })
        }
    })
    .then(function() {
        return P.all(range(row.num_chunks).map(function(chunkId) {
            return hyper.get({
                uri: new URI([req.params.domain, 'sys', 'table',
                    self._chunksTableName(req), '']),
                body: {
                    table: self._chunksTableName(req),
                    attributes: {
                        key: row.key,
                        chunk_id: chunkId,
                        tid: row.tid
                    }
                }
            })
            .then(function(res) {
                var value = res.body.items[0];
                return hyper.put({
                    uri: new URI([req.params.domain, 'sys', 'table',
                        self._chunksTableName(req), '']),
                    body: {
                        table: self._chunksTableName(req),
                        attributes: Object.assign(value, { _ttl: GRACE_TTL })
                    }
                });
            });
        }));
    });
};

ChunkedBucket.prototype._retentionPolicyUpdate = function(hyper, req, key, rev, tid) {
    var self = this;
    return hyper.get({
        uri: new URI([req.params.domain, 'sys', 'table', self._metaTableName(req), '']),
        body: {
            table: self._metaTableName(req),
            attributes: {
                key: key,
                rev: rev,
                tid: { lt: tid }
            },
            limit: 4,
            _withTTL: true
        }
    })
    .catch({ status: 404 }, function() {
        // Nothing to update, ignore
    })
    .then(function(res) {
        var rows = res && res.body && res.body.items;
        if (rows && rows.length) {
            var toRemove = rows.filter(function(row) { return !row._ttl; });
            return P.each(toRemove, function(row) {
                return self._setRowTTLs(hyper, req, row);
            });
        }
    });
};

ChunkedBucket.prototype.putRevision = function(hyper, req) {
    var rp = req.params;
    var self = this;
    var rev = parseRevision(rp.revision);
    var tid = rp.tid && coerceTid(rp.tid) || uuid.now().toString();
    if (req.headers['last-modified']) {
        // XXX: require elevated rights for passing in the revision time
        tid = mwUtil.tidFromDate(req.headers['last-modified']);
    }

    var chunks = this._sliceData(req.body);
    return P.all(chunks.map(function(chunk, index) {
        return hyper.put({
            uri: new URI([rp.domain, 'sys', 'table', self._chunksTableName(req), '']),
            body: {
                table: self._chunksTableName(req),
                attributes: {
                    key: rp.key,
                    chunk_id: index,
                    tid: tid,
                    value: chunk
                }
            }
        });
    }))
    .then(function() {
        var headers = Object.assign({}, req.headers);
        headers.etag = headers.etag || mwUtil.makeETag(rev, tid);
        return hyper.put({
            uri: new URI([rp.domain, 'sys', 'table', self._metaTableName(req), '']),
            body: {
                table: self._metaTableName(req),
                attributes: {
                    key: rp.key,
                    rev: rev,
                    tid: tid,
                    num_chunks: chunks.length,
                    headers: headers
                }
            }
        });
    })
    .then(function(res) {
        if (res.status === 201) {
            // Do the retention policy update
            return self._retentionPolicyUpdate(hyper, req, rp.key, rev, tid)
            .thenReturn({
                status: 201,
                headers: {
                    etag: mwUtil.makeETag(rp.revision, tid)
                },
                body: {
                    message: "Created.",
                    tid: rp.revision
                }
            });
        } else {
            throw res;
        }
    })
    .catch(function(error) {
        hyper.log('error/krlv/putRevision', error);
        return { status: 400 };
    });
};

module.exports = function(options) {
    var chunkedBucket = new ChunkedBucket(options);

    return {
        spec: spec, // Re-export from spec module
        operations: {
            createBucket: chunkedBucket.createBucket.bind(chunkedBucket),
            listRevisions: chunkedBucket.listRevisions.bind(chunkedBucket),
            getRevision: chunkedBucket.getRevision.bind(chunkedBucket),
            putRevision: chunkedBucket.putRevision.bind(chunkedBucket)
        }
    };
};
<|endoftext|>


<commit_before>var aster = require('aster'),
	path = require('path'),
	sys = require('sys');

function tryResolve(source)
{
	try
	{
		return require.resolve(source);
	}
	catch(e)
	{
		return null;
	}
}

function scanDeps(sourcePath, callbacks)
{
	var isRoot = !callbacks.cache;

	if(!callbacks.end) callbacks.end     = function(){};
	if(!callbacks.next) callbacks.next   = function(){};
	if(!callbacks.error) callbacks.error = function(){};
	if(!callbacks.cache) callbacks.cache = { used: {}, required: [] };
	if(callbacks.cache.used[sourcePath]) return callbacks.cache.used[sourcePath];

	var depInfo = callbacks.cache.used[sourcePath] = { path: sourcePath },
		cwd = path.dirname(sourcePath);

	try
	{
		var ast = aster.load(sourcePath);
	}
	catch(e)
	{
		console.log(e.stack)
		return;
	}

	//npm package?
	if(sourcePath.match(/\/.*?@.*?\//))
	{
		var realPath = ast.walk({
			'var': function(walker)
			{
				var value = walker.values[0];

				if(value && value.name == 'from')
				{
					return value.value.walk({
						'string': function(walker)
						{
							return walker.value;
						}
					})
				}
			}
		});

		//get the actual path info
		var ret = scanDeps(require.resolve(cwd + '/' + realPath), callbacks);

		//since this is cached, we need to rpeplace i
		depInfo.path = ret.path;

		return ret;
	}

	var requirePaths = [],
		required = [];

	//find all require.paths.unshift(...)
	ast.walk({
		'call': function(walker)
		{
			// console.log(walker.reference)
			var ref = walker.reference;

			if(walker.name == 'require')
			{
				if(ref.chain && ref.chain[1] == 'paths' && (ref.chain[2] || '').match(/push|unshift/g))
				{
					requirePaths.push(walker);
				}
				else
				{
					required.push(walker);
				}
			}
		}
	});

	requirePaths.forEach(function(path)
	{
		try
		{
			eval(path.toString().replace('__dirname',"'"+cwd+"'"));
		}
		catch(e)
		{
			console.log(e);
		}
	});

	required.forEach(function(req)
	{
		var dep = req.walk({
			'string': function(walker)
			{
				return walker.value;
			}
		});

		//relative path?
		if(dep.substr(0,1) == '.')
		{
			dep = cwd + '/' + dep;
		}

		var newDep = dep;

		if(!(newDep = tryResolve(dep)) && !(newDep = tryResolve(cwd+'/'+dep)))
		{

			return callbacks.error({ path: dep, source: sourcePath });
		}
		else
		{
			dep = newDep;
		}

		if(info = scanDeps(dep, callbacks))
		{
			callbacks.require({ path: info.path, source: sourcePath, ast: req, info: info });
		}
	});

	callbacks.next({ path: sourcePath, ast: ast });

	if(isRoot)
	{
		callbacks.end();
	}

	return depInfo;
}

function combineJs(sourceFile, callbacks)
{
	var used = {},
	replace = {},
	buffer = '',
	index = 0;

	scanDeps(sourceFile, {
		error: function(ops)
		{
			console.log('cannot include %s', ops.path);
		},
		require: function(ops)
		{
			var ast = ops.ast,
			varName = 'sardVar' + (index++),
			moduleName = used[ops.path];

			if(!replace[ops.source]) replace[ops.source] = {};

			if(ast.assignedTo)
			{
				ast.assignedTo.references().forEach(function(vr)
				{
					vr.replaceName(varName);
				});

				ast.assignedTo.replaceName(varName);
			}

			replace[ops.source][ast.toString()] = moduleName;
		},
		next: function(ops)
		{
			var moduleName = 'sardModule' + (index++);

			used[ops.path] = moduleName;

			var script = ops.ast.toString().replace(/(module\.)?exports(?=[^\w])/g,moduleName);
				required = replace[ops.path];

			for(var rep in required)
			{
				script = script.replace(rep,required[rep]);
			}

			callbacks.write(moduleName + ' = {}; \n '+script + '\n');
		},
		end: function()
		{
			callbacks.end();
		}
	})
}

exports.scanDeps = scanDeps;
exports.combineJs = combineJs;

<commit_msg>add var before setting module<commit_after>var aster = require('aster'),
	path = require('path'),
	sys = require('sys');

function tryResolve(source)
{
	try
	{
		return require.resolve(source);
	}
	catch(e)
	{
		return null;
	}
}

function scanDeps(sourcePath, callbacks)
{
	var isRoot = !callbacks.cache;

	if(!callbacks.end) callbacks.end     = function(){};
	if(!callbacks.next) callbacks.next   = function(){};
	if(!callbacks.error) callbacks.error = function(){};
	if(!callbacks.cache) callbacks.cache = { used: {}, required: [] };
	if(callbacks.cache.used[sourcePath]) return callbacks.cache.used[sourcePath];

	var depInfo = callbacks.cache.used[sourcePath] = { path: sourcePath },
		cwd = path.dirname(sourcePath);

	try
	{
		var ast = aster.load(sourcePath);
	}
	catch(e)
	{
		console.log(e.stack)
		return;
	}

	//npm package?
	if(sourcePath.match(/\/.*?@.*?\//))
	{
		var realPath = ast.walk({
			'var': function(walker)
			{
				var value = walker.values[0];

				if(value && value.name == 'from')
				{
					return value.value.walk({
						'string': function(walker)
						{
							return walker.value;
						}
					})
				}
			}
		});

		//get the actual path info
		var ret = scanDeps(require.resolve(cwd + '/' + realPath), callbacks);

		//since this is cached, we need to rpeplace i
		depInfo.path = ret.path;

		return ret;
	}

	var requirePaths = [],
		required = [];

	//find all require.paths.unshift(...)
	ast.walk({
		'call': function(walker)
		{
			// console.log(walker.reference)
			var ref = walker.reference;

			if(walker.name == 'require')
			{
				if(ref.chain && ref.chain[1] == 'paths' && (ref.chain[2] || '').match(/push|unshift/g))
				{
					requirePaths.push(walker);
				}
				else
				{
					required.push(walker);
				}
			}
		}
	});

	requirePaths.forEach(function(path)
	{
		try
		{
			eval(path.toString().replace('__dirname',"'"+cwd+"'"));
		}
		catch(e)
		{
			console.log(e);
		}
	});

	required.forEach(function(req)
	{
		var dep = req.walk({
			'string': function(walker)
			{
				return walker.value;
			}
		});

		//relative path?
		if(dep.substr(0,1) == '.')
		{
			dep = cwd + '/' + dep;
		}

		var newDep = dep;

		if(!(newDep = tryResolve(dep)) && !(newDep = tryResolve(cwd+'/'+dep)))
		{

			return callbacks.error({ path: dep, source: sourcePath });
		}
		else
		{
			dep = newDep;
		}

		if(info = scanDeps(dep, callbacks))
		{
			callbacks.require({ path: info.path, source: sourcePath, ast: req, info: info });
		}
	});

	callbacks.next({ path: sourcePath, ast: ast });

	if(isRoot)
	{
		callbacks.end();
	}

	return depInfo;
}

function combineJs(sourceFile, callbacks)
{
	var used = {},
	replace = {},
	buffer = '',
	index = 0;

	scanDeps(sourceFile, {
		error: function(ops)
		{
			console.log('cannot include %s', ops.path);
		},
		require: function(ops)
		{
			var ast = ops.ast,
			varName = 'sardVar' + (index++),
			moduleName = used[ops.path];

			if(!replace[ops.source]) replace[ops.source] = {};

			if(ast.assignedTo)
			{
				ast.assignedTo.references().forEach(function(vr)
				{
					vr.replaceName(varName);
				});

				ast.assignedTo.replaceName(varName);
			}

			replace[ops.source][ast.toString()] = moduleName;
		},
		next: function(ops)
		{
			var moduleName = 'sardModule' + (index++);

			used[ops.path] = moduleName;

			var script = ops.ast.toString().replace(/(module\.)?exports(?=[^\w])/g,moduleName);
				required = replace[ops.path];

			for(var rep in required)
			{
				script = script.replace(rep,required[rep]);
			}

			callbacks.write('var '+moduleName + ' = {}; \n'+script + '\n');
		},
		end: function()
		{
			callbacks.end();
		}
	})
}

exports.scanDeps = scanDeps;
exports.combineJs = combineJs;

<|endoftext|>