<commit_before>//TODO: make this more readable
define([
    'd3',
    'underscore',
    'components/component'
], function(d3, _, Component) {

    // TODO: Move these into barchart's space

    var margin = {
        left: 55,
        right: 15,
        top: 15,
        bottom: 10
    },
        formatValue = d3.format(',.1s'),
        x = d3.scale.ordinal(),
        y = d3.scale.linear().nice(),
        xAxis = d3.svg.axis().scale(x).orient('bottom'),
        yAxis = d3.svg.axis().scale(y).orient('left')
            .tickFormat(function(d) {
                return formatValue(d);
            })
            .tickSize(5, 5, 0);

    var BarChart = Component.extend({
        init: function(context, options) {
            this.name = 'bar-chart';
            this.template = 'components/' + this.name + '/' + this.name;
            this._super(context, options);
        },

        //load barchart data
        loadData: function() {

            var _this = this,
                defer = $.Deferred();

            var indicator = this.model.getState("yaxis").indicator;
            var indicatorFile = 'stats/' + indicator + '.json';
            var waffleFile = 'waffle-' + this.model.getState("language") + '.json';
            var dataMan = this.dataManager;

            //load data and resolve the defer when it's done
            $.when(
                dataMan.loadWaffle(this.model.getData("path") + waffleFile),
                dataMan.loadStats(this.model.getData("path") + indicatorFile, indicator)
            ).done(function() {

                //prepare data
                var stats = _this.dataManager.getStats();
                var waffle = _this.dataManager.getWaffle();
                var time = _this.model.getState("time");

                // Prepare data
                var show = _.flatten(
                    _.map(_this.model.getState("show"), function(object, region) {
                        if (object.filter) {
                            return _.map(object.filter, function(d) {
                                return {
                                    category: region,
                                    id: d
                                }
                            });
                        } else {
                            return {
                                category: region,
                                id: undefined
                            }
                        }
                    })
                );

                var things = _this.dataManager.getThing(show);
                var ids = _.map(things, function(t) {
                    return t.id;
                });
                var data = _.pick(stats[indicator], ids);

                _this.data = {
                    show: show,
                    things: things,
                    ids: ids,
                    data: data
                };

                defer.resolve();
            });

            return defer;
        },

        draw: function() {
            var measures = this.placeholder.node().getBoundingClientRect(),
                width = measures.width - margin.left - margin.right,
                height = measures.height - margin.top - margin.bottom,
                _this = this,
                time = _this.model.getState("time"),
                waffle = _this.dataManager.getWaffle(),
                indicator = this.model.getState("yaxis").indicator;

            x.rangeRoundBands([0, width], .1, .3);
            y.range([height, 0]);

            this.chartArea = this.element
                .append('g')
                .attr('transform',
                    'translate(' + margin.left + ',' + margin.top + ')');

            this.element.attr('class', this.name);

            this.chartArea.append('g')
                .attr('class', 'y axis')
                .call(yAxis);

            this.chartArea.append('g')
                .attr('class', 'x axis')
                .attr('transform', 'translate(0,' + height + ')')
                .call(xAxis);

            // Sets x scale domain
            x.domain(_.map(this.data.things, function(d) {
                return d.name;
            }));

            // Sets y scale domain
            y.domain([0, _.max(_.map(this.data.data, function(d) {
                return _.max(_.pluck(d, 'v'));
            }))]);

            // draw axis
            var chart = this.chartArea.selectAll('.bar')
                .data(this.data.ids)
                .enter();

            chart.append('rect')
                .attr('class', 'bar')
                .attr('x', function(d) {
                    return x(_this.data.things[d].name);
                })
                .attr('width', x.rangeBand())
                .attr('y', function(d) {
                    return y(_this.data.data[d][time].v);
                })
                .attr('height', function(d) {
                    return height - y(_this.data.data[d][time].v);
                });

            chart.append('text')
                .attr('class', 'bar-title')
                .attr('y', function(d) {
                    return y(_this.data.data[d][time].v) - 5;
                })
                .attr('x', function(d) {
                    return x(_this.data.things[d].name) + (x.rangeBand() / 2);
                })
                .text(function(d) {
                    return _this.data.things[d].name;
                });

            this.chartArea.select('.x.axis')
                .attr('transform', 'translate(0,' + height + ')')
                .call(xAxis)
                .selectAll('.tick text')
                .remove();

            this.chartArea.select('.y.axis')
                .call(yAxis);

            this.chartArea.append('text')
                .attr('class', 'title')
                .attr('transform', 'translate(' + 10 + ',' + 20 + ')')
                .text(waffle.definitions.indicators[indicator].name);

        },

        postRender: function() {

            var _this = this,
                promise = this.loadData();

            promise.then(function() {

                _this.draw();

            });

        },

        update: function() {
            console.log("THE BAR CHART WANTS TO UPDATE!!!");
        },

        resize: function() {
            if (!this.chartArea) return;

            var measures = this.placeholder.node().getBoundingClientRect(),
                width = measures.width - margin.left - margin.right,
                height = measures.height - margin.top - margin.bottom;

            this.element
                .attr('height', measures.height)
                .attr('width', measures.width);

            this.chartArea
                .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

            x.rangeRoundBands([0, width], .1, .3);
            y.range([height, 0]);

            this.chartArea.select('.x.axis')
                .attr('transform', 'translate(0,' + height + ')')
                .call(xAxis);

            this.chartArea.select('.y.axis')
                .call(yAxis);

            // If we have data, be responsive on resize
            if (this.data) {
                var things = this.data.things,
                    data = this.data.data,
                    time = this.model.getState("time");

                // reposition rectangles
                this.chartArea.selectAll('.bar')
                    .each(function(d) {
                        var rect = d3.select(this),
                            rectdata = rect.data();
                        // re-calc bars
                        rect.attr('x', x(things[rectdata].name))
                            .attr('width', x.rangeBand())
                            .attr('y', y(data[rectdata][time].v))
                            .attr('height', height - y(data[rectdata][time].v));
                    });

                // re-position titles
                this.chartArea.selectAll('.bar-title')
                    .each(function(d) {
                        var text = d3.select(this),
                            textData = text.data();
                        // recalc position
                        text.attr('y', y(data[textData][time].v) - 5)
                            .attr('x', x(things[textData].name) + (x.rangeBand() / 2))
                    })
            }
        }
    });

    return BarChart;
});<commit_msg>Modularizes data loading into a separate function<commit_after>//TODO: make this more readable
define([
    'd3',
    'underscore',
    'components/component'
], function(d3, _, Component) {

    // TODO: Move these into barchart's space

    var margin = {
        left: 55,
        right: 15,
        top: 15,
        bottom: 10
    },
        formatValue = d3.format(',.1s'),
        x = d3.scale.ordinal(),
        y = d3.scale.linear().nice(),
        xAxis = d3.svg.axis().scale(x).orient('bottom'),
        yAxis = d3.svg.axis().scale(y).orient('left')
            .tickFormat(function(d) {
                return formatValue(d);
            })
            .tickSize(5, 5, 0);

    var BarChart = Component.extend({
        init: function(context, options) {
            this.name = 'bar-chart';
            this.template = 'components/' + this.name + '/' + this.name;
            this._super(context, options);
        },

        //load barchart data
        loadData: function() {

            var _this = this,
                defer = $.Deferred();

            var indicator = this.model.getState("yaxis").indicator,
                indicatorFile = 'stats/' + indicator + '.json',
                waffleFile = 'waffle-' + this.model.getState("language") + '.json',
                dataMan = this.dataManager;

            var data_filter = prepareDataFilter(this.model.getState("show")),
                ids = _.map(data_filter, function(i) { return i.id } );

            //load data and resolve the defer when it's done
            $.when(
                dataMan.loadWaffle(this.model.getData("path") + waffleFile),
                dataMan.loadStats(this.model.getData("path") + indicatorFile, indicator)
            ).done(function() {
                //getting data from data manager
                var stats = _this.dataManager.getStats();
                var waffle = _this.dataManager.getWaffle();
                //get more info about each thing
                _this.things = _this.dataManager.getThing(data_filter);
                //filter data by id
                _this.data = _.pick(stats[indicator], ids);

                defer.resolve();
            });

            return defer;
        },

        draw: function() {
            var measures = this.placeholder.node().getBoundingClientRect(),
                width = measures.width - margin.left - margin.right,
                height = measures.height - margin.top - margin.bottom,
                _this = this,
                time = _this.model.getState("time"),
                waffle = _this.dataManager.getWaffle(),
                indicator = this.model.getState("yaxis").indicator;

            x.rangeRoundBands([0, width], .1, .3);
            y.range([height, 0]);

            this.chartArea = this.element
                .append('g')
                .attr('transform',
                    'translate(' + margin.left + ',' + margin.top + ')');

            this.element.attr('class', this.name);

            this.chartArea.append('g')
                .attr('class', 'y axis')
                .call(yAxis);

            this.chartArea.append('g')
                .attr('class', 'x axis')
                .attr('transform', 'translate(0,' + height + ')')
                .call(xAxis);

            // Sets x scale domain
            x.domain(_.map(this.data.things, function(d) {
                return d.name;
            }));

            // Sets y scale domain
            y.domain([0, _.max(_.map(this.data.data, function(d) {
                return _.max(_.pluck(d, 'v'));
            }))]);

            // draw axis
            var chart = this.chartArea.selectAll('.bar')
                .data(this.data.ids)
                .enter();

            chart.append('rect')
                .attr('class', 'bar')
                .attr('x', function(d) {
                    return x(_this.data.things[d].name);
                })
                .attr('width', x.rangeBand())
                .attr('y', function(d) {
                    return y(_this.data.data[d][time].v);
                })
                .attr('height', function(d) {
                    return height - y(_this.data.data[d][time].v);
                });

            chart.append('text')
                .attr('class', 'bar-title')
                .attr('y', function(d) {
                    return y(_this.data.data[d][time].v) - 5;
                })
                .attr('x', function(d) {
                    return x(_this.data.things[d].name) + (x.rangeBand() / 2);
                })
                .text(function(d) {
                    return _this.data.things[d].name;
                });

            this.chartArea.select('.x.axis')
                .attr('transform', 'translate(0,' + height + ')')
                .call(xAxis)
                .selectAll('.tick text')
                .remove();

            this.chartArea.select('.y.axis')
                .call(yAxis);

            this.chartArea.append('text')
                .attr('class', 'title')
                .attr('transform', 'translate(' + 10 + ',' + 20 + ')')
                .text(waffle.definitions.indicators[indicator].name);

        },

        postRender: function() {

            var _this = this,
                defer = $.Deferred();
                promise = this.loadData();

            promise.then(function() {

                //draw graph with d3
                _this.draw();

                //this component is ready
                defer.resolve();

            });

            return defer;

        },

        update: function() {
            console.log("THE BAR CHART WANTS TO UPDATE!!!");
        },

        resize: function() {
            if (!this.chartArea) return;

            var measures = this.placeholder.node().getBoundingClientRect(),
                width = measures.width - margin.left - margin.right,
                height = measures.height - margin.top - margin.bottom;

            this.element
                .attr('height', measures.height)
                .attr('width', measures.width);

            this.chartArea
                .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

            x.rangeRoundBands([0, width], .1, .3);
            y.range([height, 0]);
        }
    });

    //Transform data filter into shallow version
    function prepareDataFilter(show) {

        var result = [];
        //iterate over each category we want to show
        for (var reg_type in show) {
            //if category has sub filters, add them instead
            if (show[reg_type].hasOwnProperty("filter")) {
                for (var reg in show[reg_type].filter) {
                    result.push({
                        category: reg_type,
                        id: show[reg_type].filter[reg]
                    });
                }
            }
            //if not, add the category itself (e.g.: world)
            else {
                result.push({
                    category: reg_type,
                    id: reg_type
                });
            }
        }
        return result;
    };

    return BarChart;
});<|endoftext|>


