<commit_before>;(function(Hyphen, $, undefined){

    // On load
	$(document).ready(function(){

		/* Table initialisation */
        // Changing the columns is painful with this config, so we have an object allowing us to deal with that
        var columns = {
            name:0
            ,status:1
            ,prefixes:2
            ,creation_date_formatted:3
            ,last_modification_date_formatted:4
            ,actions:5
            ,id:6
            ,creation_date_unformatted:7
            ,last_modification_date_unformatted:8
            ,searchable:9
        }

        Hyphen.integration.initDataTables()
		$('.dataTable').dataTable( {
			"sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>"
			,"sPaginationType": "bootstrap"
			,"oLanguage": {
				"sLengthMenu": '_MENU_ web entities at once',
				"sZeroRecords": 'Nothing found - sorry',
	            "sInfo": 'Showing _START_ to _END_ of _TOTAL_ records',
        		"sInfoEmpty": 'Showing 0 to 0 of 0 records',
        		"sInfoFiltered": '(filtered from _MAX_ total records)'
			}
            ,"fnDrawCallback": function( oSettings ) {
                // Update the web entities proxies
                Hyphen.view.webEntities.proxiesUpdate(true)
            }
            ,"aaSorting": [[ columns.last_modification_date_formatted, "asc" ]]
            ,"aoColumnDefs": [
                {
                    "mRender": function ( data, type, row ) {

                        return $('
').append(
                            $('').text(data)
                                .addClass('webEntity_proxy')
                                .attr('webEntity_id', row[columns.id])
                        ).html()
                    },
                    "aTargets": [ columns.name ]
                }
                ,{
                    "mRender": function ( data, type, row ) {

                        return $('
').append(
                            $('').text(data)
                                .addClass(Hyphen.view.webEntities_status_getLabelColor(data))
                        ).html()
                    },
                    "aTargets": [ columns.status ]
                }
                ,{
                    "mRender": function ( data, type, row ) {
                        return $('
').append(
                            $('
').append(
                                data.map(function(lru_prefix){
                                    var url = Hyphen.utils.LRU_to_URL(lru_prefix)
                                    return $('
').append(
                                        $('').append(
                                            $('')
                                                .attr('href', url)
                                                .attr('target', '_blank')
                                                .text(Hyphen.utils.URL_simplify(url))
                                        )
                                    )
                                })
                            )
                        ).html()
                    },
                    "aTargets": [ columns.prefixes ]
                }
                ,{
                    "mRender": function ( data, type, row ) {
                        var date = new Date()
                        date.setTime(data)
                        return $('
').append(
                            $('').text(Hyphen.utils.prettyDate(date))
                                .attr('title', date)
                        ).html()
                    },
                    "aTargets": [ columns.creation_date_formatted, columns.last_modification_date_formatted ]
                }
                ,{
                    "mRender": function ( data, type, row ) {
                        return '

'
                    },
                    "aTargets": [ columns.actions ]
                }
                ,{ "iDataSort": columns.creation_date_unformatted, "aTargets": [ columns.creation_date_formatted ] }
                ,{ "iDataSort": columns.last_modification_date_unformatted, "aTargets": [ columns.last_modification_date_formatted ] }
                ,{ "bVisible": false,  "aTargets": [ columns.searchable, columns.creation_date_unformatted, columns.last_modification_date_unformatted, columns.id ] }
                ,{ "sClass": "center", "aTargets": [ columns.actions ] }
                ,{ "bSearchable": false, "aTargets": [ columns.prefixes, columns.creation_date_formatted, columns.last_modification_date_formatted, columns.actions ] }
                ,{ "bSortable": false, "aTargets": [ columns.prefixes, columns.actions, columns.searchable ] }
                ,{ "sWidth": "80px", "aTargets": [ columns.actions ] }
                ,{ "sWidth": "80px", "aTargets": [ columns.status ] }
                ,{ "sWidth": "80px", "aTargets": [ columns.creation_date_formatted, columns.last_modification_date_formatted ] }
            ]
		} )
		Hyphen.controller.core.webEntities_update()

	})

	// View

	// Fill the table on update
	$(document).on( "/webentities", function(event, eventData){
        switch(eventData.what){
            case "updated":
                $('#webEntities_table').dataTable().fnAddData(Hyphen.model.webEntities.getAll().map(function(we){
                	return [
                        we.name
                        ,we.status
                        ,we.lru_prefixes
                        ,we.creation_date
                        ,we.last_modification_date
                        ,we.id
                        ,we.id
                        ,-we.creation_date
                        ,-we.last_modification_date
                        ,we.searchable
                    ]
                }))
                $('#loading_proxy').hide()
				$('#loading_achieved').show()
                Hyphen.view.table_updateInteractions()
                break
        }
    })

    Hyphen.view.table_updateInteractions = function(){
        $('#webEntities_table tbody tr').mouseenter(function(event){
            var tr = event.currentTarget
                actionsDiv = $(tr).find('div.actions')[0]
            $(actionsDiv).html('').show()
                .append(
                    $('
')
                        .append(
                            $('').html('')
                                .attr('title', 'Edit')
                                .attr('href', 'webentity_edit.php#we_id='+$(actionsDiv).attr('we_id'))
                        ).append(
                            $('').html('')
                                .attr('title', 'Crawl')
                                .attr('href', 'crawl_new.php#we_id='+$(actionsDiv).attr('we_id'))
                        )
                )
        })
        $('#webEntities_table tbody tr').mouseleave(function(event){
            var tr = event.currentTarget
                actionsDiv = $(tr).find('div.actions')[0]
            $(actionsDiv).hide()
        })
    }

    // Download json
    $('#webEntities_download').click(function(){
        // Blob Builder
        window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder
        var bb = new BlobBuilder
        bb.append('[')
        Hyphen.model.webEntities.getAll().forEach(function(we,i){
            if(i!=0)
                bb.append(',')
            bb.append(JSON.stringify(we))
        })
        bb.append(']')
        saveAs(bb.getBlob("text/json;charset=utf-8"), "WebEntities.json")
    })

})(window.Hyphen = window.Hyphen || {}, jQuery)<commit_msg>minor fix<commit_after>;(function(Hyphen, $, undefined){

    // On load
	$(document).ready(function(){

		/* Table initialisation */
        // Changing the columns is painful with this config, so we have an object allowing us to deal with that
        var columns = {
            name:0
            ,status:1
            ,prefixes:2
            ,creation_date_formatted:3
            ,last_modification_date_formatted:4
            ,actions:5
            ,id:6
            ,creation_date_unformatted:7
            ,last_modification_date_unformatted:8
            ,searchable:9
        }

        Hyphen.integration.initDataTables()
		$('.dataTable').dataTable( {
			"sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>"
			,"sPaginationType": "bootstrap"
			,"oLanguage": {
				"sLengthMenu": '_MENU_ web entities at once',
				"sZeroRecords": 'Nothing found - sorry',
	            "sInfo": 'Showing _START_ to _END_ of _TOTAL_ records',
        		"sInfoEmpty": 'Showing 0 to 0 of 0 records',
        		"sInfoFiltered": '(filtered from _MAX_ total records)'
			}
            ,"fnDrawCallback": function( oSettings ) {
                // Update the web entities proxies
                Hyphen.view.webEntities.proxiesUpdate(true)
                Hyphen.view.table_updateInteractions()
            }
            ,"aaSorting": [[ columns.last_modification_date_formatted, "asc" ]]
            ,"aoColumnDefs": [
                {
                    "mRender": function ( data, type, row ) {

                        return $('
').append(
                            $('').text(data)
                                .addClass('webEntity_proxy')
                                .attr('webEntity_id', row[columns.id])
                        ).html()
                    },
                    "aTargets": [ columns.name ]
                }
                ,{
                    "mRender": function ( data, type, row ) {

                        return $('
').append(
                            $('').text(data)
                                .addClass(Hyphen.view.webEntities_status_getLabelColor(data))
                        ).html()
                    },
                    "aTargets": [ columns.status ]
                }
                ,{
                    "mRender": function ( data, type, row ) {
                        return $('
').append(
                            $('
').append(
                                data.map(function(lru_prefix){
                                    var url = Hyphen.utils.LRU_to_URL(lru_prefix)
                                    return $('
').append(
                                        $('').append(
                                            $('')
                                                .attr('href', url)
                                                .attr('target', '_blank')
                                                .text(Hyphen.utils.URL_simplify(url))
                                        )
                                    )
                                })
                            )
                        ).html()
                    },
                    "aTargets": [ columns.prefixes ]
                }
                ,{
                    "mRender": function ( data, type, row ) {
                        var date = new Date()
                        date.setTime(data)
                        return $('
').append(
                            $('').text(Hyphen.utils.prettyDate(date))
                                .attr('title', date)
                        ).html()
                    },
                    "aTargets": [ columns.creation_date_formatted, columns.last_modification_date_formatted ]
                }
                ,{
                    "mRender": function ( data, type, row ) {
                        return '

'
                    },
                    "aTargets": [ columns.actions ]
                }
                ,{ "iDataSort": columns.creation_date_unformatted, "aTargets": [ columns.creation_date_formatted ] }
                ,{ "iDataSort": columns.last_modification_date_unformatted, "aTargets": [ columns.last_modification_date_formatted ] }
                ,{ "bVisible": false,  "aTargets": [ columns.searchable, columns.creation_date_unformatted, columns.last_modification_date_unformatted, columns.id ] }
                ,{ "sClass": "center", "aTargets": [ columns.actions ] }
                ,{ "bSearchable": false, "aTargets": [ columns.prefixes, columns.creation_date_formatted, columns.last_modification_date_formatted, columns.actions ] }
                ,{ "bSortable": false, "aTargets": [ columns.prefixes, columns.actions, columns.searchable ] }
                ,{ "sWidth": "80px", "aTargets": [ columns.actions ] }
                ,{ "sWidth": "80px", "aTargets": [ columns.status ] }
                ,{ "sWidth": "80px", "aTargets": [ columns.creation_date_formatted, columns.last_modification_date_formatted ] }
            ]
		} )
		Hyphen.controller.core.webEntities_update()

	})

	// View

	// Fill the table on update
	$(document).on( "/webentities", function(event, eventData){
        switch(eventData.what){
            case "updated":
                $('#webEntities_table').dataTable().fnAddData(Hyphen.model.webEntities.getAll().map(function(we){
                	return [
                        we.name
                        ,we.status
                        ,we.lru_prefixes
                        ,we.creation_date
                        ,we.last_modification_date
                        ,we.id
                        ,we.id
                        ,-we.creation_date
                        ,-we.last_modification_date
                        ,we.searchable
                    ]
                }))
                $('#loading_proxy').hide()
				$('#loading_achieved').show()
                Hyphen.view.table_updateInteractions()
                break
        }
    })

    Hyphen.view.table_updateInteractions = function(){
        $('#webEntities_table tbody tr').mouseenter(function(event){
            var tr = event.currentTarget
                actionsDiv = $(tr).find('div.actions')[0]
            $(actionsDiv).html('').show()
                .append(
                    $('
')
                        .append(
                            $('').html('')
                                .attr('title', 'Edit')
                                .attr('href', 'webentity_edit.php#we_id='+$(actionsDiv).attr('we_id'))
                        ).append(
                            $('').html('')
                                .attr('title', 'Crawl')
                                .attr('href', 'crawl_new.php#we_id='+$(actionsDiv).attr('we_id'))
                        )
                )
        })
        $('#webEntities_table tbody tr').mouseleave(function(event){
            var tr = event.currentTarget
                actionsDiv = $(tr).find('div.actions')[0]
            $(actionsDiv).hide()
        })
    }

    // Download json
    $('#webEntities_download').click(function(){
        // Blob Builder
        window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder
        var bb = new BlobBuilder
        bb.append('[')
        Hyphen.model.webEntities.getAll().forEach(function(we,i){
            if(i!=0)
                bb.append(',')
            bb.append(JSON.stringify(we))
        })
        bb.append(']')
        saveAs(bb.getBlob("text/json;charset=utf-8"), "WebEntities.json")
    })

})(window.Hyphen = window.Hyphen || {}, jQuery)<|endoftext|>


<commit_before>define([
  'extensions/views/view',
  'd3loader!',
  './xaxis',
  './yaxis',
  './yaxisRight',
  './line',
  './stack',
  './linelabel',
  './hover',
  './callout',
  './tooltip',
  'extensions/views/graph/table'
],
function (View, d3, XAxis, YAxis, YAxisRight, Line, Stack, LineLabel, Hover, Callout, Tooltip, GraphTable) {

  var scaleFromStartAndEndDates = {

    getModel: function (groupIndex, modelIndex) {
      if (!this.collection.at(groupIndex) && this.encompassStack) {
        return this.collection.at(groupIndex - 1, modelIndex);
      } else {
        return this.collection.at(groupIndex, modelIndex);
      }
    },

    getXPos: function (groupIndex, modelIndex) {
      groupIndex = groupIndex || 0;
      var model = this.getModel(groupIndex, modelIndex);
      return this.modelToDate(model);
    },
    calcXScale: function () {
      var total = this.collection.first().get('values'),
          start = this.modelToDate(total.first()).toDate(),
          end = this.modelToDate(total.last()).toDate();

      return this.d3.time.scale()
              .domain([start, end])
              .range([0, this.innerWidth]);
    }
  };

  var scaleByStartDate = _.extend({}, scaleFromStartAndEndDates, {
    modelToDate: function (model) {
      return this.getMoment(model.get('_start_at'));
    }
  });

  var scaleByTimestamp = _.extend({}, scaleFromStartAndEndDates, {
    modelToDate: function (model) {
      return this.getMoment(model.get('_timestamp'));
    }
  });

  var Graph = View.extend({

    d3: d3,

    valueAttr: '_count',

    minYDomainExtent: 6,
    numYTicks: 7,

    sharedComponents: {
      xaxis: XAxis,
      yaxis: YAxis,
      yaxisRight: YAxisRight,
      line: Line,
      stack: Stack,
      linelabel: LineLabel,
      callout: Callout,
      hover: Hover,
      tooltip: Tooltip
    },

    initialize: function (options) {
      View.prototype.initialize.apply(this, arguments);

      var collection = this.collection = options.collection;
      this.listenTo(collection, 'reset add remove sync', this.render);

      this.prepareGraphArea();

      this.scales = {};
      this.margin = {};

      if (this.collection.options.axes) {
        this.table = new GraphTable(_.extend(options, {$el: this.figure, valueAttr: this.valueAttr}));
      }

      // initialize graph components
      this.componentInstances = [];
      var defaultComponentOptions = this.getDefaultComponentOptions();
      _.each(this.prop('components'), function (definition) {
        var options = _.extend({}, defaultComponentOptions, definition.options);
        this.componentInstances.push(new definition.view(options));
      }, this);

      if (isClient) {
        $(window).on('resize', _.bind(this.render, this));
      }
    },

    /**
     * Defines default options that get passed to all graph components.
     * This object will be extended with component-specific options.
     * @returns {Object} Default options that get passed to components
     */
    getDefaultComponentOptions: function () {
      return {
        graph: this,
        collection: this.collection,
        el: this.figure,
        svg: this.svg,
        wrapper: this.wrapper,
        margin: this.margin,
        scales: this.scales
      };
    },

    showLineLabels: function () {
      return this.model && this.model.get('show-line-labels');
    },

    isOneHundredPercent: function () {
      return this.model && this.model.get('one-hundred-percent');
    },

    prepareGraphArea: function () {
      var figure = this.figure = $('
').addClass('graph');
      if (this.showLineLabels()) {
        figure.addClass('graph-with-labels');
      }
      figure.appendTo(this.$el);

      var graphWrapper = this.graphWrapper = $('

');
      graphWrapper.appendTo(figure);

      this.innerEl = $('

');
      this.innerEl.appendTo(graphWrapper);

      var svg = this.svg = this.d3.select(graphWrapper[0]).append('svg');

      // Apply attributes to SVGs so that they're ignored by screenreaders.
      // The WAI-ARIA 1.0 spec says that authors MAY use aria-hidden only
      // if they're hiding content to improve the experience for users
      // of assistive technologies.
      svg.attr('role', 'presentation');
      svg.attr('aria-hidden', 'true');

      this.wrapper = svg.append('g')
        .classed('wrapper', true);
    },

    /**
     * Calculates current factor between size in displayed pixels and logical
     * size.
     */
    scaleFactor: function () {
      return $(this.svg.node()).width() / this.width;
    },

    // Not implemented; override in configuration or subclass
    calcXScale: function () {
      throw 'No x scale defined.';
    },

    // Not implemented; override in configuration or subclass
    calcYScale: function () {
      throw 'No y scale defined.';
    },

    getConfigNames: function () {
      return ['overlay'];
    },

    pxToValue: function (cssVal) {
      if (!_.isString(cssVal)) {
        return null;
      }
      var matches = cssVal.match(/([0-9\.]+)px/);
      return matches ? parseFloat(matches[1]) : null;
    },

    resize: function () {
      var $svg = $(this.svg.node());
      $svg.attr('style', '');
      var width = this.width = $svg.parent().width(),
          height;

      // when both max-width and max-height are defined, scale graph according
      // to this aspect ratio
      var maxWidth = this.pxToValue($svg.css('max-width'));
      var maxHeight = this.pxToValue($svg.css('max-height'));
      var minHeight = this.pxToValue($svg.css('min-height'));

      if (_.isNumber(maxWidth) && _.isNumber(maxHeight)) {
        var aspectRatio = maxWidth / maxHeight;
        height = width / aspectRatio;
        if (_.isNumber(minHeight)) {
          height = Math.max(height, minHeight);
        }
      } else {
        height = $svg.height();
      }
      this.height = height;

      // configure SVG for automatic resize
      this.svg.attr({
        width: '100%',
        height: '100%',
        viewBox: '0 0 ' + width + ' ' + height,
        style: 'max-width:' + width + 'px; max-height:' + height + 'px; display:block;'
      });
      $svg.height(height);

      var innerEl = this.innerEl;
      this.margin.top = innerEl.position().top;
      this.margin.left = innerEl.position().left;

      this.innerWidth = innerEl.outerWidth();
      this.innerHeight = innerEl.outerHeight();

      this.margin.bottom = height - this.margin.top - this.innerHeight;
      this.margin.right = width - this.margin.left - this.innerWidth;

      this.wrapper.attr('transform', [
        'translate(',
        this.margin.left,
        ', ',
        this.margin.top,
        ')'
      ].join(''));
    },

    applyConfig: function (name) {
      var config = this.configs[name];
      if (!config) {
        return;
      }

      if (config.initialize) {
        config.initialize.call(this);
      }

      _.each(config, function (value, key) {
        if (key === 'initialize') {
          return;
        }
        this[key] = value;
      }, this);
    },

    /**
     * The linelabel figcaption is positioned on top of the graph
     * at small screen sizes using position static.
     */
    lineLabelOnTop: function () {
      return this.$el.find('figcaption').css('position') === 'static';
    },

    /**
     * Hide callout during resize if present. Works around bug in iOS Webkit
     * that incorrectly calculates height of inner element.
     */
    resizeWithCalloutHidden: function () {
      var callout = this.$el.find('.callout');
      var calloutHidden = callout.hasClass('performance-hidden');
      callout.addClass('performance-hidden');

      this.resize();

      if (!calloutHidden) {
        callout.removeClass('performance-hidden');
      }
    },

    /**
     * Applies current configuration, then renders components in defined order
     */
    render: function () {
      if (isServer) {
        return;
      }

      View.prototype.render.apply(this, arguments);

      if (this.collection.options) {
        this.currency = this.collection.options.currency;
      }

      this.resizeWithCalloutHidden();

      var configNames = this.getConfigNames();
      if (_.isString(configNames)) {
        configNames = [configNames];
      }

      _.each(configNames, function (configName) {
        this.applyConfig(configName);
      }, this);

      this.scales.x = this.calcXScale();
      this.scales.y = this.calcYScale();

      _.each(this.componentInstances, function (component) {
        _.each(configNames, function (configName) {
          component.applyConfig(configName);
        });
        component.render();
      }, this);
      if (this.table) {
        this.table.render();
      }
    },

    remove: function () {
      if (this.table) {
        this.table.remove();
      }
      _.invoke(this.componentInstances, 'remove');
      return View.prototype.remove.apply(this, arguments);
    },

    configs: {
      hour: scaleByTimestamp,
      day: scaleByStartDate,
      week: scaleByStartDate,
      month: scaleByStartDate,
      quarter: scaleByStartDate,

      ymin: {
        initialize: function () {
          var d3 = this.d3;
          var valueAttr = this.valueAttr;
          var min = d3.min(this.collection.models, function (group) {
            return d3.min(group.get('values').models, function (value) {
              return value.get(valueAttr);
            });
          });
          this.getYMin = min;
        }
      },

      overlay: {
        getYPos: function (groupIndex, modelIndex) {
          var group = this.collection.at(groupIndex);
          var model = group.get('values').at(modelIndex);
          return model.get(this.valueAttr);
        },
        calcYScale: function () {
          var d3 = this.d3;
          var valueAttr = this.valueAttr;
          var max = d3.max(this.collection.models, function (group) {
            return d3.max(group.get('values').models, function (value) {
              return value.get(valueAttr);
            });
          });

          var yScale = this.d3.scale.linear();
          var yMin = this.getYMin || 0;
          var tickValues = this.calculateLinearTicks([yMin, Math.max(max, this.minYDomainExtent)], this.numYTicks);
          yScale.domain(tickValues.extent);
          yScale.rangeRound([this.innerHeight, 0]);
          yScale.tickValueList = tickValues.values;
          return yScale;
        }
      },

      stack: {
        initialize: function () {
          var valueAttr = this.valueAttr;
          var stack = this.d3.layout.stack()
            .values(function (group) {
              return group.get('values').models;
            })
            .y(function (model) {
              return model.get(valueAttr);
            });

          if (this.isOneHundredPercent()) {
            stack.offset(function (data) {
              var lineCount = data.length,
                  lineLength = data[0].length,
                  i, j, sumOfYValues, y0 = [];

              for (j = 0; j < lineLength; ++j) {
                sumOfYValues = 0;
                for (i = 0; i < lineCount; i++) {
                  sumOfYValues += data[i][j][1];
                }
                for (i = 0; i < lineCount; i++) {
                  if (sumOfYValues) {
                    data[i][j][1] = data[i][j][1] / sumOfYValues;
                  } else {
                    data[i][j][1] = null;
                  }
                }
              }
              for (j = 0; j < lineLength; ++j) {
                y0[j] = 0;
              }
              return y0;
            });
          }

          if (this.outStack) {
            stack.out(_.bind(this.outStack, this));
          }

          this.layers = stack(this.collection.models.slice().reverse());
        },
        getYPos: function (groupIndex, modelIndex) {
          if (!this.collection.at(groupIndex)) {
            if (this.collection.at(groupIndex - 1) && this.encompassStack) {
              return 0;
            } else {
              return null;
            }
          }
          var model = this.collection.at(groupIndex).get('values').at(modelIndex);
          var yProperty = this.stackYProperty || 'y';
          if (model[yProperty] === null) {
            return null;
          }
          var y0Property = this.stackY0Property || 'y0';
          return model[y0Property] + model[yProperty];
        },
        getY0Pos: function (groupIndex, modelIndex) {
          var y0Property = this.stackY0Property || 'y0';
          var model = this.collection.at(groupIndex).get('values').at(modelIndex);
          return model[y0Property];
        },
        calcYScale: function () {
          var d3 = this.d3;
          var valueAttr = this.valueAttr;

          var sumAtIndex = _.bind(function (i) {
            return this.collection.reduce(function (memo, group) {
              return memo + group.get('values').at(i).get(valueAttr);
            }, 0);
          }, this);

          var sums = [];
          for (var i = 0; i < this.collection.at(0).get('values').length; i++) {
            sums.push(sumAtIndex(i));
          }
          var max = d3.max(sums);
          var yScale = this.d3.scale.linear();
          var yMin = this.getYMin || 0;
          var tickValues = this.calculateLinearTicks([yMin, Math.max(max, this.minYDomainExtent)], this.numYTicks);
          if (this.isOneHundredPercent()) {
            yScale.domain([0, 1]);
          } else {
            yScale.domain(tickValues.extent);
          }
          yScale.rangeRound([this.innerHeight, 0]);
          yScale.tickValueList = tickValues.values;
          return yScale;
        }
      }
    }
  });

  return Graph;
});
<commit_msg>Unbind window resize event on remove<commit_after>define([
  'extensions/views/view',
  'd3loader!',
  './xaxis',
  './yaxis',
  './yaxisRight',
  './line',
  './stack',
  './linelabel',
  './hover',
  './callout',
  './tooltip',
  'extensions/views/graph/table'
],
function (View, d3, XAxis, YAxis, YAxisRight, Line, Stack, LineLabel, Hover, Callout, Tooltip, GraphTable) {

  var scaleFromStartAndEndDates = {

    getModel: function (groupIndex, modelIndex) {
      if (!this.collection.at(groupIndex) && this.encompassStack) {
        return this.collection.at(groupIndex - 1, modelIndex);
      } else {
        return this.collection.at(groupIndex, modelIndex);
      }
    },

    getXPos: function (groupIndex, modelIndex) {
      groupIndex = groupIndex || 0;
      var model = this.getModel(groupIndex, modelIndex);
      return this.modelToDate(model);
    },
    calcXScale: function () {
      var total = this.collection.first().get('values'),
          start = this.modelToDate(total.first()).toDate(),
          end = this.modelToDate(total.last()).toDate();

      return this.d3.time.scale()
              .domain([start, end])
              .range([0, this.innerWidth]);
    }
  };

  var scaleByStartDate = _.extend({}, scaleFromStartAndEndDates, {
    modelToDate: function (model) {
      return this.getMoment(model.get('_start_at'));
    }
  });

  var scaleByTimestamp = _.extend({}, scaleFromStartAndEndDates, {
    modelToDate: function (model) {
      return this.getMoment(model.get('_timestamp'));
    }
  });

  var Graph = View.extend({

    d3: d3,

    valueAttr: '_count',

    minYDomainExtent: 6,
    numYTicks: 7,

    sharedComponents: {
      xaxis: XAxis,
      yaxis: YAxis,
      yaxisRight: YAxisRight,
      line: Line,
      stack: Stack,
      linelabel: LineLabel,
      callout: Callout,
      hover: Hover,
      tooltip: Tooltip
    },

    initialize: function (options) {
      View.prototype.initialize.apply(this, arguments);

      var collection = this.collection = options.collection;
      this.listenTo(collection, 'reset add remove sync', this.render);

      this.prepareGraphArea();

      this.scales = {};
      this.margin = {};

      if (this.collection.options.axes) {
        this.table = new GraphTable(_.extend(options, {$el: this.figure, valueAttr: this.valueAttr}));
      }

      // initialize graph components
      this.componentInstances = [];
      var defaultComponentOptions = this.getDefaultComponentOptions();
      _.each(this.prop('components'), function (definition) {
        var options = _.extend({}, defaultComponentOptions, definition.options);
        this.componentInstances.push(new definition.view(options));
      }, this);

      if (isClient) {
        $(window).on('resize.' + this.cid, _.bind(this.render, this));
      }
    },

    /**
     * Defines default options that get passed to all graph components.
     * This object will be extended with component-specific options.
     * @returns {Object} Default options that get passed to components
     */
    getDefaultComponentOptions: function () {
      return {
        graph: this,
        collection: this.collection,
        el: this.figure,
        svg: this.svg,
        wrapper: this.wrapper,
        margin: this.margin,
        scales: this.scales
      };
    },

    showLineLabels: function () {
      return this.model && this.model.get('show-line-labels');
    },

    isOneHundredPercent: function () {
      return this.model && this.model.get('one-hundred-percent');
    },

    prepareGraphArea: function () {
      var figure = this.figure = $('
').addClass('graph');
      if (this.showLineLabels()) {
        figure.addClass('graph-with-labels');
      }
      figure.appendTo(this.$el);

      var graphWrapper = this.graphWrapper = $('

');
      graphWrapper.appendTo(figure);

      this.innerEl = $('

');
      this.innerEl.appendTo(graphWrapper);

      var svg = this.svg = this.d3.select(graphWrapper[0]).append('svg');

      // Apply attributes to SVGs so that they're ignored by screenreaders.
      // The WAI-ARIA 1.0 spec says that authors MAY use aria-hidden only
      // if they're hiding content to improve the experience for users
      // of assistive technologies.
      svg.attr('role', 'presentation');
      svg.attr('aria-hidden', 'true');

      this.wrapper = svg.append('g')
        .classed('wrapper', true);
    },

    /**
     * Calculates current factor between size in displayed pixels and logical
     * size.
     */
    scaleFactor: function () {
      return $(this.svg.node()).width() / this.width;
    },

    // Not implemented; override in configuration or subclass
    calcXScale: function () {
      throw 'No x scale defined.';
    },

    // Not implemented; override in configuration or subclass
    calcYScale: function () {
      throw 'No y scale defined.';
    },

    getConfigNames: function () {
      return ['overlay'];
    },

    pxToValue: function (cssVal) {
      if (!_.isString(cssVal)) {
        return null;
      }
      var matches = cssVal.match(/([0-9\.]+)px/);
      return matches ? parseFloat(matches[1]) : null;
    },

    resize: function () {
      var $svg = $(this.svg.node());
      $svg.attr('style', '');
      var width = this.width = $svg.parent().width(),
          height;

      // when both max-width and max-height are defined, scale graph according
      // to this aspect ratio
      var maxWidth = this.pxToValue($svg.css('max-width'));
      var maxHeight = this.pxToValue($svg.css('max-height'));
      var minHeight = this.pxToValue($svg.css('min-height'));

      if (_.isNumber(maxWidth) && _.isNumber(maxHeight)) {
        var aspectRatio = maxWidth / maxHeight;
        height = width / aspectRatio;
        if (_.isNumber(minHeight)) {
          height = Math.max(height, minHeight);
        }
      } else {
        height = $svg.height();
      }
      this.height = height;

      // configure SVG for automatic resize
      this.svg.attr({
        width: '100%',
        height: '100%',
        viewBox: '0 0 ' + width + ' ' + height,
        style: 'max-width:' + width + 'px; max-height:' + height + 'px; display:block;'
      });
      $svg.height(height);

      var innerEl = this.innerEl;
      this.margin.top = innerEl.position().top;
      this.margin.left = innerEl.position().left;

      this.innerWidth = innerEl.outerWidth();
      this.innerHeight = innerEl.outerHeight();

      this.margin.bottom = height - this.margin.top - this.innerHeight;
      this.margin.right = width - this.margin.left - this.innerWidth;

      this.wrapper.attr('transform', [
        'translate(',
        this.margin.left,
        ', ',
        this.margin.top,
        ')'
      ].join(''));
    },

    applyConfig: function (name) {
      var config = this.configs[name];
      if (!config) {
        return;
      }

      if (config.initialize) {
        config.initialize.call(this);
      }

      _.each(config, function (value, key) {
        if (key === 'initialize') {
          return;
        }
        this[key] = value;
      }, this);
    },

    /**
     * The linelabel figcaption is positioned on top of the graph
     * at small screen sizes using position static.
     */
    lineLabelOnTop: function () {
      return this.$el.find('figcaption').css('position') === 'static';
    },

    /**
     * Hide callout during resize if present. Works around bug in iOS Webkit
     * that incorrectly calculates height of inner element.
     */
    resizeWithCalloutHidden: function () {
      var callout = this.$el.find('.callout');
      var calloutHidden = callout.hasClass('performance-hidden');
      callout.addClass('performance-hidden');

      this.resize();

      if (!calloutHidden) {
        callout.removeClass('performance-hidden');
      }
    },

    /**
     * Applies current configuration, then renders components in defined order
     */
    render: function () {
      if (isServer) {
        return;
      }

      View.prototype.render.apply(this, arguments);

      if (this.collection.options) {
        this.currency = this.collection.options.currency;
      }

      this.resizeWithCalloutHidden();

      var configNames = this.getConfigNames();
      if (_.isString(configNames)) {
        configNames = [configNames];
      }

      _.each(configNames, function (configName) {
        this.applyConfig(configName);
      }, this);

      this.scales.x = this.calcXScale();
      this.scales.y = this.calcYScale();

      _.each(this.componentInstances, function (component) {
        _.each(configNames, function (configName) {
          component.applyConfig(configName);
        });
        component.render();
      }, this);
      if (this.table) {
        this.table.render();
      }
    },

    remove: function () {
      if (this.table) {
        this.table.remove();
      }
      _.invoke(this.componentInstances, 'remove');
      $(window).off('resize.' + this.cid);
      return View.prototype.remove.apply(this, arguments);
    },

    configs: {
      hour: scaleByTimestamp,
      day: scaleByStartDate,
      week: scaleByStartDate,
      month: scaleByStartDate,
      quarter: scaleByStartDate,

      ymin: {
        initialize: function () {
          var d3 = this.d3;
          var valueAttr = this.valueAttr;
          var min = d3.min(this.collection.models, function (group) {
            return d3.min(group.get('values').models, function (value) {
              return value.get(valueAttr);
            });
          });
          this.getYMin = min;
        }
      },

      overlay: {
        getYPos: function (groupIndex, modelIndex) {
          var group = this.collection.at(groupIndex);
          var model = group.get('values').at(modelIndex);
          return model.get(this.valueAttr);
        },
        calcYScale: function () {
          var d3 = this.d3;
          var valueAttr = this.valueAttr;
          var max = d3.max(this.collection.models, function (group) {
            return d3.max(group.get('values').models, function (value) {
              return value.get(valueAttr);
            });
          });

          var yScale = this.d3.scale.linear();
          var yMin = this.getYMin || 0;
          var tickValues = this.calculateLinearTicks([yMin, Math.max(max, this.minYDomainExtent)], this.numYTicks);
          yScale.domain(tickValues.extent);
          yScale.rangeRound([this.innerHeight, 0]);
          yScale.tickValueList = tickValues.values;
          return yScale;
        }
      },

      stack: {
        initialize: function () {
          var valueAttr = this.valueAttr;
          var stack = this.d3.layout.stack()
            .values(function (group) {
              return group.get('values').models;
            })
            .y(function (model) {
              return model.get(valueAttr);
            });

          if (this.isOneHundredPercent()) {
            stack.offset(function (data) {
              var lineCount = data.length,
                  lineLength = data[0].length,
                  i, j, sumOfYValues, y0 = [];

              for (j = 0; j < lineLength; ++j) {
                sumOfYValues = 0;
                for (i = 0; i < lineCount; i++) {
                  sumOfYValues += data[i][j][1];
                }
                for (i = 0; i < lineCount; i++) {
                  if (sumOfYValues) {
                    data[i][j][1] = data[i][j][1] / sumOfYValues;
                  } else {
                    data[i][j][1] = null;
                  }
                }
              }
              for (j = 0; j < lineLength; ++j) {
                y0[j] = 0;
              }
              return y0;
            });
          }

          if (this.outStack) {
            stack.out(_.bind(this.outStack, this));
          }

          this.layers = stack(this.collection.models.slice().reverse());
        },
        getYPos: function (groupIndex, modelIndex) {
          if (!this.collection.at(groupIndex)) {
            if (this.collection.at(groupIndex - 1) && this.encompassStack) {
              return 0;
            } else {
              return null;
            }
          }
          var model = this.collection.at(groupIndex).get('values').at(modelIndex);
          var yProperty = this.stackYProperty || 'y';
          if (model[yProperty] === null) {
            return null;
          }
          var y0Property = this.stackY0Property || 'y0';
          return model[y0Property] + model[yProperty];
        },
        getY0Pos: function (groupIndex, modelIndex) {
          var y0Property = this.stackY0Property || 'y0';
          var model = this.collection.at(groupIndex).get('values').at(modelIndex);
          return model[y0Property];
        },
        calcYScale: function () {
          var d3 = this.d3;
          var valueAttr = this.valueAttr;

          var sumAtIndex = _.bind(function (i) {
            return this.collection.reduce(function (memo, group) {
              return memo + group.get('values').at(i).get(valueAttr);
            }, 0);
          }, this);

          var sums = [];
          for (var i = 0; i < this.collection.at(0).get('values').length; i++) {
            sums.push(sumAtIndex(i));
          }
          var max = d3.max(sums);
          var yScale = this.d3.scale.linear();
          var yMin = this.getYMin || 0;
          var tickValues = this.calculateLinearTicks([yMin, Math.max(max, this.minYDomainExtent)], this.numYTicks);
          if (this.isOneHundredPercent()) {
            yScale.domain([0, 1]);
          } else {
            yScale.domain(tickValues.extent);
          }
          yScale.rangeRound([this.innerHeight, 0]);
          yScale.tickValueList = tickValues.values;
          return yScale;
        }
      }
    }
  });

  return Graph;
});
<|endoftext|>


<commit_before>/* global forge, $, asyncTest, askQuestion, ok, start */

module("forge.media");

forge.tools.getLocal("fixtures/media/test.mp3", function (audioFile) {
    forge.tools.getLocal("fixtures/media/small.mp4", function (videoFile) {
        testsWithFixtures(audioFile, videoFile);
    });
});

var testsWithFixtures = function (audioFile, videoFile) {
    asyncTest("Play audio", 1, function() {
        forge.media.createAudioPlayer(audioFile, function (player) {
            player.play(function () {
                askQuestion("Is audio playing?", {
                    Yes: function () {
                        player.duration(function (duration) {
                            player.seek(duration/3, function () {
                                askQuestion("Did the pitch jump?", {
                                    Yes: function () {
                                        player.positionChanged.addListener(function (time) {
                                            $('#playertime').text(time);
                                        });
                                        askQuestion("Is the time changing: ", {
                                            Yes: function () {
                                                player.pause(function () {
                                                    askQuestion("Has the audio paused?", {
                                                        Yes: function () {
                                                            player.play(function () {
                                                                askQuestion("Has the audio continued from where it paused?", {
                                                                    Yes: function () {
                                                                        player.stop(function () {
                                                                            askQuestion("Has the audio stopped?", {
                                                                                Yes: function () {
                                                                                player.destroy(function () {
                                                                                ok(true, "Success");
                                                                                start();
                                                                                }, function () {
                                                                                ok(false, "Error calling destroy on player");
                                                                                start();
                                                                                });
                                                                                },
                                                                                No: function () {
                                                                                ok(false, "User claims failure");
                                                                                start();
                                                                                }
                                                                            });
                                                                        }, function () {
                                                                            ok(false, "Error calling stop on player");
                                                                            start();
                                                                        });
                                                                    },
                                                                    No: function () {
                                                                        ok(false, "User claims failure");
                                                                        start();
                                                                    }
                                                                });
                                                            }, function () {
                                                                ok(false, "Error calling play on player");
                                                                start();
                                                            });
                                                        },
                                                        No: function () {
                                                            ok(false, "User claims failure");
                                                            start();
                                                        }
                                                    });
                                                }, function () {
                                                    ok(false, "Error calling pause on player");
                                                    start();
                                                });
                                            },
                                            No: function () {
                                                ok(false, "User claims failure");
                                                start();
                                            }
                                        });
                                    },
                                    No: function () {
                                        ok(false, "User claims failure");
                                        start();
                                    }
                                });
                            }, function () {
                                ok(false, "Error calling seek on player");
                                start();
                            });
                        }, function () {
                            ok(false, "Error calling duration on player");
                            start();
                        });

                    },
                    No: function () {
                        ok(false, "User claims failure");
                        start();
                    }
                });
            }, function () {
                ok(false, "Error calling play on player");
                start();
            });
        }, function () {
            ok(false, "Error creating audio player");
                start();
        });
    });

    asyncTest("Play remote video", 1, function() {
        forge.media.videoPlay("https://ops.trigger.io/75d92dce/tests/big_buck_bunny.mp4");

        askQuestion("Did a video just play?", {
            Yes: function () {
                ok(true, "Success");
                start();
            },
            No: function () {
                ok(false, "User claims failure");
                start();
            }
        });
    });

    asyncTest("Play local video in assets", 1, function() {
        forge.media.videoPlay(videoFile);

        askQuestion("Did another video just play?", {
            Yes: function () {
                ok(true, "Success");
                start();
            },
            No: function () {
                ok(false, "User claims failure");
                start();
            }
        });
    });

    if (forge.file) {
        asyncTest("Play local video", 1, function() {
            forge.file.getVideo(function (video) {
                forge.file.URL(video, function (url) {
                    askQuestion("Were you just prompted to select a video?", {
                        Yes: function () {
                            forge.media.videoPlay(url);
                            askQuestion("Did that video play?", {
                                Yes: function () {
                                    ok(true, "Success");
                                    start();
                                },
                                No: function () {
                                    ok(false, "User claims failure");
                                    start();
                                }
                            });
                        },
                        No: function () {
                            ok(false, "User claims failure");
                            start();
                        }
                    });
                });
            });
        });

        asyncTest("Gallery Video Player", 1, function() {
            forge.file.getVideo({
                source: "gallery"
            }, function (file) {
                forge.file.URL(file, function (url) {
                    forge.media.videoPlay(url, function () {
                        askQuestion("Did your video just play?", {
                            Yes: function () {
                                ok(true, "video capture successful");
                                start();
                            },
                            No: function () {
                                ok(false, "didn't play back just-captured video");
                                start();
                            }
                        });
                    }, function (e) {
                        ok(false, "API call failure: "+e.message);
                        start();
                    });
                }, function (e) {
                    ok(false, "API call failure: "+e.message);
                    start();
                });
            },	function (e) {
                ok(false, "API call failure: "+e.message);
                start();
            });
        });

    }
};
<commit_msg>Update tests for API refactors<commit_after>/* global forge, $, asyncTest, askQuestion, ok, start */

module("forge.media");

forge.tools.getFileFromSourceDirectory("fixtures/media/test.mp3", function (audioFile) {
    forge.tools.getFileFromSourceDirectory("fixtures/media/small.mp4", function (videoFile) {
        testsWithFixtures(audioFile, videoFile);
    });
});

var testsWithFixtures = function (audioFile, videoFile) {
    asyncTest("Play audio", 1, function() {
        forge.media.createAudioPlayer(audioFile, function (player) {
            player.play(function () {
                askQuestion("Is audio playing?", {
                    Yes: function () {
                        player.duration(function (duration) {
                            player.seek(duration/3, function () {
                                askQuestion("Did the pitch jump?", {
                                    Yes: function () {
                                        player.positionChanged.addListener(function (time) {
                                            $('#playertime').text(time);
                                        });
                                        askQuestion("Is the time changing: ", {
                                            Yes: function () {
                                                player.pause(function () {
                                                    askQuestion("Has the audio paused?", {
                                                        Yes: function () {
                                                            player.play(function () {
                                                                askQuestion("Has the audio continued from where it paused?", {
                                                                    Yes: function () {
                                                                        player.stop(function () {
                                                                            askQuestion("Has the audio stopped?", {
                                                                                Yes: function () {
                                                                                player.destroy(function () {
                                                                                ok(true, "Success");
                                                                                start();
                                                                                }, function () {
                                                                                ok(false, "Error calling destroy on player");
                                                                                start();
                                                                                });
                                                                                },
                                                                                No: function () {
                                                                                ok(false, "User claims failure");
                                                                                start();
                                                                                }
                                                                            });
                                                                        }, function () {
                                                                            ok(false, "Error calling stop on player");
                                                                            start();
                                                                        });
                                                                    },
                                                                    No: function () {
                                                                        ok(false, "User claims failure");
                                                                        start();
                                                                    }
                                                                });
                                                            }, function () {
                                                                ok(false, "Error calling play on player");
                                                                start();
                                                            });
                                                        },
                                                        No: function () {
                                                            ok(false, "User claims failure");
                                                            start();
                                                        }
                                                    });
                                                }, function () {
                                                    ok(false, "Error calling pause on player");
                                                    start();
                                                });
                                            },
                                            No: function () {
                                                ok(false, "User claims failure");
                                                start();
                                            }
                                        });
                                    },
                                    No: function () {
                                        ok(false, "User claims failure");
                                        start();
                                    }
                                });
                            }, function () {
                                ok(false, "Error calling seek on player");
                                start();
                            });
                        }, function () {
                            ok(false, "Error calling duration on player");
                            start();
                        });

                    },
                    No: function () {
                        ok(false, "User claims failure");
                        start();
                    }
                });
            }, function () {
                ok(false, "Error calling play on player");
                start();
            });
        }, function () {
            ok(false, "Error creating audio player");
                start();
        });
    });

    asyncTest("Play remote video", 1, function() {
        forge.media.playVideoURL("https://ops.trigger.io/75d92dce/tests/big_buck_bunny.mp4");

        askQuestion("Did a video just play?", {
            Yes: function () {
                ok(true, "Success");
                start();
            },
            No: function () {
                ok(false, "User claims failure");
                start();
            }
        });
    });

    asyncTest("Play local video in assets", 1, function() {
        forge.media.playVideoFile(videoFile);

        askQuestion("Did another video just play?", {
            Yes: function () {
                ok(true, "Success");
                start();
            },
            No: function () {
                ok(false, "User claims failure");
                start();
            }
        });
    });

    if (forge.file) {
        asyncTest("Play local video", 1, function() {
            forge.file.getVideo(function (file) {
                askQuestion("Were you just prompted to select a video?", {
                    Yes: function () {
                        forge.media.playVideoFile(file);
                        askQuestion("Did that video play?", {
                            Yes: function () {
                                ok(true, "Success");
                                start();
                            },
                            No: function () {
                                ok(false, "User claims failure");
                                start();
                            }
                        });
                    },
                    No: function () {
                        ok(false, "User claims failure");
                        start();
                    }
                });
            });
        });
    }
};
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Route.extend({
  createFeedFromGtfsService: Ember.inject.service('create-feed-from-gtfs'),
  beforeModel: function(transition) {
    var controller = this;
    var feedModel = this.get('createFeedFromGtfsService').feedModel;
    var url = feedModel.get('url');
    var adapter = this.get('store').adapterFor('feeds');
    var fetch_info_url = adapter.urlPrefix()+'/feeds/fetch_info';
    var promise = adapter.ajax(fetch_info_url, 'post', {data:{url:url}});
    promise.then(function(response) {
      if (response.status == 'complete') {
        feedModel.set('id', response.feed.onestop_id);
        response.operators.map(function(operator){feedModel.addOperator(operator)});
        return feedModel;
      } else if (response.status == 'processing') {
        transition.abort();
        return Ember.run.later(controller, function(){
          transition.retry();
        }, 1000);
      }
    }).catch(function() {
      feedModel.get('errors').add('url','The feed URL is invalid. Please check the link and try again.');
    });
    return promise
  },
  model: function() {
    return this.get('createFeedFromGtfsService').feedModel;
  }
});
<commit_msg>Add back operators_in_feed from feedinfo response<commit_after>import Ember from 'ember';

export default Ember.Route.extend({
  createFeedFromGtfsService: Ember.inject.service('create-feed-from-gtfs'),
  beforeModel: function(transition) {
    var controller = this;
    var feedModel = this.get('createFeedFromGtfsService').feedModel;
    var url = feedModel.get('url');
    var adapter = this.get('store').adapterFor('feeds');
    var fetch_info_url = adapter.urlPrefix()+'/feeds/fetch_info';
    var promise = adapter.ajax(fetch_info_url, 'post', {data:{url:url}});
    promise.then(function(response) {
      if (response.status == 'complete') {
        feedModel.set('id', response.feed.onestop_id);
        feedModel.set('operators_in_feed', response.feed.operators_in_feed);
        response.operators.map(function(operator){feedModel.addOperator(operator)});
        return feedModel;
      } else if (response.status == 'processing') {
        transition.abort();
        return Ember.run.later(controller, function(){
          transition.retry();
        }, 1000);
      }
    }).catch(function() {
      feedModel.get('errors').add('url','The feed URL is invalid. Please check the link and try again.');
    });
    return promise
  },
  model: function() {
    return this.get('createFeedFromGtfsService').feedModel;
  }
});
<|endoftext|>


<commit_before>/*
 * Filter that only returns xforms.  Used by the change listener.
 */
function(doc, req)
{
	if (doc['xmlns'] == "http://code.javarosa.org/devicereport") {
		return false;
	}
    var doc_type = doc["doc_type"];

    switch (doc_type) {
        case "XFormInstance":
        case "XFormArchived":
        case "XFormDeprecated":
        case "XFormDuplicate":
            return true;
        default:
            return false;
    }
}
<commit_msg>expanding xforms.js couch filter to inclue HQSubmissions to index into ES<commit_after>/*
 * Filter that only returns xforms.  Used by the change listener.
 */
function(doc, req)
{
	if (doc['xmlns'] == "http://code.javarosa.org/devicereport") {
		return false;
	}
    var doc_type = doc["doc_type"];

    switch (doc_type) {
        case "XFormInstance":
        case "XFormArchived":
        case "XFormDeprecated":
        case "XFormDuplicate":
        case "HQSubmission":
            return true;
        default:
            return false;
    }
}
<|endoftext|>


<commit_before>var API_BASE = 'http://' + window.location.hostname + ':5000/';

function logFailure(fail) {
    console.log("Trouble getting data. API server down?");
    console.log(fail);
}

function makeLink(url, text) {
    var link = $('<a />', {
        href: url,
        text: text,
    });
    return $('<div />').append(link).html();
}

function makeList(container, options) {
    $.getJSON(API_BASE + options.endpoint)
        .done(function (json) {
            $container = $(container);
            $container.append($('<h3 />').text(options.title).addClass('text-center'));
            $list = $('<ul />');

            data = json.data;
            data.forEach(function (e) {
                console.log(e);
                $item = $('<li />');
                if (typeof options.keyName === 'function') {
                    $item.html(options.keyName(e));
                } else {
                    $item.html(e[options.keyName]);
                }
                $list.append($item);
            });
            $container.append($list);
        })
        .fail(logFailure);
}

function makeXYGraph(container, options) {
    $.getJSON(API_BASE + options.endpoint)
        .done(function (json) {
            data = json.data;
            $(container).highcharts({
                chart: {
                    type: options.type
                },
                title: {
                    text: options.title
                },
                subtitle: {
                    text: options.subtitle
                },
                xAxis: {
                    categories: data.map(function (e) {
                        if (typeof options.keyName === "function") {
                            return options.keyName(e);
                        }
                        return e[options.keyName];
                    })
                },
                yAxis: {
                    min: 0,
                    title: {
                        text: options.yTitle
                    }
                },
                legend: {
                    enabled: false
                },
                series: [{
                    name: options.label,
                    data: data.map(function (e) {
                        if (typeof options.valueName === "function") {
                            return options.valueName(e);
                        }
                        return e[options.valueName];
                    })
                }]
            });
        })
        .fail(logFailure);
}

// first row
makeXYGraph('#most-active-people', {
    endpoint: 'gabrielfalcao/lettuce/most_active_people',
    type: 'bar',
    title: "Most active people",
    keyName: function (e) {
        return makeLink("http://github.com/" + e.term, e.term);
    },
    valueName: 'count',
    yTitle: 'Events',
    label: 'events'
});
makeXYGraph('#total-events-monthly', {
    endpoint: 'gabrielfalcao/lettuce/total_events_monthly',
    type: 'area',
    title: "Activity",
    subtitle: "Total monthly events",
    keyName: 'month',
    valueName: 'value',
    yTitle: 'Events',
    label: 'events'
});

// second row
makeXYGraph('#most-active-issues', {
    endpoint: 'gabrielfalcao/lettuce/most_active_issues',
    type: 'bar',
    title: "Most active issues",
    keyName: function (e) {
        return makeLink("http://github.com/gabrielfalcao/lettuce/issues/" + e.term,
                        "#" + e.term);
    },
    valueName: 'count',
    yTitle: 'Events',
    label: 'events'
});

<commit_msg>use single quotes for keyword<commit_after>var API_BASE = 'http://' + window.location.hostname + ':5000/';

function logFailure(fail) {
    console.log("Trouble getting data. API server down?");
    console.log(fail);
}

function makeLink(url, text) {
    var link = $('<a />', {
        href: url,
        text: text,
    });
    return $('<div />').append(link).html();
}

function makeList(container, options) {
    $.getJSON(API_BASE + options.endpoint)
        .done(function (json) {
            $container = $(container);
            $container.append($('<h3 />').text(options.title).addClass('text-center'));
            $list = $('<ul />');

            data = json.data;
            data.forEach(function (e) {
                console.log(e);
                $item = $('<li />');
                if (typeof options.keyName === 'function') {
                    $item.html(options.keyName(e));
                } else {
                    $item.html(e[options.keyName]);
                }
                $list.append($item);
            });
            $container.append($list);
        })
        .fail(logFailure);
}

function makeXYGraph(container, options) {
    $.getJSON(API_BASE + options.endpoint)
        .done(function (json) {
            data = json.data;
            $(container).highcharts({
                chart: {
                    type: options.type
                },
                title: {
                    text: options.title
                },
                subtitle: {
                    text: options.subtitle
                },
                xAxis: {
                    categories: data.map(function (e) {
                        if (typeof options.keyName === 'function') {
                            return options.keyName(e);
                        }
                        return e[options.keyName];
                    })
                },
                yAxis: {
                    min: 0,
                    title: {
                        text: options.yTitle
                    }
                },
                legend: {
                    enabled: false
                },
                series: [{
                    name: options.label,
                    data: data.map(function (e) {
                        if (typeof options.valueName === 'function') {
                            return options.valueName(e);
                        }
                        return e[options.valueName];
                    })
                }]
            });
        })
        .fail(logFailure);
}

// first row
makeXYGraph('#most-active-people', {
    endpoint: 'gabrielfalcao/lettuce/most_active_people',
    type: 'bar',
    title: "Most active people",
    keyName: function (e) {
        return makeLink("http://github.com/" + e.term, e.term);
    },
    valueName: 'count',
    yTitle: 'Events',
    label: 'events'
});
makeXYGraph('#total-events-monthly', {
    endpoint: 'gabrielfalcao/lettuce/total_events_monthly',
    type: 'area',
    title: "Activity",
    subtitle: "Total monthly events",
    keyName: 'month',
    valueName: 'value',
    yTitle: 'Events',
    label: 'events'
});

// second row
makeXYGraph('#most-active-issues', {
    endpoint: 'gabrielfalcao/lettuce/most_active_issues',
    type: 'bar',
    title: "Most active issues",
    keyName: function (e) {
        return makeLink("http://github.com/gabrielfalcao/lettuce/issues/" + e.term,
                        "#" + e.term);
    },
    valueName: 'count',
    yTitle: 'Events',
    label: 'events'
});

<|endoftext|>