<commit_before>// Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/**
 * Container is responsible for the video rendering and state
 */

var UIObject = require('../../base/ui_object');
var Styler = require('../../base/styler');
var _ = require('underscore');

class Container extends UIObject {
  get name() { return 'Container' }
  get attributes() { return { 'data-container': '' } }
  get events() { return {'click': 'clicked'} }

  constructor(options) {
    super(options);
    this.playback = options.playback;
    this.settings = this.playback.settings;
    this.isReady = false;
    this.mediaControlDisabled = false;
    this.plugins = [this.playback];
    this.bindEvents();
  }

  bindEvents() {
    this.listenTo(this.playback, 'playback:progress', this.progress);
    this.listenTo(this.playback, 'playback:timeupdate', this.timeUpdated);
    this.listenTo(this.playback, 'playback:ready', this.ready);
    this.listenTo(this.playback, 'playback:buffering', this.buffering);
    this.listenTo(this.playback, 'playback:bufferfull', this.bufferfull);
    this.listenTo(this.playback, 'playback:settingsupdate', this.settingsUpdate);
    this.listenTo(this.playback, 'playback:loadedmetadata', this.loadedMetadata);
    this.listenTo(this.playback, 'playback:highdefinitionupdate', this.highDefinitionUpdate);
    this.listenTo(this.playback, 'playback:playbackstate', this.playbackStateChanged);
    this.listenTo(this.playback, 'playback:dvr', this.playbackDvrStateChanged);
    this.listenTo(this.playback, 'playback:mediacontrol:disable', this.disableMediaControl);
    this.listenTo(this.playback, 'playback:mediacontrol:enable', this.enableMediaControl);
    this.listenTo(this.playback, 'playback:ended', this.ended);
    this.listenTo(this.playback, 'playback:play', this.playing);
    this.listenTo(this.playback, 'playback:error', this.error);
  }

  with(klass) {
    _.extend(this, klass);
    return this;
  }

  playbackStateChanged() {
    this.trigger('container:playbackstate');
  }

  playbackDvrStateChanged(dvrInUse) {
    this.settings = this.playback.settings
    this.dvrInUse = dvrInUse
    this.trigger('container:dvr', dvrInUse)
  }

  statsAdd(metric) {
    this.trigger('container:stats:add', metric)
  }

  statsReport(metrics) {
    this.trigger('container:stats:report', metrics)
  }

  getPlaybackType() {
    return this.playback.getPlaybackType()
  }

  isDvrEnabled() {
    return !!this.playback.dvrEnabled
  }

  isDvrInUse() {
    return !!this.dvrInUse
  }

  destroy() {
    this.trigger('container:destroyed', this, this.name);
    this.playback.destroy();
    _(this.plugins).each((plugin) => plugin.destroy())
    this.$el.remove();
  }

  setStyle(style) {
    this.$el.css(style);
  }

  animate(style, duration) {
    return this.$el.animate(style, duration).promise();
  }

  ready() {
    this.isReady = true;
    this.trigger('container:ready', this.name);
  }

  isPlaying() {
    return this.playback.isPlaying();
  }

  getDuration() {
    return this.playback.getDuration();
  }

  error(error) {
    this.$el.prepend(error.render().el)
    this.trigger('container:error', {error: error, container: this}, this.name);
  }

  loadedMetadata(duration) {
    this.trigger('container:loadedmetadata', duration);
  }

  timeUpdated(position, duration) {
    this.trigger('container:timeupdate', position, duration, this.name);
  }

  progress(startPosition, endPosition, duration) {
    this.trigger('container:progress', startPosition, endPosition, duration, this.name);
  }

  playing() {
    this.trigger('container:play', this.name);
  }

  play() {
    this.playback.play();
  }

  stop() {
    this.trigger('container:stop', this.name);
    this.playback.stop();
  }

  pause() {
    this.trigger('container:pause', this.name);
    this.playback.pause();
  }

  ended() {
    this.trigger('container:ended', this, this.name);
  }

  clicked() {
    this.trigger('container:click', this, this.name);
  }

  setCurrentTime(time) {
    this.trigger('container:seek', time, this.name);
    this.playback.seek(time);
  }

  setVolume(value) {
    this.trigger('container:volume', value, this.name);
    this.playback.volume(value);
  }

  requestFullscreen() {
    this.trigger('container:fullscreen', this.name);
  }

  buffering() {
    this.trigger('container:state:buffering', this.name);
  }

  bufferfull() {
    this.trigger('container:state:bufferfull', this.name);
  }

  addPlugin(plugin) {
    this.plugins.push(plugin);
  }

  hasPlugin(name) {
    return !!this.getPlugin(name);
  }

  getPlugin(name) {
    return _(this.plugins).find(function(plugin) { return plugin.name === name });
  }

  settingsUpdate() {
    this.settings = this.playback.settings;
    this.trigger('container:settingsupdate');
  }

  highDefinitionUpdate() {
    this.trigger('container:highdefinitionupdate');
  }

  isHighDefinitionInUse() {
    return this.playback.isHighDefinitionInUse()
  }

  disableMediaControl() {
    this.mediaControlDisabled = true;
    this.trigger('container:mediacontrol:disable');
  }

  enableMediaControl() {
    this.mediaControlDisabled = false;
    this.trigger('container:mediacontrol:enable');
  }

  render() {
    var style = Styler.getStyleFor('container');
    this.$el.append(style);
    this.$el.append(this.playback.render().el);
    return this;
  }
}

module.exports = Container;
<commit_msg>container: fix jshint complaints<commit_after>// Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/**
 * Container is responsible for the video rendering and state
 */

var UIObject = require('../../base/ui_object');
var Styler = require('../../base/styler');
var _ = require('underscore');

class Container extends UIObject {
  get name() { return 'Container' }
  get attributes() { return { 'data-container': '' } }
  get events() { return {'click': 'clicked'} }

  constructor(options) {
    super(options);
    this.playback = options.playback;
    this.settings = this.playback.settings;
    this.isReady = false;
    this.mediaControlDisabled = false;
    this.plugins = [this.playback];
    this.bindEvents();
  }

  bindEvents() {
    this.listenTo(this.playback, 'playback:progress', this.progress);
    this.listenTo(this.playback, 'playback:timeupdate', this.timeUpdated);
    this.listenTo(this.playback, 'playback:ready', this.ready);
    this.listenTo(this.playback, 'playback:buffering', this.buffering);
    this.listenTo(this.playback, 'playback:bufferfull', this.bufferfull);
    this.listenTo(this.playback, 'playback:settingsupdate', this.settingsUpdate);
    this.listenTo(this.playback, 'playback:loadedmetadata', this.loadedMetadata);
    this.listenTo(this.playback, 'playback:highdefinitionupdate', this.highDefinitionUpdate);
    this.listenTo(this.playback, 'playback:playbackstate', this.playbackStateChanged);
    this.listenTo(this.playback, 'playback:dvr', this.playbackDvrStateChanged);
    this.listenTo(this.playback, 'playback:mediacontrol:disable', this.disableMediaControl);
    this.listenTo(this.playback, 'playback:mediacontrol:enable', this.enableMediaControl);
    this.listenTo(this.playback, 'playback:ended', this.ended);
    this.listenTo(this.playback, 'playback:play', this.playing);
    this.listenTo(this.playback, 'playback:error', this.error);
  }

  with(klass) {
    _.extend(this, klass);
    return this;
  }

  playbackStateChanged() {
    this.trigger('container:playbackstate');
  }

  playbackDvrStateChanged(dvrInUse) {
    this.settings = this.playback.settings
    this.dvrInUse = dvrInUse
    this.trigger('container:dvr', dvrInUse)
  }

  statsAdd(metric) {
    this.trigger('container:stats:add', metric)
  }

  statsReport(metrics) {
    this.trigger('container:stats:report', metrics)
  }

  getPlaybackType() {
    return this.playback.getPlaybackType()
  }

  isDvrEnabled() {
    return !!this.playback.dvrEnabled
  }

  isDvrInUse() {
    return !!this.dvrInUse
  }

  destroy() {
    this.trigger('container:destroyed', this, this.name);
    this.playback.destroy();
    _(this.plugins).each((plugin) => plugin.destroy())
    this.$el.remove();
  }

  setStyle(style) {
    this.$el.css(style);
  }

  animate(style, duration) {
    return this.$el.animate(style, duration).promise();
  }

  ready() {
    this.isReady = true;
    this.trigger('container:ready', this.name);
  }

  isPlaying() {
    return this.playback.isPlaying();
  }

  getDuration() {
    return this.playback.getDuration();
  }

  error(errorObj) {
    this.$el.prepend(errorObj.render().el)
    this.trigger('container:error', {error: errorObj, container: this}, this.name);
  }

  loadedMetadata(duration) {
    this.trigger('container:loadedmetadata', duration);
  }

  timeUpdated(position, duration) {
    this.trigger('container:timeupdate', position, duration, this.name);
  }

  progress(startPosition, endPosition, duration) {
    this.trigger('container:progress', startPosition, endPosition, duration, this.name);
  }

  playing() {
    this.trigger('container:play', this.name);
  }

  play() {
    this.playback.play();
  }

  stop() {
    this.trigger('container:stop', this.name);
    this.playback.stop();
  }

  pause() {
    this.trigger('container:pause', this.name);
    this.playback.pause();
  }

  ended() {
    this.trigger('container:ended', this, this.name);
  }

  clicked() {
    this.trigger('container:click', this, this.name);
  }

  setCurrentTime(time) {
    this.trigger('container:seek', time, this.name);
    this.playback.seek(time);
  }

  setVolume(value) {
    this.trigger('container:volume', value, this.name);
    this.playback.volume(value);
  }

  requestFullscreen() {
    this.trigger('container:fullscreen', this.name);
  }

  buffering() {
    this.trigger('container:state:buffering', this.name);
  }

  bufferfull() {
    this.trigger('container:state:bufferfull', this.name);
  }

  addPlugin(plugin) {
    this.plugins.push(plugin);
  }

  hasPlugin(name) {
    return !!this.getPlugin(name);
  }

  getPlugin(name) {
    return _(this.plugins).find(function(plugin) { return plugin.name === name });
  }

  settingsUpdate() {
    this.settings = this.playback.settings;
    this.trigger('container:settingsupdate');
  }

  highDefinitionUpdate() {
    this.trigger('container:highdefinitionupdate');
  }

  isHighDefinitionInUse() {
    return this.playback.isHighDefinitionInUse()
  }

  disableMediaControl() {
    this.mediaControlDisabled = true;
    this.trigger('container:mediacontrol:disable');
  }

  enableMediaControl() {
    this.mediaControlDisabled = false;
    this.trigger('container:mediacontrol:enable');
  }

  render() {
    var style = Styler.getStyleFor('container');
    this.$el.append(style);
    this.$el.append(this.playback.render().el);
    return this;
  }
}

module.exports = Container;
<|endoftext|>


<commit_before>(function() {
    module.exports = CropArea();

    function CropArea() {

        var _eventsQueue   = require('../events-queue/events-queue.js'),
            _utils         = require('../utils/utils.js'),
            _settings      = require('../settings/settings.js'),
            _information   = require('../information/information.js'),
            _this          = {},
            _hasInit       = false,
            _onChangeQueue = [],
            _image         = new Image(),
            _canvasElement,
            _source,
            _canvas,
            _context;

        /*========================================================================
            PUBLIC
        ========================================================================*/

        _this.changeFile = changeFile;
        _this.onChange   = storeOnChange;

        return _this;

        /*========================================================================
            PRIVATE
        ========================================================================*/

        function init(){
            createCanvasElement();
            bindListeners();
            _hasInit = true;
        }

        function changeFile(file){
            if(!_hasInit){
                init();
            }
            _utils.fileToBase64(file, function (src) {
                _information.updateProperty('originalImage', {
                    src  : src,
                    file : _utils.base64toBlob(src)
                });
                _image.src = src;
            });
        }

        function bindListeners(){
            _image.onload = onCanvasSrcLoad;
            _eventsQueue.subscribe('resize', window, cacheCanvasDimensions);
        }

        function createCanvasElement(){

            var cropArea    = _settings.cropArea,
                tagName;

            if(cropArea){
                tagName = cropArea.tagName.toLocaleLowerCase();

                if(_settings.cropArea && !_utils.isClosedElement(_settings.cropArea)){
                    if(tagName !== "canvas"){
                        _canvasElement = document.createElement('canvas');
                        cropArea.appendChild(_canvasElement);
                    }else{
                        _canvasElement = _settings.cropArea;
                    }

                    _context        =   _canvasElement.getContext('2d');
                }
            }
        }

        function onCanvasSrcLoad(e){

            var canvasParams;

            _information.updateProperty('originalImage', {
                width  : this.width,
                height : this.height
            });

            //Without a set size on the canvas the image data context with render at it's default dimensions of 300x150.
            //CSS will then scale the scaled down image data up to the size that it calculates for the DOM.
            _canvasElement.width    = _canvasElement.offsetWidth;
            _canvasElement.height   = _canvasElement.offsetHeight;

            _source           = {};
            _canvas           = {};

            _source['width']  = this.width;
            _source['height'] = this.height;

            _canvas['width']  = _canvasElement.width;
            _canvas['height'] = _canvasElement.height;

            canvasParams  = measureContext();

            _canvas['widthRatio']   = (canvasParams.dWidth / _canvas['width']);
            _canvas['heightRatio']  = (canvasParams.dHeight / _canvas['height']);

            _context.clearRect(0, 0, _canvas.width, _canvas.height);
            _context.drawImage(_image,
                canvasParams.sx,
                canvasParams.sy,
                canvasParams.sWidth,
                canvasParams.sHeight,
                canvasParams.dx,
                canvasParams.dy,
                canvasParams.dWidth,
                canvasParams.dHeight
            );
            cacheCanvasDimensions();
            notify();
        }

        function storeOnChange(fn){
            _onChangeQueue.push(fn);
        }

        function notify(){
            var totalSubscribers= _onChangeQueue.length;
            while(totalSubscribers--){
                if(_onChangeQueue[totalSubscribers] && typeof _onChangeQueue[totalSubscribers] === 'function'){
                    _onChangeQueue[totalSubscribers]({
                        source : _source,
                        canvas : _canvas,
                        context: _context
                    });
                }
            }
        }

        function cacheCanvasDimensions(){
            if(_canvasElement && _canvas){
                var canvasBounding = _canvasElement.getBoundingClientRect();
                _canvas['top']     = canvasBounding.top;
                _canvas['left']    = canvasBounding.left;
                _canvas['cWidth']  = _canvasElement.offsetWidth;
                _canvas['cHeight'] = _canvasElement.offsetHeight;
            }
        }

        function measureContext(){
            var hRatio   =   _canvas.width  / _source.width,
                vRatio   =   _canvas.height  / _source.height,
                ratio    =   Math.min( hRatio, vRatio);

            return{
                sx:      0,
                sy:      0,
                sWidth:  _source.width,
                sHeight: _source.height,
                dx:      (_canvas.width - _source.width * ratio ) / 2,
                dy:      (_canvas.height - _source.height * ratio ) / 2,
                dWidth:  _source.width * ratio,
                dHeight: _source.height * ratio
            }
        }
    }
})();<commit_msg>Updated crop area to use an array of arguments when drawing pixel data to make data source easier to apply to other components.<commit_after>(function() {
    module.exports = CropArea();

    function CropArea() {

        var _eventsQueue   = require('../events-queue/events-queue.js'),
            _utils         = require('../utils/utils.js'),
            _settings      = require('../settings/settings.js'),
            _information   = require('../information/information.js'),
            _this          = {},
            _hasInit       = false,
            _onChangeQueue = [],
            _image         = new Image(),
            _canvasElement,
            _source,
            _canvas,
            _context;

        /*========================================================================
            PUBLIC
        ========================================================================*/

        _this.changeFile = changeFile;
        _this.onChange   = storeOnChange;

        return _this;

        /*========================================================================
            PRIVATE
        ========================================================================*/

        function init(){
            createCanvasElement();
            bindListeners();
            _hasInit = true;
        }

        function changeFile(file){
            if(!_hasInit){
                init();
            }
            _utils.fileToBase64(file, function (src) {
                _information.updateProperty('originalImage', {
                    src  : src,
                    file : _utils.base64toBlob(src)
                });
                _image.src = src;
            });
        }

        function bindListeners(){
            _image.onload = onCanvasSrcLoad;
            _eventsQueue.subscribe('resize', window, cacheCanvasDimensions);
        }

        function createCanvasElement(){

            var cropArea    = _settings.cropArea,
                tagName;

            if(cropArea){
                tagName = cropArea.tagName.toLocaleLowerCase();

                if(_settings.cropArea && !_utils.isClosedElement(_settings.cropArea)){
                    if(tagName !== "canvas"){
                        _canvasElement = document.createElement('canvas');
                        cropArea.appendChild(_canvasElement);
                    }else{
                        _canvasElement = _settings.cropArea;
                    }

                    _context        =   _canvasElement.getContext('2d');
                }
            }
        }

        function onCanvasSrcLoad(e){

            var canvasParams;

            _information.updateProperty('originalImage', {
                width  : this.width,
                height : this.height
            });

            //Without a set size on the canvas the image data context with render at it's default dimensions of 300x150.
            //CSS will then scale the scaled down image data up to the size that it calculates for the DOM.
            _canvasElement.width    = _canvasElement.offsetWidth;
            _canvasElement.height   = _canvasElement.offsetHeight;

            _source                 = {};
            _canvas                 = {};

            _source['width']        = this.width;
            _source['height']       = this.height;

            _canvas['width']        = _canvasElement.width;
            _canvas['height']       = _canvasElement.height;

            canvasParams            = measureContext();

            _canvas['widthRatio']   = (canvasParams.dWidth / _canvas['width']);
            _canvas['heightRatio']  = (canvasParams.dHeight / _canvas['height']);

            _context.clearRect(0, 0, _canvas.width, _canvas.height);

            canvasParams.unshift(_image);
            _context.drawImage.apply(_context, canvasParams);
            cacheCanvasDimensions();
            notify(canvasParams);
        }

        function storeOnChange(fn){
            _onChangeQueue.push(fn);
        }

        function notify(canvasParams){
            var totalSubscribers= _onChangeQueue.length;
            while(totalSubscribers--){
                if(_onChangeQueue[totalSubscribers] && typeof _onChangeQueue[totalSubscribers] === 'function'){
                    _onChangeQueue[totalSubscribers]({
                        source       : _source,
                        canvas       : _canvas,
                        context      : _context,
                        canvasParams : canvasParams
                    });
                }
            }
        }

        function cacheCanvasDimensions(){
            if(_canvasElement && _canvas){
                var canvasBounding = _canvasElement.getBoundingClientRect();
                _canvas['top']     = canvasBounding.top;
                _canvas['left']    = canvasBounding.left;
                _canvas['cWidth']  = _canvasElement.offsetWidth;
                _canvas['cHeight'] = _canvasElement.offsetHeight;
            }
        }

        function measureContext(){
            var hRatio        =   _canvas.width  / _source.width,
                vRatio        =   _canvas.height  / _source.height,
                ratio         =   Math.min( hRatio, vRatio),
                paramsAsObect = {
                    sx:      0,
                    sy:      0,
                    sWidth:  _source.width,
                    sHeight: _source.height,
                    dx:      (_canvas.width - _source.width * ratio ) / 2,
                    dy:      (_canvas.height - _source.height * ratio ) / 2,
                    dWidth:  _source.width * ratio,
                    dHeight: _source.height * ratio
                };
            return Object.keys(paramsAsObect).map(function (key) {
                return paramsAsObect[key]
            });
        }
    }
})();<|endoftext|>


<commit_before>/* eslint-disable jsx-a11y/no-static-element-interactions */
import Immutable from 'immutable'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router'
import classNames from 'classnames'
import Mousetrap from 'mousetrap'
import ImageAsset from '../assets/ImageAsset'
import { ElloBuyButton } from '../editor/ElloBuyButton'
import { DismissButtonLGReverse } from '../buttons/Buttons'
import { SHORTCUT_KEYS } from '../../constants/application_types'
import { css, select } from '../../styles/jss'
import * as s from '../../styles/jso'

const STATUS = {
  PENDING: 'isPending',
  REQUEST: 'isRequesting',
  SUCCESS: null,
  FAILURE: 'isFailing',
}

const lightBoxInactiveImageStyle = css(
  s.inline,
  s.relative,
  s.center,
  s.bgcF2,
  select(
    '> .LightBoxMask',
    s.bgcTransparent,
    select(
      '> .LightBox',
      s.relative,
      s.alignTop,
      s.inline,
      select(
        '> .ImgHolder',
        s.relative,
        s.inlineBlock,
        select(
          '> .ImageAttachment',
          {
            transform: 'scale(1.0)',
          },
        ),
      ),
    ),
  ),
)

const lightBoxImageStyle = css(
  s.block,
  s.relative,
  s.bgcF2,
  { margin: '0 auto' },
  select(
    '> .LightBoxMask',
    s.fullscreen,
    s.fullWidth,
    s.fullHeight,
    s.bgcModal,
    s.zModal,
    { transition: `background-color 0.4s ${s.ease}` },
    select(
      '> .LightBox',
      s.relative,
      s.containedAlignMiddle,
      s.center,
      select(
        '> .ImageAttachment',
      ),
    ),
  ),
)

class ImageRegion extends Component {

  static propTypes = {
    asset: PropTypes.object,
    buyLinkURL: PropTypes.string,
    columnWidth: PropTypes.number,
    commentOffset: PropTypes.number,
    content: PropTypes.object.isRequired,
    contentWidth: PropTypes.number,
    detailPath: PropTypes.string.isRequired,
    isComment: PropTypes.bool,
    isPostBody: PropTypes.bool,
    isPostDetail: PropTypes.bool,
    isGridMode: PropTypes.bool.isRequired,
    isNotification: PropTypes.bool,
    shouldUseVideo: PropTypes.bool.isRequired,
  }

  static defaultProps = {
    asset: null,
    buyLinkURL: null,
    columnWidth: 0,
    commentOffset: 0,
    contentWidth: 0,
    isComment: false,
    isNotification: false,
    isPostBody: true,
    isPostDetail: false,
    isGridMode: false,
  }

  static contextTypes = {
    onTrackRelatedPostClick: PropTypes.func,
  }

  componentWillMount() {
    const { shouldUseVideo } = this.props

    this.state = {
      scale: null,
      currentImageHeight: null,
      currentImageWidth: null,
      measuredImageHeight: null,
      measuredImageWidth: null,
      lightBox: false,
      status: shouldUseVideo ? STATUS.SUCCESS : STATUS.REQUEST,
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    return !Immutable.is(nextProps.content, this.props.content) ||
      !Immutable.is(nextProps.asset, this.props.asset) ||
      ['buyLinkURL', 'columnWidth', 'contentWidth', 'isGridMode'].some(prop =>
        nextProps[prop] !== this.props[prop],
      ) ||
      ['scale', 'currentImageHeight', 'currentImageWidth', 'lightBox', 'status'].some(prop => nextState[prop] !== this.state[prop])
  }

  onClickStaticImageRegion = (event) => {
    console.log(event.target.classList.contains('ElloBuyButton'))
    const { lightBox } = this.state
    const { isPostBody, isPostDetail, isGridMode } = this.props
    const buyButtonClick = event.target.classList.contains('ElloBuyButton')

    if (isPostBody && !buyButtonClick && (isPostDetail || !isGridMode)) {
      if (lightBox) {
        return this.resetImageScale()
      }
      return this.setImageScale()
    }
    return null
  }

  onLoadSuccess = (img) => {
    if (this.isBasicAttachment()) {
      const dimensions = this.getBasicAttachmentDimensions(img)
      this.setState({ width: dimensions.width, height: dimensions.height })
    }
    this.setState({ status: STATUS.SUCCESS })
  }

  onLoadFailure = () => {
    this.setState({ status: STATUS.FAILURE })
  }

  getAttachmentMetadata() {
    if (!this.attachment || this.isBasicAttachment()) { return null }
    const optimized = this.attachment.get('optimized')
    const xhdpi = this.attachment.get('xhdpi')
    const hdpi = this.attachment.get('hdpi')
    let width = null
    let height = null

    // Todo: Not sure if we need to calculate hdpi or if xhdpi will work
    if (optimized.getIn(['metadata', 'width'])) {
      width = Number(optimized.getIn(['metadata', 'width']))
      height = Number(optimized.getIn(['metadata', 'height']))
    } else if (xhdpi.getIn(['metadata', 'width'])) {
      width = Number(xhdpi.getIn(['metadata', 'width']))
      height = Number(xhdpi.getIn(['metadata', 'height']))
    } else if (hdpi.getIn(['metadata', 'width'])) {
      width = Number(hdpi.getIn(['metadata', 'width']))
      height = Number(hdpi.getIn(['metadata', 'height']))
    }
    return {
      width,
      height,
      ratio: width ? width / height : null,
    }
  }

  // Use the lowest of the size constraints to ensure we don't go askew, go
  // below 1:1 pixel density, or go above the desired grid cell height
  getImageDimensions(metadata = this.getAttachmentMetadata()) {
    if (!metadata) { return metadata }
    const { columnWidth, commentOffset, contentWidth, isGridMode, isComment } = this.props
    const { height, ratio } = metadata
    const allowableWidth = isGridMode ? columnWidth : contentWidth
    const widthOffset = isGridMode && isComment ? commentOffset : 0
    const calculatedWidth = allowableWidth - widthOffset
    const maxCellHeight = isGridMode ? 1200 : 7500
    const widthConstrainedRelativeHeight = Math.round(calculatedWidth * (1 / ratio))
    const hv = Math.min(widthConstrainedRelativeHeight, height, maxCellHeight)
    const wv = Math.round(hv * ratio)
    return {
      width: wv,
      height: hv,
      ratio,
    }
  }

  getBasicAttachmentDimensions(img) {
    const height = img.height
    const ratio = img.width / height
    return this.getImageDimensions({ height, ratio })
  }

  getImageSourceSet() {
    const { isGridMode } = this.props
    const images = []
    if (!this.isBasicAttachment()) {
      if (isGridMode) {
        images.push(`${this.attachment.getIn(['mdpi', 'url'])} 375w`)
        images.push(`${this.attachment.getIn(['hdpi', 'url'])} 1920w`)
      } else {
        images.push(`${this.attachment.getIn(['mdpi', 'url'])} 180w`)
        images.push(`${this.attachment.getIn(['hdpi', 'url'])} 750w`)
        images.push(`${this.attachment.getIn(['xhdpi', 'url'])} 1500w`)
        images.push(`${this.attachment.getIn(['optimized', 'url'])} 1920w`)
      }
    }
    return images.join(', ')
  }

  setImageScale() {
    const { measuredImageHeight, measuredImageWidth } = this.state

    const dimensions = this.getImageDimensions()
    let imageHeight = null
    let imageWidth = null

    if (dimensions) {
      imageHeight = dimensions.height
      imageWidth = dimensions.width
    } else {
      const { width, height } = this.state
      imageHeight = height
      imageWidth = width
    }

    const innerHeightPadded = (window.innerHeight - 80)
    const innerWidthPadded = (window.innerWidth - 80)

    const innerRatio = innerWidthPadded / innerHeightPadded
    const imageRatio = imageWidth / imageHeight

    let scale = null

    if (imageRatio < innerRatio) {
      scale = (innerHeightPadded / imageHeight)
    } else {
      scale = (innerWidthPadded / imageWidth)
    }

    this.setState({
      scale,
      currentImageHeight: measuredImageHeight,
      currentImageWidth: measuredImageWidth,
      lightBox: true,
    })

    Mousetrap.bind(SHORTCUT_KEYS.ESC, () => { this.resetImageScale() })
  }

  handleScreenDimensions = (measuredDimensions) => {
    if (measuredDimensions) {
      this.setState({
        measuredImageHeight: measuredDimensions.height,
        measuredImageWidth: measuredDimensions.width,
      })
    }
  }

  resetImageScale() {
    this.setState({
      scale: null,
      lightBox: false,
    })

    setTimeout(() => {
      this.setState({
        currentImageHeight: null,
        currentImageWidth: null,
      })
    }, 100)

    Mousetrap.unbind(SHORTCUT_KEYS.ESC)
  }

  isBasicAttachment() {
    const { asset } = this.props
    return !asset || !asset.get('attachment')
  }

  isGif() {
    return this.attachment.getIn(['optimized', 'metadata', 'type']) === 'image/gif'
  }

  renderGifAttachment() {
    const { content, isNotification, isPostBody, isPostDetail, isGridMode } = this.props
    const { scale } = this.state
    const dimensions = this.getImageDimensions()
    return (
      <ImageAsset
        alt={content.get('alt') ? content.get('alt').replace('.gif', '') : null}
        className="ImageAttachment"
        height={isNotification ? 'auto' : dimensions.height}
        onLoadFailure={this.onLoadFailure}
        onLoadSuccess={this.onLoadSuccess}
        role="presentation"
        isPostBody={isPostBody}
        isPostDetail={isPostDetail}
        isGridMode={isGridMode}
        src={this.attachment.getIn(['optimized', 'url'])}
        width={isNotification ? null : dimensions.width}
        style={{ transform: scale ? `scale(${scale})` : null }}
        onScreenDimensions={
          isPostBody && (isPostDetail || !isGridMode) ?
            ((measuredDimensions) => { this.handleScreenDimensions(measuredDimensions) }) :
            null
        }
      />
    )
  }

  renderImageAttachment() {
    const { content, isNotification, isPostBody, isPostDetail, isGridMode } = this.props
    const { scale } = this.state
    const srcset = this.getImageSourceSet()
    const dimensions = this.getImageDimensions()
    return (
      <ImageAsset
        alt={content.get('alt') ? content.get('alt').replace('.jpg', '') : null}
        className="ImageAttachment"
        height={isNotification ? 'auto' : dimensions.height}
        onLoadFailure={this.onLoadFailure}
        onLoadSuccess={this.onLoadSuccess}
        role="presentation"
        isPostBody={isPostBody}
        isPostDetail={isPostDetail}
        isGridMode={isGridMode}
        srcSet={srcset}
        src={this.attachment.getIn(['hdpi', 'url'])}
        width={isNotification ? null : dimensions.width}
        style={{ transform: scale ? `scale(${scale})` : null }}
        onScreenDimensions={
          isPostBody && (isPostDetail || !isGridMode) ?
            ((measuredDimensions) => { this.handleScreenDimensions(measuredDimensions) }) :
            null
        }
      />
    )
  }

  renderLegacyImageAttachment() {
    const { content, isNotification, isPostBody, isPostDetail, isGridMode } = this.props
    const attrs = { src: content.get('url') }
    const { scale, width, height } = this.state
    const stateDimensions = width ? { width, height } : {}
    if (isNotification) {
      attrs.height = 'auto'
    }
    return (
      <ImageAsset
        alt={content.get('alt') ? content.get('alt').replace('.jpg', '') : null}
        className="ImageAttachment"
        onLoadFailure={this.onLoadFailure}
        onLoadSuccess={this.onLoadSuccess}
        role="presentation"
        isPostBody={isPostBody}
        isPostDetail={isPostDetail}
        isGridMode={isGridMode}
        style={{ transform: scale ? `scale(${scale})` : null }}
        onScreenDimensions={
          isPostBody && (isPostDetail || !isGridMode) ?
            ((measuredDimensions) => { this.handleScreenDimensions(measuredDimensions) }) :
            null
        }
        {...stateDimensions}
        {...attrs}
      />
    )
  }

  renderVideoAttachment() {
    const { height, width } = this.getImageDimensions()
    return (
      <video
        autoPlay
        height={height}
        loop
        muted
        playsInline
        width={width}
      >
        <track kind="captions" />
        <source src={this.attachment.getIn(['video', 'url'])} />
      </video>
    )
  }

  renderAttachment() {
    const { asset, shouldUseVideo } = this.props
    if (!this.isBasicAttachment()) {
      this.attachment = asset.get('attachment')
      if (shouldUseVideo) {
        return this.renderVideoAttachment()
      } else if (this.isGif()) {
        return this.renderGifAttachment()
      }
      return this.renderImageAttachment()
    }
    return this.renderLegacyImageAttachment()
  }

  renderRegionAsLink() {
    const { buyLinkURL, detailPath } = this.props
    return (

        <Link to={detailPath} onClick={this.context.onTrackRelatedPostClick}>
          {this.renderAttachment()}
        </Link>
        {
          buyLinkURL && buyLinkURL.length ?
            <ElloBuyButton to={buyLinkURL} /> :
            null
        }

    )
  }

  renderRegionAsStatic() {
    const { lightBox } = this.state
    const { currentImageHeight, currentImageWidth } = this.state
    const { buyLinkURL } = this.props
    return (
      <div
        className={`${lightBox ? lightBoxImageStyle : lightBoxInactiveImageStyle}`}
        onClick={this.onClickStaticImageRegion}
        style={{ height: currentImageHeight, width: currentImageWidth }}
      >

          {
            lightBox ?
              <DismissButtonLGReverse /> :
              null
          }

              {this.renderAttachment()}
              {
                buyLinkURL && buyLinkURL.length && !lightBox ?
                  <ElloBuyButton to={buyLinkURL} /> :
                  null
              }

    )
  }

  render() {
    const { isGridMode, detailPath } = this.props
    const { status } = this.state
    const asLink = isGridMode && detailPath
    return (

        {asLink ? this.renderRegionAsLink() : this.renderRegionAsStatic()}

    )
  }
}

export default ImageRegion

<commit_msg>js - lightbox - remove console statement<commit_after>/* eslint-disable jsx-a11y/no-static-element-interactions */
import Immutable from 'immutable'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router'
import classNames from 'classnames'
import Mousetrap from 'mousetrap'
import ImageAsset from '../assets/ImageAsset'
import { ElloBuyButton } from '../editor/ElloBuyButton'
import { DismissButtonLGReverse } from '../buttons/Buttons'
import { SHORTCUT_KEYS } from '../../constants/application_types'
import { css, select } from '../../styles/jss'
import * as s from '../../styles/jso'

const STATUS = {
  PENDING: 'isPending',
  REQUEST: 'isRequesting',
  SUCCESS: null,
  FAILURE: 'isFailing',
}

const lightBoxInactiveImageStyle = css(
  s.inline,
  s.relative,
  s.center,
  s.bgcF2,
  select(
    '> .LightBoxMask',
    s.bgcTransparent,
    select(
      '> .LightBox',
      s.relative,
      s.alignTop,
      s.inline,
      select(
        '> .ImgHolder',
        s.relative,
        s.inlineBlock,
        select(
          '> .ImageAttachment',
          {
            transform: 'scale(1.0)',
          },
        ),
      ),
    ),
  ),
)

const lightBoxImageStyle = css(
  s.block,
  s.relative,
  s.bgcF2,
  { margin: '0 auto' },
  select(
    '> .LightBoxMask',
    s.fullscreen,
    s.fullWidth,
    s.fullHeight,
    s.bgcModal,
    s.zModal,
    { transition: `background-color 0.4s ${s.ease}` },
    select(
      '> .LightBox',
      s.relative,
      s.containedAlignMiddle,
      s.center,
      select(
        '> .ImageAttachment',
      ),
    ),
  ),
)

class ImageRegion extends Component {

  static propTypes = {
    asset: PropTypes.object,
    buyLinkURL: PropTypes.string,
    columnWidth: PropTypes.number,
    commentOffset: PropTypes.number,
    content: PropTypes.object.isRequired,
    contentWidth: PropTypes.number,
    detailPath: PropTypes.string.isRequired,
    isComment: PropTypes.bool,
    isPostBody: PropTypes.bool,
    isPostDetail: PropTypes.bool,
    isGridMode: PropTypes.bool.isRequired,
    isNotification: PropTypes.bool,
    shouldUseVideo: PropTypes.bool.isRequired,
  }

  static defaultProps = {
    asset: null,
    buyLinkURL: null,
    columnWidth: 0,
    commentOffset: 0,
    contentWidth: 0,
    isComment: false,
    isNotification: false,
    isPostBody: true,
    isPostDetail: false,
    isGridMode: false,
  }

  static contextTypes = {
    onTrackRelatedPostClick: PropTypes.func,
  }

  componentWillMount() {
    const { shouldUseVideo } = this.props

    this.state = {
      scale: null,
      currentImageHeight: null,
      currentImageWidth: null,
      measuredImageHeight: null,
      measuredImageWidth: null,
      lightBox: false,
      status: shouldUseVideo ? STATUS.SUCCESS : STATUS.REQUEST,
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    return !Immutable.is(nextProps.content, this.props.content) ||
      !Immutable.is(nextProps.asset, this.props.asset) ||
      ['buyLinkURL', 'columnWidth', 'contentWidth', 'isGridMode'].some(prop =>
        nextProps[prop] !== this.props[prop],
      ) ||
      ['scale', 'currentImageHeight', 'currentImageWidth', 'lightBox', 'status'].some(prop => nextState[prop] !== this.state[prop])
  }

  onClickStaticImageRegion = (event) => {
    const { lightBox } = this.state
    const { isPostBody, isPostDetail, isGridMode } = this.props
    const buyButtonClick = event.target.classList.contains('ElloBuyButton')

    if (isPostBody && !buyButtonClick && (isPostDetail || !isGridMode)) {
      if (lightBox) {
        return this.resetImageScale()
      }
      return this.setImageScale()
    }
    return null
  }

  onLoadSuccess = (img) => {
    if (this.isBasicAttachment()) {
      const dimensions = this.getBasicAttachmentDimensions(img)
      this.setState({ width: dimensions.width, height: dimensions.height })
    }
    this.setState({ status: STATUS.SUCCESS })
  }

  onLoadFailure = () => {
    this.setState({ status: STATUS.FAILURE })
  }

  getAttachmentMetadata() {
    if (!this.attachment || this.isBasicAttachment()) { return null }
    const optimized = this.attachment.get('optimized')
    const xhdpi = this.attachment.get('xhdpi')
    const hdpi = this.attachment.get('hdpi')
    let width = null
    let height = null

    // Todo: Not sure if we need to calculate hdpi or if xhdpi will work
    if (optimized.getIn(['metadata', 'width'])) {
      width = Number(optimized.getIn(['metadata', 'width']))
      height = Number(optimized.getIn(['metadata', 'height']))
    } else if (xhdpi.getIn(['metadata', 'width'])) {
      width = Number(xhdpi.getIn(['metadata', 'width']))
      height = Number(xhdpi.getIn(['metadata', 'height']))
    } else if (hdpi.getIn(['metadata', 'width'])) {
      width = Number(hdpi.getIn(['metadata', 'width']))
      height = Number(hdpi.getIn(['metadata', 'height']))
    }
    return {
      width,
      height,
      ratio: width ? width / height : null,
    }
  }

  // Use the lowest of the size constraints to ensure we don't go askew, go
  // below 1:1 pixel density, or go above the desired grid cell height
  getImageDimensions(metadata = this.getAttachmentMetadata()) {
    if (!metadata) { return metadata }
    const { columnWidth, commentOffset, contentWidth, isGridMode, isComment } = this.props
    const { height, ratio } = metadata
    const allowableWidth = isGridMode ? columnWidth : contentWidth
    const widthOffset = isGridMode && isComment ? commentOffset : 0
    const calculatedWidth = allowableWidth - widthOffset
    const maxCellHeight = isGridMode ? 1200 : 7500
    const widthConstrainedRelativeHeight = Math.round(calculatedWidth * (1 / ratio))
    const hv = Math.min(widthConstrainedRelativeHeight, height, maxCellHeight)
    const wv = Math.round(hv * ratio)
    return {
      width: wv,
      height: hv,
      ratio,
    }
  }

  getBasicAttachmentDimensions(img) {
    const height = img.height
    const ratio = img.width / height
    return this.getImageDimensions({ height, ratio })
  }

  getImageSourceSet() {
    const { isGridMode } = this.props
    const images = []
    if (!this.isBasicAttachment()) {
      if (isGridMode) {
        images.push(`${this.attachment.getIn(['mdpi', 'url'])} 375w`)
        images.push(`${this.attachment.getIn(['hdpi', 'url'])} 1920w`)
      } else {
        images.push(`${this.attachment.getIn(['mdpi', 'url'])} 180w`)
        images.push(`${this.attachment.getIn(['hdpi', 'url'])} 750w`)
        images.push(`${this.attachment.getIn(['xhdpi', 'url'])} 1500w`)
        images.push(`${this.attachment.getIn(['optimized', 'url'])} 1920w`)
      }
    }
    return images.join(', ')
  }

  setImageScale() {
    const { measuredImageHeight, measuredImageWidth } = this.state

    const dimensions = this.getImageDimensions()
    let imageHeight = null
    let imageWidth = null

    if (dimensions) {
      imageHeight = dimensions.height
      imageWidth = dimensions.width
    } else {
      const { width, height } = this.state
      imageHeight = height
      imageWidth = width
    }

    const innerHeightPadded = (window.innerHeight - 80)
    const innerWidthPadded = (window.innerWidth - 80)

    const innerRatio = innerWidthPadded / innerHeightPadded
    const imageRatio = imageWidth / imageHeight

    let scale = null

    if (imageRatio < innerRatio) {
      scale = (innerHeightPadded / imageHeight)
    } else {
      scale = (innerWidthPadded / imageWidth)
    }

    this.setState({
      scale,
      currentImageHeight: measuredImageHeight,
      currentImageWidth: measuredImageWidth,
      lightBox: true,
    })

    Mousetrap.bind(SHORTCUT_KEYS.ESC, () => { this.resetImageScale() })
  }

  handleScreenDimensions = (measuredDimensions) => {
    if (measuredDimensions) {
      this.setState({
        measuredImageHeight: measuredDimensions.height,
        measuredImageWidth: measuredDimensions.width,
      })
    }
  }

  resetImageScale() {
    this.setState({
      scale: null,
      lightBox: false,
    })

    setTimeout(() => {
      this.setState({
        currentImageHeight: null,
        currentImageWidth: null,
      })
    }, 100)

    Mousetrap.unbind(SHORTCUT_KEYS.ESC)
  }

  isBasicAttachment() {
    const { asset } = this.props
    return !asset || !asset.get('attachment')
  }

  isGif() {
    return this.attachment.getIn(['optimized', 'metadata', 'type']) === 'image/gif'
  }

  renderGifAttachment() {
    const { content, isNotification, isPostBody, isPostDetail, isGridMode } = this.props
    const { scale } = this.state
    const dimensions = this.getImageDimensions()
    return (
      <ImageAsset
        alt={content.get('alt') ? content.get('alt').replace('.gif', '') : null}
        className="ImageAttachment"
        height={isNotification ? 'auto' : dimensions.height}
        onLoadFailure={this.onLoadFailure}
        onLoadSuccess={this.onLoadSuccess}
        role="presentation"
        isPostBody={isPostBody}
        isPostDetail={isPostDetail}
        isGridMode={isGridMode}
        src={this.attachment.getIn(['optimized', 'url'])}
        width={isNotification ? null : dimensions.width}
        style={{ transform: scale ? `scale(${scale})` : null }}
        onScreenDimensions={
          isPostBody && (isPostDetail || !isGridMode) ?
            ((measuredDimensions) => { this.handleScreenDimensions(measuredDimensions) }) :
            null
        }
      />
    )
  }

  renderImageAttachment() {
    const { content, isNotification, isPostBody, isPostDetail, isGridMode } = this.props
    const { scale } = this.state
    const srcset = this.getImageSourceSet()
    const dimensions = this.getImageDimensions()
    return (
      <ImageAsset
        alt={content.get('alt') ? content.get('alt').replace('.jpg', '') : null}
        className="ImageAttachment"
        height={isNotification ? 'auto' : dimensions.height}
        onLoadFailure={this.onLoadFailure}
        onLoadSuccess={this.onLoadSuccess}
        role="presentation"
        isPostBody={isPostBody}
        isPostDetail={isPostDetail}
        isGridMode={isGridMode}
        srcSet={srcset}
        src={this.attachment.getIn(['hdpi', 'url'])}
        width={isNotification ? null : dimensions.width}
        style={{ transform: scale ? `scale(${scale})` : null }}
        onScreenDimensions={
          isPostBody && (isPostDetail || !isGridMode) ?
            ((measuredDimensions) => { this.handleScreenDimensions(measuredDimensions) }) :
            null
        }
      />
    )
  }

  renderLegacyImageAttachment() {
    const { content, isNotification, isPostBody, isPostDetail, isGridMode } = this.props
    const attrs = { src: content.get('url') }
    const { scale, width, height } = this.state
    const stateDimensions = width ? { width, height } : {}
    if (isNotification) {
      attrs.height = 'auto'
    }
    return (
      <ImageAsset
        alt={content.get('alt') ? content.get('alt').replace('.jpg', '') : null}
        className="ImageAttachment"
        onLoadFailure={this.onLoadFailure}
        onLoadSuccess={this.onLoadSuccess}
        role="presentation"
        isPostBody={isPostBody}
        isPostDetail={isPostDetail}
        isGridMode={isGridMode}
        style={{ transform: scale ? `scale(${scale})` : null }}
        onScreenDimensions={
          isPostBody && (isPostDetail || !isGridMode) ?
            ((measuredDimensions) => { this.handleScreenDimensions(measuredDimensions) }) :
            null
        }
        {...stateDimensions}
        {...attrs}
      />
    )
  }

  renderVideoAttachment() {
    const { height, width } = this.getImageDimensions()
    return (
      <video
        autoPlay
        height={height}
        loop
        muted
        playsInline
        width={width}
      >
        <track kind="captions" />
        <source src={this.attachment.getIn(['video', 'url'])} />
      </video>
    )
  }

  renderAttachment() {
    const { asset, shouldUseVideo } = this.props
    if (!this.isBasicAttachment()) {
      this.attachment = asset.get('attachment')
      if (shouldUseVideo) {
        return this.renderVideoAttachment()
      } else if (this.isGif()) {
        return this.renderGifAttachment()
      }
      return this.renderImageAttachment()
    }
    return this.renderLegacyImageAttachment()
  }

  renderRegionAsLink() {
    const { buyLinkURL, detailPath } = this.props
    return (

        <Link to={detailPath} onClick={this.context.onTrackRelatedPostClick}>
          {this.renderAttachment()}
        </Link>
        {
          buyLinkURL && buyLinkURL.length ?
            <ElloBuyButton to={buyLinkURL} /> :
            null
        }

    )
  }

  renderRegionAsStatic() {
    const { lightBox } = this.state
    const { currentImageHeight, currentImageWidth } = this.state
    const { buyLinkURL } = this.props
    return (
      <div
        className={`${lightBox ? lightBoxImageStyle : lightBoxInactiveImageStyle}`}
        onClick={this.onClickStaticImageRegion}
        style={{ height: currentImageHeight, width: currentImageWidth }}
      >

          {
            lightBox ?
              <DismissButtonLGReverse /> :
              null
          }

              {this.renderAttachment()}
              {
                buyLinkURL && buyLinkURL.length && !lightBox ?
                  <ElloBuyButton to={buyLinkURL} /> :
                  null
              }

    )
  }

  render() {
    const { isGridMode, detailPath } = this.props
    const { status } = this.state
    const asLink = isGridMode && detailPath
    return (

        {asLink ? this.renderRegionAsLink() : this.renderRegionAsStatic()}

    )
  }
}

export default ImageRegion

<|endoftext|>


<commit_before>// @flow
import React, { PropTypes } from "react";
import Svg from "../Svg";
import "./Close.css";

type CloseButtonType = {
  handleClick: any,
  buttonClass?: string,
  tooltip?: string
};

function CloseButton({ handleClick, buttonClass, tooltip }: CloseButtonType) {
  return (
    <div
      className={buttonClass ? `close-btn ${buttonClass}` : "close-btn"}
      onClick={handleClick}
      title={tooltip}
    >
      <Svg name="close" />
    </div>
  );
}

CloseButton.propTypes = {
  handleClick: PropTypes.func.isRequired
};

export default CloseButton;
<commit_msg>Switch Close Button from PropType to Flow Props (#4166)<commit_after>// @flow
import React from "react";
import Svg from "../Svg";
import "./Close.css";

type Props = {
  handleClick: Function,
  buttonClass?: string,
  tooltip?: string
};

function CloseButton({ handleClick, buttonClass, tooltip }: Props) {
  return (
    <div
      className={buttonClass ? `close-btn ${buttonClass}` : "close-btn"}
      onClick={handleClick}
      title={tooltip}
    >
      <Svg name="close" />
    </div>
  );
}

export default CloseButton;
<|endoftext|>


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

    angular
        .module('app.dashboard')
        .controller('Dashboard', Dashboard);

    function Dashboard(dataservice) {
    	var vm = this;
    	vm.ranks = [];
        vm.model = [];
        vm.chartData = {}

        activate();
        function activate() {
            var promises = [
                getHighestRanks(),
                getMatchdayByWeekNmr(),
                getFiveBigTeamData()
            ];

            return dataservice.ready(promises).then(function(result){
            	vm.ranks = result[0];
                vm.model = result[1];

                vm.chartData.categories = result[2].categories;
                vm.chartData.series = result[2].series;

                initChart();
            });
        }

        function initChart(){
            $('#epl-chart-container').highcharts({
                title: {
                    text: 'Five Biggest Teams',
                    style: {
                        display: 'none'
                    }
                },
                xAxis: {
                    title: {
                        text: 'Week'
                    },
                    categories: vm.chartData.categories
                },
                yAxis: {
                    title: {
                        text: 'Point'
                    },
                    plotLines: [{
                        value: 0,
                        width: 1,
                        color: '#808080'
                    }]
                },
                tooltip: {
                    valueSuffix: ' Pts'
                },
                legend: {
                    layout: 'horizontal',

                    verticalAlign: 'top',
                    borderWidth: 0
                },
                series: vm.chartData.series
            });
        }

        // Get chart data through service
        function getFiveBigTeamData() {
            return dataservice.getFiveBigTeamData().then(function(data) {
                return data;
            });
        }

        // Get ranks through service
        function getHighestRanks() {
            return dataservice.getHighestRanks().then(function(data) {
                return data.ranks;
            });
        }

        // Get matchday through service
        function getMatchdayByWeekNmr() {
            return dataservice.getMatchdayByWeekNmr().then(function(data) {
                return data.model;
            });
        }
    }

})();
<commit_msg>remove exporting button<commit_after>(function() {
    'use strict';

    angular
        .module('app.dashboard')
        .controller('Dashboard', Dashboard);

    function Dashboard(dataservice) {
    	var vm = this;
    	vm.ranks = [];
        vm.model = [];
        vm.chartData = {}

        activate();
        function activate() {
            var promises = [
                getHighestRanks(),
                getMatchdayByWeekNmr(),
                getFiveBigTeamData()
            ];

            return dataservice.ready(promises).then(function(result){
            	vm.ranks = result[0];
                vm.model = result[1];

                vm.chartData.categories = result[2].categories;
                vm.chartData.series = result[2].series;

                initChart();
            });
        }

        function initChart(){
            $('#epl-chart-container').highcharts({
                series: vm.chartData.series,
                title: {
                    text: 'Five Biggest Teams',
                    style: {
                        display: 'none'
                    }
                },
                xAxis: {
                    title: {
                        text: 'Week'
                    },
                    categories: vm.chartData.categories
                },
                yAxis: {
                    title: {
                        text: 'Point'
                    },
                    plotLines: [{
                        value: 0,
                        width: 1,
                        color: '#808080'
                    }]
                },
                tooltip: {
                    valueSuffix: ' Pts'
                },
                legend: {
                    layout: 'horizontal',

                    verticalAlign: 'top',
                    borderWidth: 0
                },
                exporting: { enabled: false }
            });
        }

        // Get chart data through service
        function getFiveBigTeamData() {
            return dataservice.getFiveBigTeamData().then(function(data) {
                return data;
            });
        }

        // Get ranks through service
        function getHighestRanks() {
            return dataservice.getHighestRanks().then(function(data) {
                return data.ranks;
            });
        }

        // Get matchday through service
        function getMatchdayByWeekNmr() {
            return dataservice.getMatchdayByWeekNmr().then(function(data) {
                return data.model;
            });
        }
    }

})();
<|endoftext|>


<commit_before>/*eslint-env node*/

const path = require('path');
const express = require('express');
const morgan = require('morgan');
const proxy = require('http-proxy-middleware');

const webpack = require('webpack');
const webpackMiddleware = require('webpack-dev-middleware');
const WEBPACK_CONFIG = require('../webpack.config');

const argv = require('minimist')(process.argv.slice(2));

const PORT = argv.port || 8000;
const HOST = argv.host || 'localhost';
const API_HOST = argv.apihost || 'localhost';
const API_PORT = argv.apiport || process.env.BC_GOV_SCHOOLBUS_API_PORT || 8080;

const PROJECT_ROOT = path.join(__dirname, '..');
const DIST_PATH = path.join(PROJECT_ROOT, 'dist');

const app = express();

app.use(morgan('dev'));

// TODO: Remove - just for testing
var count = 0;
app.get('/api/test', function(req, res) {
  res.status(200);
  count++;
  var newCount = count;
  setTimeout(function() {
    res.send(JSON.stringify({ count: newCount })).end();
  }, Math.random() * 10 * 1000);
});

app.use('/api', proxy({
  target: `https://${API_HOST}:${API_PORT}/schoolbus-tbd/api`,
  changeOrigin: true,
}));

// Override WebPack config to work with this express server
WEBPACK_CONFIG.output.path = '/';
WEBPACK_CONFIG.output.publicPath = '/js/';

const compiler = webpack(WEBPACK_CONFIG);
const middleware = webpackMiddleware(compiler, {
  publicPath: WEBPACK_CONFIG.output.publicPath,
  contentBase: 'src',
  stats: {
    colors: true,
    hash: false,
    timings: true,
    chunks: false,
    chunkModules: false,
    modules: false,
  },
});
app.use(require('webpack-hot-middleware')(compiler));

app.use(middleware);

app.use(express.static(DIST_PATH));

app.use('/test', express.static(PROJECT_ROOT + '/test'));
app.use('/node_modules', express.static(PROJECT_ROOT + '/node_modules'));

app.listen(PORT, function () {
  console.log('\uD83C\uDF0E   Dev web server initialized http://' + HOST + ':' + PORT);
});
<commit_msg>SB-64 Added Dev API endpoint.<commit_after>/*eslint-env node*/

const path = require('path');
const express = require('express');
const morgan = require('morgan');
const proxy = require('http-proxy-middleware');

const webpack = require('webpack');
const webpackMiddleware = require('webpack-dev-middleware');
const WEBPACK_CONFIG = require('../webpack.config');

const argv = require('minimist')(process.argv.slice(2));

const PORT = argv.port || 8000;
const HOST = argv.host || 'localhost';
const API_HOST = argv.apihost || 'server-tran-schoolbus-dev.pathfinder.gov.bc.ca';
const API_PORT = argv.apiport || process.env.BC_GOV_SCHOOLBUS_API_PORT || 80;

const PROJECT_ROOT = path.join(__dirname, '..');
const DIST_PATH = path.join(PROJECT_ROOT, 'dist');

const app = express();

app.use(morgan('dev'));

// TODO: Remove - just for testing
var count = 0;
app.get('/api/test', function(req, res) {
  res.status(200);
  count++;
  var newCount = count;
  setTimeout(function() {
    res.send(JSON.stringify({ count: newCount })).end();
  }, Math.random() * 10 * 1000);
});

app.use('/api', proxy({
  target: `http://${API_HOST}:${API_PORT}/api`,
  changeOrigin: true,
  logLevel: 'debug',
}));

// Override WebPack config to work with this express server
WEBPACK_CONFIG.output.path = '/';
WEBPACK_CONFIG.output.publicPath = '/js/';

const compiler = webpack(WEBPACK_CONFIG);
const middleware = webpackMiddleware(compiler, {
  publicPath: WEBPACK_CONFIG.output.publicPath,
  contentBase: 'src',
  stats: {
    colors: true,
    hash: false,
    timings: true,
    chunks: false,
    chunkModules: false,
    modules: false,
  },
});
app.use(require('webpack-hot-middleware')(compiler));

app.use(middleware);

app.use(express.static(DIST_PATH));

app.use('/test', express.static(PROJECT_ROOT + '/test'));
app.use('/node_modules', express.static(PROJECT_ROOT + '/node_modules'));

app.listen(PORT, function () {
  console.log('\uD83C\uDF0E   Dev web server initialized http://' + HOST + ':' + PORT);
});
<|endoftext|>


<commit_before>/*

generatePEG.js - generate PEG parser from textual grammar

The MIT License (MIT)

Copyright (c) 2015 Dale Schumacher

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

*/
"use strict";

var tart = require('tart-tracing');
var tracing = tart.tracing();
var sponsor = tracing.sponsor;
/*
var tart = require('tart');
var sponsor = tart.minimal({
    fail: function (e) { console.log('ERROR!', e); }
});
*/
var stream = require('../stream.js');
var input = require('../input.js');

var log = console.log;
//var log = function () {};

var PEG = require('../PEG.js');

/*
var pf = PEG.factory(sponsor);
var ns = pf.namespace(log);
ns.define('Grammar',
    pf.star(
        pf.any
    )
);
*/
var ns = require('../grammar.js').build(sponsor/*, log*/);
require('../reducePEG.js').transform(ns);

/*
*/
var allSource = ''
+ 'ALL <- .*\n';
var simpleSource = ''
+ '\r\n# comment\n';
var objectSource = ''
+ 'IGNORE <- { type:\'name\', value:\'_\' }';
var stringSource = ''
+ 'STRING <- \'One\' "Two" Three [Four] [Five]+ [Six]*';
var commentSource = ''
+ 'Comment <- [#] (!EOL .)* EOL\r'
+ "EOL <- '\\n'\n"
+ '     / "\\r" "\\n"?\r\n';
var exprSource = ''
+ 'Assign <- Name "=" Assign\n'
+ '        / Expr\n'
+ 'Name   <- [a-zA-Z]\n'
+ 'Expr   <- Term ([-+] Term)*\n'
+ 'Term   <- Factor ([/*] Factor)*\n'
+ 'Factor <- "(" Assign ")"\n'
+ '        / Name\n'
+ '        / [0-9]+\n';
//var fileSource = require('fs').readFileSync('grammar.peg', 'utf8');
var fileSource = require('fs').readFileSync('examples/LISP.peg', 'utf8');
var source = fileSource; //allSource;

var cs = stream.characters(true);
/*
*/
var next = input.fromReadable(sponsor,
    cs.pipe(stream.countRowCol()));
cs.end(source);
/*
process.stdin.setEncoding('utf8');
var next = input.fromReadable(sponsor,
    process.stdin.pipe(cs).pipe(stream.countRowCol()));
*/

var ok = sponsor(function okBeh(m) {
    log('OK:', JSON.stringify(m, null, '  '));
    process.stdout.write(
        require('../generate.js').text(m.value, 2, cs.allCharacters)
    );
});
var fail = sponsor(function failBeh(m) {
    console.log('FAIL:', JSON.stringify(m, null, '  '));
});

var start = sponsor(ns.lookup('Grammar'));
var matcher = sponsor(PEG.start(start, ok, fail));
next(matcher);

require('../fixture.js').asyncRepeat(3,
    function eventLoop() {
        return tracing.eventLoop({
//            count: 10000,
//            log: function (effect) { console.log('DEBUG', effect); },
            fail: function (error) { console.log('FAIL!', error); }
        });
    }
);
<commit_msg>Re-connect to stdin (intermittent failure)<commit_after>/*

generatePEG.js - generate PEG parser from textual grammar

The MIT License (MIT)

Copyright (c) 2015 Dale Schumacher

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

*/
"use strict";

var tart = require('tart-tracing');
var tracing = tart.tracing();
var sponsor = tracing.sponsor;
/*
var tart = require('tart');
var sponsor = tart.minimal({
    fail: function (e) { console.log('ERROR!', e); }
});
*/
var stream = require('../stream.js');
var input = require('../input.js');

//var log = console.log;
var log = function () {};

var PEG = require('../PEG.js');

/*
var pf = PEG.factory(sponsor);
var ns = pf.namespace(log);
ns.define('Grammar',
    pf.star(
        pf.any
    )
);
*/
var ns = require('../grammar.js').build(sponsor/*, log*/);
require('../reducePEG.js').transform(ns);

/*
var allSource = ''
+ 'ALL <- .*\n';
var simpleSource = ''
+ '\r\n# comment\n';
var objectSource = ''
+ 'IGNORE <- { type:\'name\', value:\'_\' }';
var stringSource = ''
+ 'STRING <- \'One\' "Two" Three [Four] [Five]+ [Six]*';
var commentSource = ''
+ 'Comment <- [#] (!EOL .)* EOL\r'
+ "EOL <- '\\n'\n"
+ '     / "\\r" "\\n"?\r\n';
var exprSource = ''
+ 'Assign <- Name "=" Assign\n'
+ '        / Expr\n'
+ 'Name   <- [a-zA-Z]\n'
+ 'Expr   <- Term ([-+] Term)*\n'
+ 'Term   <- Factor ([/*] Factor)*\n'
+ 'Factor <- "(" Assign ")"\n'
+ '        / Name\n'
+ '        / [0-9]+\n';
//var fileSource = require('fs').readFileSync('grammar.peg', 'utf8');
var fileSource = require('fs').readFileSync('examples/LISP.peg', 'utf8');
var source = fileSource; //allSource;
*/

var cs = stream.characters(true);
/*
var next = input.fromReadable(sponsor,
    cs.pipe(stream.countRowCol()));
cs.end(source);
*/
process.stdin.setEncoding('utf8');
var next = input.fromReadable(sponsor,
    process.stdin.pipe(cs).pipe(stream.countRowCol()));
/*
*/

var ok = sponsor(function okBeh(m) {
    log('OK:', JSON.stringify(m, null, '  '));
    process.stdout.write(
        require('../generate.js').text(m.value, 2, cs.allCharacters)
    );
});
var fail = sponsor(function failBeh(m) {
    console.log('FAIL:', JSON.stringify(m, null, '  '));
});

var start = sponsor(ns.lookup('Grammar'));
var matcher = sponsor(PEG.start(start, ok, fail));
next(matcher);

require('../fixture.js').asyncRepeat(3,
    function eventLoop() {
        return tracing.eventLoop({
//            count: 10000,
//            log: function (effect) { console.log('DEBUG', effect); },
            fail: function (error) { console.log('FAIL!', error); }
        });
    }
);
<|endoftext|>


<commit_before>// Define actions concerning snek here

export const doSomething = (payload) => {
  return {
    type: 'DO_SOMETHING',
    payload,
  };
};
<commit_msg>return state outside switch statement<commit_after>// Define actions concerning snek here

export const doSomething = (payload) => {
  return {
    type: 'DO_SOMETHING',
    payload,
  };
};<|endoftext|>


<commit_before>var gulp = require('gulp');
var resemble = require('node-resemble-js');
var paths = require('../util/paths');
var fs = require('fs');
var path = require('path');
var _ = require('underscore');

gulp.task('compare', function (done) {
  var compareConfig = JSON.parse(fs.readFileSync(paths.compareConfigFileName, 'utf8'));

  function updateProgress() {
    var results = {};
    _.each(compareConfig.testPairs, function (pair) {
      if (!results[pair.testStatus]) {
        results[pair.testStatus] = 0;
      }
      !results[pair.testStatus]++;
    });
    if (!results.running){
      console.log ("\nTest completed...")
      console.log ((results.pass || 0) + " Passed")
      console.log ((results.fail || 0) + " Failed\n")

      if (results.fail) {
        console.log ("*** Mismatch errors found ***")
        console.log ("For a detailed report run `gulp openReport`\n")
        if (paths.cliExitOnFail) {
          done(new Error('Mismatch errors found.'));
        }
      } else {
        done();
      }

    }
  }

  _.each(compareConfig.testPairs, function (pair) {
    pair.testStatus = "running";

    var referencePath = path.join(paths.backstop, pair.reference);
    var testPath = path.join(paths.backstop, pair.test);

    resemble(referencePath).compareTo(testPath).onComplete(function(data) {
      var imageComparisonFailed = !data.isSameDimensions || data.misMatchPercentage > pair.misMatchThreshold;

      if (imageComparisonFailed) {
        pair.testStatus = "fail";
        console.log('ERROR:', pair.label, pair.fileName);
      } else {
        pair.testStatus = "pass";
        console.log('OK:', pair.label, pair.fileName);
      }
      updateProgress();
    });
  });
});
<commit_msg>Saves image-diffs when using the CLI reporter #121<commit_after>var gulp = require('gulp');
var resemble = require('node-resemble-js');
var paths = require('../util/paths');
var fs = require('fs');
var path = require('path');
var _ = require('underscore');

gulp.task('compare', function (done) {
  var compareConfig = JSON.parse(fs.readFileSync(paths.compareConfigFileName, 'utf8'));

  function updateProgress() {
    var results = {};
    _.each(compareConfig.testPairs, function (pair) {
      if (!results[pair.testStatus]) {
        results[pair.testStatus] = 0;
      }
      !results[pair.testStatus]++;
    });
    if (!results.running) {
      console.log ("\nTest completed...");
      console.log ((results.pass || 0) + " Passed");
      console.log ((results.fail || 0) + " Failed\n");

      if (results.fail) {
        console.log ("*** Mismatch errors found ***");
        console.log ("For a detailed report run `gulp openReport`\n");
        if (paths.cliExitOnFail) {
          done(new Error('Mismatch errors found.'));
        }
      } else {
        done();
      }

    }
  }

  _.each(compareConfig.testPairs, function (pair) {
    pair.testStatus = "running";

    var referencePath = path.join(paths.backstop, pair.reference);
    var testPath = path.join(paths.backstop, pair.test);

    resemble(referencePath).compareTo(testPath).onComplete(function (data) {
      var imageComparisonFailed = !data.isSameDimensions || data.misMatchPercentage > pair.misMatchThreshold;

      if (imageComparisonFailed) {
        pair.testStatus = "fail";
        console.log('ERROR:', pair.label, pair.fileName);
        storeFailedDiffImage(testPath, data);
      } else {
        pair.testStatus = "pass";
        console.log('OK:', pair.label, pair.fileName);
      }
      updateProgress();
    });
  });

  function storeFailedDiffImage(testPath, data) {
    var failedDiffFilename = getFailedDiffFilename(testPath);
    console.log('Storing diff image in ', failedDiffFilename);
    var failedDiffStream = fs.createWriteStream(failedDiffFilename);
    data.getDiffImage().pack().pipe(failedDiffStream)
  }

  function getFailedDiffFilename(testPath) {
    var lastSlash = testPath.lastIndexOf('/');
    return testPath.slice(0, lastSlash + 1) + 'failed_diff_' + testPath.slice(lastSlash + 1, testPath.length);
  }
});
<|endoftext|>