<commit_before>var canvasRenderer = L.canvas();

L.CanvasFlowmapLayer = L.GeoJSON.extend({
  options: {
    // this is only a default option example
    // developers will need to provide this with values unique to their data
    originAndDestinationFieldIds: {
      originUniqueIdField: 'origin_id',
      originGeometry: {
        x: 'origin_lon',
        y: 'origin_lat'
      },
      destinationUniqueIdField: 'destination_id',
      destinationGeometry: {
        x: 'destination_lon',
        y: 'destination_lat'
      }
    },

    canvasBezierStyle: {
      type: 'simple',
      symbol: {
        // use canvas styling options (compare to styling circle markers below)
        strokeStyle: 'rgba(255, 0, 51, 0.8)',
        lineWidth: 0.75,
        lineCap: 'round',
        shadowColor: 'rgb(255, 0, 51)',
        shadowBlur: 1.5
      }
    },

    // valid values: 'selection' or 'all'
    // use 'all' to display all Bezier paths immediately
    // use 'selection' if Bezier paths will be drawn with user interactions
    pathDisplayMode: 'all',

    pointToLayer: function(geoJsonPoint, latlng) {
      return L.circleMarker(latlng);
    },

    style: function(geoJsonFeature) {
      // use leaflet's path styling options
      if (geoJsonFeature.properties.isOrigin) {
        // developers can rely on the "isOrigin" property to set different symbols
        // for origin and destination circle markers
        return {
          renderer: canvasRenderer,
          radius: 5,
          weight: 1,
          color: 'rgb(195, 255, 62)',
          fillColor: 'rgba(195, 255, 62, 0.6)',
          fillOpacity: 0.6
        };
      } else {
        return {
          renderer: canvasRenderer,
          radius: 2.5,
          weight: 0.25,
          color: 'rgb(17, 142, 170)',
          fillColor: 'rgb(17, 142, 170)',
          fillOpacity: 0.7
        };
      }
    }
  },

  initialize: function(geojson, options) {
    L.setOptions(this, options);

    this._layers = {};

    // same as L.GeoJSON intialize method, but first performs custom geojson
    // data parsing and reformatting before eventually calling addData method
    if (geojson && this.options.originAndDestinationFieldIds) {
      this.setOriginAndDestinationGeoJsonPoints(geojson);
    }
  },

  setOriginAndDestinationGeoJsonPoints: function(geoJsonFeatureCollection) {
    if (geoJsonFeatureCollection.features) {
      var configOriginGeometryObject = this.options.originAndDestinationFieldIds.originGeometry;
      var configDestinationGeometryObject = this.options.originAndDestinationFieldIds.destinationGeometry;

      geoJsonFeatureCollection.features.forEach(function(feature, index) {
        if (feature.type === 'Feature' && feature.geometry && feature.geometry.type === 'Point') {
          // origin feature -- modify attributes and geometry
          feature.properties.isOrigin = true;
          feature.properties._isSelectedForPathDisplay = this.options.pathDisplayMode === 'all' ? true : false;
          feature.properties._uniqueId = index + '_origin';

          feature.geometry.coordinates = [
            feature.properties[configOriginGeometryObject.x],
            feature.properties[configOriginGeometryObject.y]
          ];

          // destination feature -- clone, modify, and push to feature collection
          var destinationFeature = JSON.parse(JSON.stringify(feature));

          destinationFeature.properties.isOrigin = false;
          destinationFeature.properties._isSelectedForPathDisplay = false;
          destinationFeature.properties._uniqueId = index + '_destination';

          destinationFeature.geometry.coordinates = [
            destinationFeature.properties[configDestinationGeometryObject.x],
            destinationFeature.properties[configDestinationGeometryObject.y]
          ];

          geoJsonFeatureCollection.features.push(destinationFeature);
        }
      }, this);

      // all origin/destination features are available for future internal used
      // but only a filtered subset of these are drawn on the map
      this.originAndDestinationGeoJsonPoints = geoJsonFeatureCollection;
      var geoJsonPointsToDraw = this._filterGeoJsonPointsToDraw(geoJsonFeatureCollection);
      this.addData(geoJsonPointsToDraw);
    } else {
      // TODO: improved handling of invalid incoming GeoJson FeatureCollection?
      this.originAndDestinationGeoJsonPoints = null;
    }

    return this;
  },

  _filterGeoJsonPointsToDraw: function(geoJsonFeatureCollection) {
    var newGeoJson = {
      type: 'FeatureCollection',
      features: []
    };

    var originUniqueIdValues = [];
    var destinationUniqueIdValues = [];

    var originUniqueIdField = this.options.originAndDestinationFieldIds.originUniqueIdField;
    var destinationUniqueIdField = this.options.originAndDestinationFieldIds.destinationUniqueIdField;

    geoJsonFeatureCollection.features.forEach(function(feature) {
      var isOrigin = feature.properties.isOrigin;

      if (isOrigin && originUniqueIdValues.indexOf(feature.properties[originUniqueIdField]) === -1) {
        originUniqueIdValues.push(feature.properties[originUniqueIdField]);
        newGeoJson.features.push(feature);
      } else if (!isOrigin && destinationUniqueIdValues.indexOf(feature.properties[destinationUniqueIdField]) === -1) {
        destinationUniqueIdValues.push(feature.properties[destinationUniqueIdField]);
        newGeoJson.features.push(feature);
      } else {
        // do not attempt to draw an origin or destination circle on the canvas if it is already in one of the tracking arrays
        return;
      }
    });

    return newGeoJson;
  },

  onAdd: function(map) {
    // call the L.GeoJSON onAdd method,
    // then continue with custom code
    L.GeoJSON.prototype.onAdd.call(this, map);

    // create new canvas element just for manually drawing bezier curves
    this._canvasElement = L.DomUtil.create('canvas', 'leaflet-zoom-animated');

    var originProp = L.DomUtil.testProp(['transformOrigin', 'WebkitTransformOrigin', 'msTransformOrigin']);
    this._canvasElement.style[originProp] = '50% 50%';

    var pane = map.getPane(this.options.pane);
    pane.insertBefore(this._canvasElement, pane.firstChild);

    this.on('click', this._modifyClickEvent, this);
    map.on('moveend', this._resetCanvas, this);
    map.on('resize', this._resizeCanvas, this);
    if (map.options.zoomAnimation && L.Browser.any3d) {
      map.on('zoomanim', this._animateZoom, this);
    }

    // calculate initial size and position of canvas
    // and draw its content for the first time
    this._resizeCanvas();
    this._resetCanvas();
  },

  onRemove: function(map) {
    // call the L.GeoJSON onRemove method,
    // then continue with custom code
    L.GeoJSON.prototype.onRemove.call(this, map);

    L.DomUtil.remove(this._canvasElement);

    this.off('click', this._modifyClickEvent, this);
    map.off('moveend', this._resetCanvas, this);
    map.off('resize', this._resizeCanvas, this);
    if (map.options.zoomAnimation) {
      map.off('zoomanim', this._animateZoom, this);
    }
  },

  _modifyClickEvent: function(e) {
    var odInfo = this._getSharedOriginOrDestinationFeatures(e.layer.feature);
    e.isOriginFeature = odInfo.isOriginFeature;
    e.sharedOriginFeatures = odInfo.sharedOriginFeatures;
    e.sharedDestinationFeatures = odInfo.sharedDestinationFeatures;
  },

  _getSharedOriginOrDestinationFeatures: function(testFeature) {
    var isOriginFeature = testFeature.properties.isOrigin;
    var sharedOriginFeatures = [];
    var sharedDestinationFeatures = [];

    if (isOriginFeature) {
      // for an ORIGIN point that was interacted with,
      // make an array of all other ORIGIN features with the same ORIGIN ID field
      var originUniqueIdField = this.options.originAndDestinationFieldIds.originUniqueIdField;
      var testFeatureOriginId = testFeature.properties[originUniqueIdField];
      sharedOriginFeatures = this.originAndDestinationGeoJsonPoints.features.filter(function(feature) {
        return feature.properties.isOrigin &&
          feature.properties[originUniqueIdField] === testFeatureOriginId;
      });
    } else {
      // for a DESTINATION point that was interacted with,
      // make an array of all other ORIGIN features with the same DESTINATION ID field
      var destinationUniqueIdField = this.options.originAndDestinationFieldIds.destinationUniqueIdField;
      var testFeatureDestinationId = testFeature.properties[destinationUniqueIdField];
      sharedDestinationFeatures = this.originAndDestinationGeoJsonPoints.features.filter(function(feature) {
        return feature.properties.isOrigin &&
          feature.properties[destinationUniqueIdField] === testFeatureDestinationId;
      });
    }

    return {
      isOriginFeature: isOriginFeature, // Boolean
      sharedOriginFeatures: sharedOriginFeatures, // Array of features
      sharedDestinationFeatures: sharedDestinationFeatures // Array of features
    };
  },

  selectFeaturesForPathDisplay: function(selectionFeatures, selectionMode) {
    this._applyFeaturesSelection(selectionFeatures, selectionMode, '_isSelectedForPathDisplay');
  },

  _applyFeaturesSelection: function(selectionFeatures, selectionMode, selectionAttributeName) {
    var selectionIds = selectionFeatures.map(function(feature) {
      return feature.properties._uniqueId;
    });

    if (selectionMode === 'SELECTION_NEW') {
      this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
        if (selectionIds.indexOf(feature.properties._uniqueId) > -1) {
          feature.properties[selectionAttributeName] = true;
        } else {
          feature.properties[selectionAttributeName] = false;
        }
      });
    } else if (selectionMode === 'SELECTION_ADD') {
      this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
        if (selectionIds.indexOf(feature.properties._uniqueId) > -1) {
          feature.properties[selectionAttributeName] = true;
        }
      });
    } else if (selectionMode === 'SELECTION_SUBTRACT') {
      this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
        if (selectionIds.indexOf(feature.properties._uniqueId) > -1) {
          feature.properties[selectionAttributeName] = false;
        }
      });
    } else {
      return;
    }

    this._resetCanvas();
  },

  _animateZoom: function(e) {
    // see: https://github.com/Leaflet/Leaflet.heat
    var scale = this._map.getZoomScale(e.zoom);
    var offset = this._map._getCenterOffset(e.center)._multiplyBy(-scale).subtract(this._map._getMapPanePos());

    if (L.DomUtil.setTransform) {
      L.DomUtil.setTransform(this._canvasElement, offset, scale);
    } else {
      this._canvasElement.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(offset) + ' scale(' + scale + ')';
    }
  },

  _resizeCanvas: function() {
    // update the canvas size
    var size = this._map.getSize();
    this._canvasElement.width = size.x;
    this._canvasElement.height = size.y;
  },

  _resetCanvas: function() {
    // update the canvas position and redraw its content
    var topLeft = this._map.containerPointToLayerPoint([0, 0]);
    L.DomUtil.setPosition(this._canvasElement, topLeft);
    this._redrawCanvas();
  },

  _redrawCanvas: function() {
    // draw canvas content
    if (this.originAndDestinationGeoJsonPoints) {
      this._clearCanvas();
      // loop over each of the "selected" features and re-draw the canvas paths
      this._drawSelectedCanvasPaths(false);
    }
  },

  _clearCanvas: function() {
    this._canvasElement.getContext('2d')
      .clearRect(0, 0, this._canvasElement.width, this._canvasElement.height);
  },

  _drawSelectedCanvasPaths: function(/*animate*/) {
    // var ctx = animate ? this._animationCanvasElement.getContext('2d') : this._canvasElement.getContext('2d');
    var ctx = this._canvasElement.getContext('2d');
    ctx.beginPath();

    var originAndDestinationFieldIds = this.options.originAndDestinationFieldIds;

    this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {

      if (feature.properties._isSelectedForPathDisplay) {
        var originXCoordinate = feature.properties[originAndDestinationFieldIds.originGeometry.x];
        var originYCoordinate = feature.properties[originAndDestinationFieldIds.originGeometry.y];
        var destinationXCoordinate = feature.properties[originAndDestinationFieldIds.destinationGeometry.x];
        var destinationYCoordinate = feature.properties[originAndDestinationFieldIds.destinationGeometry.y];

        // origin and destination points for drawing curved lines
        // ensure that canvas features will be drawn beyond +/-180 longitude
        // var originPoint = this._wrapAroundCanvasPointGeometry(new Point(originXCoordinate, originYCoordinate, spatialReference));
        // var destinationPoint = this._wrapAroundCanvasPointGeometry(new Point(destinationXCoordinate, destinationYCoordinate, spatialReference));

        // convert geometry to screen coordinates for canvas drawing
        var screenOriginPoint = this._map.latLngToContainerPoint(L.latLng([originYCoordinate, originXCoordinate]));
        var screenDestinationPoint = this._map.latLngToContainerPoint(L.latLng([destinationYCoordinate, destinationXCoordinate]));

        // get the canvas symbol properties,
        // and draw a curved canvas line

        // var symbol;
        // if (animate) {
        //   symbol = this._getSymbolProperties(feature, this.animatePathProperties);
        //   this._animateCanvasLineSymbol(ctx, symbol, screenOriginPoint, screenDestinationPoint);
        // } else {
        //   symbol = this._getSymbolProperties(feature, this.pathProperties);
        //   this._applyCanvasLineSymbol(ctx, symbol, screenOriginPoint, screenDestinationPoint);
        // }

        var symbol = this._getSymbolProperties(feature, this.options.canvasBezierStyle);
        this._applyCanvasLineSymbol(ctx, symbol, screenOriginPoint, screenDestinationPoint);
      }
    }, this);

    ctx.stroke();
    ctx.closePath();
  },

  _getSymbolProperties: function(feature, canvasSymbolConfig) {
    // get the canvas symbol properties
    var symbol;
    var filteredSymbols;
    if (canvasSymbolConfig.type === 'simple') {
      symbol = canvasSymbolConfig.symbol;
    } else if (canvasSymbolConfig.type === 'uniqueValue') {
      filteredSymbols = canvasSymbolConfig.uniqueValueInfos.filter(function(info) {
        return info.value === feature.properties[canvasSymbolConfig.field];
      });
      symbol = filteredSymbols[0].symbol;
    } else if (canvasSymbolConfig.type === 'classBreaks') {
      filteredSymbols = canvasSymbolConfig.classBreakInfos.filter(function(info) {
        return (
          info.classMinValue <= feature.properties[canvasSymbolConfig.field] &&
          info.classMaxValue >= feature.properties[canvasSymbolConfig.field]
        );
      });
      if (filteredSymbols.length) {
        symbol = filteredSymbols[0].symbol;
      } else {
        symbol = canvasSymbolConfig.defaultSymbol;
      }
    }
    return symbol;
  },

  _applyCanvasLineSymbol: function(ctx, symbolObject, screenOriginPoint, screenDestinationPoint) {
    ctx.lineCap = symbolObject.lineCap;
    ctx.lineWidth = symbolObject.lineWidth;
    ctx.strokeStyle = symbolObject.strokeStyle;
    ctx.shadowBlur = symbolObject.shadowBlur;
    ctx.shadowColor = symbolObject.shadowColor;
    ctx.moveTo(screenOriginPoint.x, screenOriginPoint.y);
    ctx.bezierCurveTo(screenOriginPoint.x, screenDestinationPoint.y, screenDestinationPoint.x, screenDestinationPoint.y, screenDestinationPoint.x, screenDestinationPoint.y);
  },
});

L.canvasFlowmapLayer = function(originAndDestinationGeoJsonPoints, opts) {
  return new L.CanvasFlowmapLayer(originAndDestinationGeoJsonPoints, opts);
};
<commit_msg>- modifying click and mouseover interactions - added wrap around antimeridian functionality<commit_after>var canvasRenderer = L.canvas();

L.CanvasFlowmapLayer = L.GeoJSON.extend({
  options: {
    // this is only a default option example
    // developers will need to provide this with values unique to their data
    originAndDestinationFieldIds: {
      originUniqueIdField: 'origin_id',
      originGeometry: {
        x: 'origin_lon',
        y: 'origin_lat'
      },
      destinationUniqueIdField: 'destination_id',
      destinationGeometry: {
        x: 'destination_lon',
        y: 'destination_lat'
      }
    },

    canvasBezierStyle: {
      type: 'simple',
      symbol: {
        // use canvas styling options (compare to styling circle markers below)
        strokeStyle: 'rgba(255, 0, 51, 0.8)',
        lineWidth: 0.75,
        lineCap: 'round',
        shadowColor: 'rgb(255, 0, 51)',
        shadowBlur: 1.5
      }
    },

    // valid values: 'selection' or 'all'
    // use 'all' to display all Bezier paths immediately
    // use 'selection' if Bezier paths will be drawn with user interactions
    pathDisplayMode: 'all',

    wrapAroundCanvas: true,

    pointToLayer: function(geoJsonPoint, latlng) {
      return L.circleMarker(latlng);
    },

    style: function(geoJsonFeature) {
      // use leaflet's path styling options
      if (geoJsonFeature.properties.isOrigin) {
        // developers can rely on the "isOrigin" property to set different symbols
        // for origin and destination circle markers
        return {
          renderer: canvasRenderer,
          radius: 5,
          weight: 1,
          color: 'rgb(195, 255, 62)',
          fillColor: 'rgba(195, 255, 62, 0.6)',
          fillOpacity: 0.6
        };
      } else {
        return {
          renderer: canvasRenderer,
          radius: 2.5,
          weight: 0.25,
          color: 'rgb(17, 142, 170)',
          fillColor: 'rgb(17, 142, 170)',
          fillOpacity: 0.7
        };
      }
    }
  },

  initialize: function(geojson, options) {
    L.setOptions(this, options);

    this._layers = {};

    // same as L.GeoJSON intialize method, but first performs custom geojson
    // data parsing and reformatting before eventually calling addData method
    if (geojson && this.options.originAndDestinationFieldIds) {
      this.setOriginAndDestinationGeoJsonPoints(geojson);
    }
  },

  setOriginAndDestinationGeoJsonPoints: function(geoJsonFeatureCollection) {
    if (geoJsonFeatureCollection.features) {
      var configOriginGeometryObject = this.options.originAndDestinationFieldIds.originGeometry;
      var configDestinationGeometryObject = this.options.originAndDestinationFieldIds.destinationGeometry;

      geoJsonFeatureCollection.features.forEach(function(feature, index) {
        if (feature.type === 'Feature' && feature.geometry && feature.geometry.type === 'Point') {
          // origin feature -- modify attributes and geometry
          feature.properties.isOrigin = true;
          feature.properties._isSelectedForPathDisplay = this.options.pathDisplayMode === 'all' ? true : false;
          feature.properties._uniqueId = index + '_origin';

          feature.geometry.coordinates = [
            feature.properties[configOriginGeometryObject.x],
            feature.properties[configOriginGeometryObject.y]
          ];

          // destination feature -- clone, modify, and push to feature collection
          var destinationFeature = JSON.parse(JSON.stringify(feature));

          destinationFeature.properties.isOrigin = false;
          destinationFeature.properties._isSelectedForPathDisplay = false;
          destinationFeature.properties._uniqueId = index + '_destination';

          destinationFeature.geometry.coordinates = [
            destinationFeature.properties[configDestinationGeometryObject.x],
            destinationFeature.properties[configDestinationGeometryObject.y]
          ];

          geoJsonFeatureCollection.features.push(destinationFeature);
        }
      }, this);

      // all origin/destination features are available for future internal used
      // but only a filtered subset of these are drawn on the map
      this.originAndDestinationGeoJsonPoints = geoJsonFeatureCollection;
      var geoJsonPointsToDraw = this._filterGeoJsonPointsToDraw(geoJsonFeatureCollection);
      this.addData(geoJsonPointsToDraw);
    } else {
      // TODO: improved handling of invalid incoming GeoJson FeatureCollection?
      this.originAndDestinationGeoJsonPoints = null;
    }

    return this;
  },

  _filterGeoJsonPointsToDraw: function(geoJsonFeatureCollection) {
    var newGeoJson = {
      type: 'FeatureCollection',
      features: []
    };

    var originUniqueIdValues = [];
    var destinationUniqueIdValues = [];

    var originUniqueIdField = this.options.originAndDestinationFieldIds.originUniqueIdField;
    var destinationUniqueIdField = this.options.originAndDestinationFieldIds.destinationUniqueIdField;

    geoJsonFeatureCollection.features.forEach(function(feature) {
      var isOrigin = feature.properties.isOrigin;

      if (isOrigin && originUniqueIdValues.indexOf(feature.properties[originUniqueIdField]) === -1) {
        originUniqueIdValues.push(feature.properties[originUniqueIdField]);
        newGeoJson.features.push(feature);
      } else if (!isOrigin && destinationUniqueIdValues.indexOf(feature.properties[destinationUniqueIdField]) === -1) {
        destinationUniqueIdValues.push(feature.properties[destinationUniqueIdField]);
        newGeoJson.features.push(feature);
      } else {
        // do not attempt to draw an origin or destination circle on the canvas if it is already in one of the tracking arrays
        return;
      }
    });

    return newGeoJson;
  },

  onAdd: function(map) {
    // call the L.GeoJSON onAdd method,
    // then continue with custom code
    L.GeoJSON.prototype.onAdd.call(this, map);

    // create new canvas element just for manually drawing bezier curves
    this._canvasElement = L.DomUtil.create('canvas', 'leaflet-zoom-animated');

    var originProp = L.DomUtil.testProp(['transformOrigin', 'WebkitTransformOrigin', 'msTransformOrigin']);
    this._canvasElement.style[originProp] = '50% 50%';

    var pane = map.getPane(this.options.pane);
    pane.insertBefore(this._canvasElement, pane.firstChild);

    this.on('click mouseover', this._modifyInteractionEvent, this);
    // map.on('moveend', this._resetCanvas, this);
    map.on('move', this._resetCanvas, this);
    map.on('resize', this._resizeCanvas, this);
    if (map.options.zoomAnimation && L.Browser.any3d) {
      map.on('zoomanim', this._animateZoom, this);
    }

    // calculate initial size and position of canvas
    // and draw its content for the first time
    this._resizeCanvas();
    this._resetCanvas();
  },

  onRemove: function(map) {
    // call the L.GeoJSON onRemove method,
    // then continue with custom code
    L.GeoJSON.prototype.onRemove.call(this, map);

    L.DomUtil.remove(this._canvasElement);

    this.off('click mouseover', this._modifyInteractionEvent, this);
    // map.off('moveend', this._resetCanvas, this);
    map.off('move', this._resetCanvas, this);
    map.off('resize', this._resizeCanvas, this);
    if (map.options.zoomAnimation) {
      map.off('zoomanim', this._animateZoom, this);
    }
  },

  _modifyInteractionEvent: function(e) {
    var odInfo = this._getSharedOriginOrDestinationFeatures(e.layer.feature);
    e.isOriginFeature = odInfo.isOriginFeature;
    e.sharedOriginFeatures = odInfo.sharedOriginFeatures;
    e.sharedDestinationFeatures = odInfo.sharedDestinationFeatures;
  },

  _getSharedOriginOrDestinationFeatures: function(testFeature) {
    var isOriginFeature = testFeature.properties.isOrigin;
    var sharedOriginFeatures = [];
    var sharedDestinationFeatures = [];

    if (isOriginFeature) {
      // for an ORIGIN point that was interacted with,
      // make an array of all other ORIGIN features with the same ORIGIN ID field
      var originUniqueIdField = this.options.originAndDestinationFieldIds.originUniqueIdField;
      var testFeatureOriginId = testFeature.properties[originUniqueIdField];
      sharedOriginFeatures = this.originAndDestinationGeoJsonPoints.features.filter(function(feature) {
        return feature.properties.isOrigin &&
          feature.properties[originUniqueIdField] === testFeatureOriginId;
      });
    } else {
      // for a DESTINATION point that was interacted with,
      // make an array of all other ORIGIN features with the same DESTINATION ID field
      var destinationUniqueIdField = this.options.originAndDestinationFieldIds.destinationUniqueIdField;
      var testFeatureDestinationId = testFeature.properties[destinationUniqueIdField];
      sharedDestinationFeatures = this.originAndDestinationGeoJsonPoints.features.filter(function(feature) {
        return feature.properties.isOrigin &&
          feature.properties[destinationUniqueIdField] === testFeatureDestinationId;
      });
    }

    return {
      isOriginFeature: isOriginFeature, // Boolean
      sharedOriginFeatures: sharedOriginFeatures, // Array of features
      sharedDestinationFeatures: sharedDestinationFeatures // Array of features
    };
  },

  selectFeaturesForPathDisplay: function(selectionFeatures, selectionMode) {
    this._applyFeaturesSelection(selectionFeatures, selectionMode, '_isSelectedForPathDisplay');
  },

  _applyFeaturesSelection: function(selectionFeatures, selectionMode, selectionAttributeName) {
    var selectionIds = selectionFeatures.map(function(feature) {
      return feature.properties._uniqueId;
    });

    if (selectionMode === 'SELECTION_NEW') {
      this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
        if (selectionIds.indexOf(feature.properties._uniqueId) > -1) {
          feature.properties[selectionAttributeName] = true;
        } else {
          feature.properties[selectionAttributeName] = false;
        }
      });
    } else if (selectionMode === 'SELECTION_ADD') {
      this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
        if (selectionIds.indexOf(feature.properties._uniqueId) > -1) {
          feature.properties[selectionAttributeName] = true;
        }
      });
    } else if (selectionMode === 'SELECTION_SUBTRACT') {
      this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {
        if (selectionIds.indexOf(feature.properties._uniqueId) > -1) {
          feature.properties[selectionAttributeName] = false;
        }
      });
    } else {
      return;
    }

    this._resetCanvas();
  },

  _animateZoom: function(e) {
    // see: https://github.com/Leaflet/Leaflet.heat
    var scale = this._map.getZoomScale(e.zoom);
    var offset = this._map._getCenterOffset(e.center)._multiplyBy(-scale).subtract(this._map._getMapPanePos());

    if (L.DomUtil.setTransform) {
      L.DomUtil.setTransform(this._canvasElement, offset, scale);
    } else {
      this._canvasElement.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(offset) + ' scale(' + scale + ')';
    }
  },

  _resizeCanvas: function() {
    // update the canvas size
    var size = this._map.getSize();
    this._canvasElement.width = size.x;
    this._canvasElement.height = size.y;
  },

  _resetCanvas: function() {
    // update the canvas position and redraw its content
    var topLeft = this._map.containerPointToLayerPoint([0, 0]);
    L.DomUtil.setPosition(this._canvasElement, topLeft);
    this._wrapGeoJsonCircleMarkers();
    this._redrawCanvas();
  },

  _wrapGeoJsonCircleMarkers: function() {
    // ensure that the GeoJson point features,
    // which are drawn on the map as individual CircleMarker layers,
    // will be drawn beyond +/-180 longitude
    this.eachLayer(function(layer) {
      var wrappedLatLng = this._wrapAroundLatLng(layer.getLatLng());
      layer.setLatLng(wrappedLatLng);
    }, this);
  },

  _redrawCanvas: function() {
    // draw canvas content (only the Bezier curves)
    if (this.originAndDestinationGeoJsonPoints) {
      this._clearCanvas();
      // loop over each of the "selected" features and re-draw the canvas paths
      this._drawSelectedCanvasPaths(false);
    }
  },

  _clearCanvas: function() {
    this._canvasElement.getContext('2d')
      .clearRect(0, 0, this._canvasElement.width, this._canvasElement.height);
  },

  _drawSelectedCanvasPaths: function(/*animate*/) {
    // var ctx = animate ? this._animationCanvasElement.getContext('2d') : this._canvasElement.getContext('2d');
    var ctx = this._canvasElement.getContext('2d');
    ctx.beginPath();

    var originAndDestinationFieldIds = this.options.originAndDestinationFieldIds;

    this.originAndDestinationGeoJsonPoints.features.forEach(function(feature) {

      if (feature.properties._isSelectedForPathDisplay) {
        var originXCoordinate = feature.properties[originAndDestinationFieldIds.originGeometry.x];
        var originYCoordinate = feature.properties[originAndDestinationFieldIds.originGeometry.y];
        var destinationXCoordinate = feature.properties[originAndDestinationFieldIds.destinationGeometry.x];
        var destinationYCoordinate = feature.properties[originAndDestinationFieldIds.destinationGeometry.y];

        // origin and destination points for drawing curved lines
        // ensure that canvas features will be drawn beyond +/-180 longitude
        var originLatLng = this._wrapAroundLatLng(L.latLng([originYCoordinate, originXCoordinate]));
        var destinationLatLng = this._wrapAroundLatLng(L.latLng([destinationYCoordinate, destinationXCoordinate]));

        // convert geometry to screen coordinates for canvas drawing
        var screenOriginPoint = this._map.latLngToContainerPoint(originLatLng);
        var screenDestinationPoint = this._map.latLngToContainerPoint(destinationLatLng);

        // get the canvas symbol properties,
        // and draw a curved canvas line

        // var symbol;
        // if (animate) {
        //   symbol = this._getSymbolProperties(feature, this.animatePathProperties);
        //   this._animateCanvasLineSymbol(ctx, symbol, screenOriginPoint, screenDestinationPoint);
        // } else {
        //   symbol = this._getSymbolProperties(feature, this.pathProperties);
        //   this._applyCanvasLineSymbol(ctx, symbol, screenOriginPoint, screenDestinationPoint);
        // }

        var symbol = this._getSymbolProperties(feature, this.options.canvasBezierStyle);
        this._applyCanvasLineSymbol(ctx, symbol, screenOriginPoint, screenDestinationPoint);
      }
    }, this);

    ctx.stroke();
    ctx.closePath();
  },

  _getSymbolProperties: function(feature, canvasSymbolConfig) {
    // get the canvas symbol properties
    var symbol;
    var filteredSymbols;
    if (canvasSymbolConfig.type === 'simple') {
      symbol = canvasSymbolConfig.symbol;
    } else if (canvasSymbolConfig.type === 'uniqueValue') {
      filteredSymbols = canvasSymbolConfig.uniqueValueInfos.filter(function(info) {
        return info.value === feature.properties[canvasSymbolConfig.field];
      });
      symbol = filteredSymbols[0].symbol;
    } else if (canvasSymbolConfig.type === 'classBreaks') {
      filteredSymbols = canvasSymbolConfig.classBreakInfos.filter(function(info) {
        return (
          info.classMinValue <= feature.properties[canvasSymbolConfig.field] &&
          info.classMaxValue >= feature.properties[canvasSymbolConfig.field]
        );
      });
      if (filteredSymbols.length) {
        symbol = filteredSymbols[0].symbol;
      } else {
        symbol = canvasSymbolConfig.defaultSymbol;
      }
    }
    return symbol;
  },

  _applyCanvasLineSymbol: function(ctx, symbolObject, screenOriginPoint, screenDestinationPoint) {
    ctx.lineCap = symbolObject.lineCap;
    ctx.lineWidth = symbolObject.lineWidth;
    ctx.strokeStyle = symbolObject.strokeStyle;
    ctx.shadowBlur = symbolObject.shadowBlur;
    ctx.shadowColor = symbolObject.shadowColor;
    ctx.moveTo(screenOriginPoint.x, screenOriginPoint.y);
    ctx.bezierCurveTo(screenOriginPoint.x, screenDestinationPoint.y, screenDestinationPoint.x, screenDestinationPoint.y, screenDestinationPoint.x, screenDestinationPoint.y);
  },

  _wrapAroundLatLng: function(latLng) {
    if (this.options.wrapAroundCanvas) {
      var wrappedLatLng = latLng.clone();
      var mapCenterLng = this._map.getCenter().lng;
      var wrapAroundDiff = mapCenterLng - wrappedLatLng.lng;
      if (wrapAroundDiff < -180 || wrapAroundDiff > 180) {
        wrappedLatLng.lng += (Math.round(wrapAroundDiff / 360) * 360);
      }
      return wrappedLatLng;
    } else {
      return latLng;
    }
  }
});

L.canvasFlowmapLayer = function(originAndDestinationGeoJsonPoints, opts) {
  return new L.CanvasFlowmapLayer(originAndDestinationGeoJsonPoints, opts);
};
<|endoftext|>


<commit_before>import Component from '@ember/component';
import { task } from 'ember-concurrency';
import FileSaverMixin from 'ember-cli-file-saver/mixins/file-saver';
import { inject as service } from '@ember/service';

export default Component.extend(FileSaverMixin,{
  flashMessages: service(),
  oss: task(function *() {
    let pdf = yield this.model.oss();
    let fileName = `${this.model.nomen} OSS`;
    this.saveFileAs(fileName, pdf, 'application/pdf');
    this.flashMessages.success("Downloaded!");
  }).drop(),
});
<commit_msg>Websafe OSS filename.<commit_after>import Component from '@ember/component';
import { computed } from '@ember/object';
import { task } from 'ember-concurrency';
import FileSaverMixin from 'ember-cli-file-saver/mixins/file-saver';
import { inject as service } from '@ember/service';

export default Component.extend(FileSaverMixin,{
  flashMessages: service(),
  filename: computed(
    'model',
    function() {
      return `${this.model.nomen} OSS`
        .replace(/ /g,'-')
        .replace(/_/g,'-')
        .replace(/[^\w-]+/g,'')
        .replace(/--+/g,'-');
    }
  ),
  oss: task(function *() {
    let pdf = yield this.model.oss();
    let fileName = this.filename;
    this.saveFileAs(fileName, pdf, 'application/pdf');
    this.flashMessages.success("Downloaded!");
  }).drop(),
});
<|endoftext|>


<commit_before>var express = require('express');
//var db = require('../db');
var assert = require('assert');
var mongoose = require('mongoose');
var User = require('../schemas/User');
var Challenge = require('../schemas/Challenge');
var ObjectId = require('mongoose').Types.ObjectId;

var router = express.Router();   // get router instance

// Connection URL
var db_url = 'mongodb://localhost:27017/openchallenge';

mongoose.connect(db_url);

router.get('/', function (req, res, next) {
    res.send("Ciao chicco!");
});

/*****************************************************************************
 *
 * API to manage CHALLENGES
 *
 */

router.post('/setWinners', function (req, res) {
    var obj = req.body;
    var errors = false;
    User.findByIdAndUpdate(
        obj.first,
        {$inc: {'gold': 1}},
        {safe: true, upsert: true},
        function (err) {
            errors = errors || err;
            User.findByIdAndUpdate(
                obj.second,
                {$inc: {'silver': 1}},
                {safe: true, upsert: true},
                function (err) {
                    errors = errors || err;
                    User.findByIdAndUpdate(
                        obj.third,
                        {$inc: {'bronze': 1}},
                        {safe: true, upsert: true},
                        function (err) {
                            errors = errors || err;
                            console.log(errors);
                            res.send(errors);
                        });
                });
        });
});

router.post('/newChallenge', function (req, res) {
    var obj = req.body;
    User.findOne({'uid': obj.organizer})
        .exec(function (err, user) {
            assert.equal(err, null);
            var challenge = new Challenge({
                name: obj.name,
                description: obj.description,
                rules: obj.rules,
                image: obj.image,
                location: {
                    address: obj.location.address,
                    lat: obj.location.lat,
                    long: obj.location.long
                },
                date: obj.date,
                organizer: user._id,
                participants: []
            });
            challenge.save(function (err) {
                if (err) {
                    res.send("Error");
                    console.log("Error saving new challenge");
                } else {
                    res.send("Saved!");
                }
            }).then(function (challenge) {                  // add challenge to user's organized list
                user.organizedChallenges.push(challenge);
            })
        });
});

router.get('/getNumParticipants/:id_chall/:user_uid', function (req, res, next) {
    var user_uid = req.params.user_uid;
    var chall_id = req.params.id_chall;
    User.findOne({'uid': user_uid})
        .exec(function (err, user) {
            Challenge.aggregate([
                {$match: {'_id': mongoose.Types.ObjectId(chall_id)}},
                { //add number participants field
                    $addFields: {
                        numParticipants: {$size: '$participants'}
                    }
                },
                { //select only participants array that will be populated later and numPart
                    $project: {
                        numParticipants: 1,
                        _id: 0,
                        participants: 1
                    }
                }

            ]).exec(function (err, chall) {
                if (err) res.send("Err");

                else {
                    //check if you participate in this challenge (we can change with joined challenges)
                    var part = chall[0].participants;
                    var found = false;
                    for (var i = 0; i < part.length; i++) {
                        if (part[i].toString() == user._id.toString()) {
                            found = true;
                            break;
                        }
                    }

                    Challenge.populate(chall,
                        {
                            path: 'participants',
                            select: 'picture',
                            options: {limit: 3}
                        },
                        function (err, challPop) {
                        //adding youparticipate field
                            challPop[0].joined = found;
                            res.send(challPop)
                        })
                }
            });
        });
});

router.get('/allChallenges', function (req, res, next) {

    Challenge.find()
        .populate('organizer')
        .populate({
            path: 'participants',
            select: 'username picture',
            options: {limit: 3}
        })
        .exec(function (error, challenge) {
            assert.equal(error, null);
            res.send(challenge);
        })
});

router.get('/addParticipant/:chall_id/:user_id', function (req, res) {
    var chall_id = req.params.chall_id;
    var user_id = req.params.user_id;
    User.findOneAndUpdate({'uid': user_id}, {$addToSet: {joinedChallenges: chall_id}}) // add to joined list
        .exec(function (err, user) {
            assert.equal(error, null);
            Challenge.findByIdAndUpdate(
                chall_id,
                {$addToSet: {"participants": user._id}},  // do not add if already present
                {safe: true, upsert: true},
                function (err) {
                    if (err) {
                        res.send('Error');
                        console.log(err);
                    }
                    else res.send('you participate now!')
                }
            );
        });
});

router.get('/removeParticipant/:chall_id/:user_id', function (req, res) {
    var chall_id = req.params.chall_id;
    var user_id = req.params.user_id;
    User.findOneAndUpdate({'uid': user_id}, {$pull: {joinedChallenges: chall_id}})  // remove from joined list
        .exec(function (err, user) {
            Challenge.findByIdAndUpdate(
                chall_id,
                {$pull: {"participants": user._id}},
                {safe: true, upsert: true},
                function (err) {
                    if (err) {
                        res.send('Error');
                        console.log(err);
                    }
                    else res.send('removed!');
                }
            );
        });

});

router.get('/getParticipants/:chall_id', function (req, res, next) {
    Challenge.findById(req.params.chall_id)
        .populate('participants')
        .exec(function (err, chall) {
            assert.equal(err, null);
            res.send(chall.participants);
        })
});

/*****************************************************************************
 *
 * API to manage USERS
 *
 */

router.post('/newUser', function (req, res, next) {
    var obj = req.body;
    var user = new User({
        username: obj.username,
        status: obj.status,
        picture: obj.picture,
        rate: 0,
        gold: 0,
        silver: 0,
        bronze: 0,
        uid: obj.uid,
        joinedChallenges: [],
        organizedChallenges: []
    });
    User.findOne({'username': user.username}).exec(function (err, u) {
        if (err) res.send("Error!");
        else if (u) {
            res.send("already exists");
        }
        else {
            user.save(function (err) {
                if (err) res.send("Error");
                else res.send("User " + user.username + " created!");
            });
        }
    });

});

router.get('deleteUser/:user', function (req, res) {
    User.deleteOne({_id: req.params.user})
        .exec(function (err) {
            assert.equal(err, null);
            res.send('deleted');
        })
});

router.get('/allUsers', function (req, res) {
    User.find(function (err, users) {
        assert.equal(err, null);
        res.send(users);
    });
});

router.get('/findUsers/:user', function (req, res) {
    var user = req.params.user;
    User.find({'username': new RegExp('^' + user)}).exec(function (err, users) {
        if (err) res.send('Error');
        else res.send(users);
    });
});

router.get('/findUserByUid/:uid', function (req, res) {
    var user_id = req.params.uid;
    User.findOne({'uid': user_id})
        .exec(function (err, user) {
            if (err) res.send("Error");
            if (user)
                res.send(user);
            else
                res.send("No user found");
        });
});

module.exports = router;
<commit_msg>fixed add and remove participant<commit_after>var express = require('express');
//var db = require('../db');
var assert = require('assert');
var mongoose = require('mongoose');
var User = require('../schemas/User');
var Challenge = require('../schemas/Challenge');
var ObjectId = require('mongoose').Types.ObjectId;

var router = express.Router();   // get router instance

// Connection URL
var db_url = 'mongodb://localhost:27017/openchallenge';

mongoose.connect(db_url);

router.get('/', function (req, res, next) {
    res.send("Ciao chicco!");
});

/*****************************************************************************
 *
 * API to manage CHALLENGES
 *
 */

router.post('/setWinners', function (req, res) {
    var obj = req.body;
    var errors = false;
    User.findByIdAndUpdate(
        obj.first,
        {$inc: {'gold': 1}},
        {safe: true, upsert: true},
        function (err) {
            errors = errors || err;
            User.findByIdAndUpdate(
                obj.second,
                {$inc: {'silver': 1}},
                {safe: true, upsert: true},
                function (err) {
                    errors = errors || err;
                    User.findByIdAndUpdate(
                        obj.third,
                        {$inc: {'bronze': 1}},
                        {safe: true, upsert: true},
                        function (err) {
                            errors = errors || err;
                            console.log(errors);
                            res.send(errors);
                        });
                });
        });
});

router.post('/newChallenge', function (req, res) {
    var obj = req.body;
    User.findOne({'uid': obj.organizer})
        .exec(function (err, user) {
            assert.equal(err, null);
            var challenge = new Challenge({
                name: obj.name,
                description: obj.description,
                rules: obj.rules,
                image: obj.image,
                location: {
                    address: obj.location.address,
                    lat: obj.location.lat,
                    long: obj.location.long
                },
                date: obj.date,
                organizer: user._id,
                participants: []
            });
            challenge.save(function (err) {
                if (err) {
                    res.send("Error");
                    console.log("Error saving new challenge");
                } else {
                    res.send("Saved!");
                }
            }).then(function (challenge) {                  // add challenge to user's organized list
                user.organizedChallenges.push(challenge);
            })
        });
});

router.get('/getNumParticipants/:id_chall/:user_uid', function (req, res, next) {
    var user_uid = req.params.user_uid;
    var chall_id = req.params.id_chall;
    User.findOne({'uid': user_uid})
        .exec(function (err, user) {
            Challenge.aggregate([
                {$match: {'_id': mongoose.Types.ObjectId(chall_id)}},
                { //add number participants field
                    $addFields: {
                        numParticipants: {$size: '$participants'}
                    }
                },
                { //select only participants array that will be populated later and numPart
                    $project: {
                        numParticipants: 1,
                        _id: 0,
                        participants: 1
                    }
                }

            ]).exec(function (err, chall) {
                if (err) res.send("Err");

                else {
                    //check if you participate in this challenge (we can change with joined challenges)
                    var part = chall[0].participants;
                    var found = false;
                    for (var i = 0; i < part.length; i++) {
                        if (part[i].toString() == user._id.toString()) {
                            found = true;
                            break;
                        }
                    }

                    Challenge.populate(chall,
                        {
                            path: 'participants',
                            select: 'picture',
                            options: {limit: 3}
                        },
                        function (err, challPop) {
                            //adding youparticipate field
                            challPop[0].joined = found;
                            res.send(challPop)
                        })
                }
            });
        });
});

router.get('/allChallenges', function (req, res, next) {

    Challenge.find()
        .populate('organizer')
        .populate({
            path: 'participants',
            select: 'username picture',
            options: {limit: 3}
        })
        .exec(function (error, challenge) {
            assert.equal(error, null);
            res.send(challenge);
        })
});

router.get('/addParticipant/:chall_id/:user_id', function (req, res) {
    var chall_id = req.params.chall_id;
    var user_id = req.params.user_id;
    User.findOneAndUpdate({'uid': user_id}, {$addToSet: {joinedChallenges: chall_id}}) // add to joined list
        .exec(function (err, user) {
            if (err) res.send("Errrrror");
            else {
                Challenge.findByIdAndUpdate(
                    chall_id,
                    {$addToSet: {"participants": user._id}},  // do not add if already present
                    {safe: true, upsert: true},
                    function (err) {
                        if (err) {
                            res.send('Error');
                            console.log(err);
                        }
                        else res.send('you participate now!')
                    }
                );
            }
        });
});

router.get('/removeParticipant/:chall_id/:user_id', function (req, res) {
    var chall_id = req.params.chall_id;
    var user_id = req.params.user_id;
    User.findOneAndUpdate({'uid': user_id}, {$pull: {joinedChallenges: chall_id}})  // remove from joined list
        .exec(function (err, user) {
            if (err) res.send("Error");
            else {
                Challenge.findByIdAndUpdate(
                    chall_id,
                    {$pull: {"participants": user._id}},
                    {safe: true, upsert: true},
                    function (err) {
                        if (err) {
                            res.send('Error');
                            console.log(err);
                        }
                        else res.send('removed!');
                    }
                );
            }
        });

});

router.get('/getParticipants/:chall_id', function (req, res, next) {
    Challenge.findById(req.params.chall_id)
        .populate('participants')
        .exec(function (err, chall) {
            assert.equal(err, null);
            res.send(chall.participants);
        })
});

/*****************************************************************************
 *
 * API to manage USERS
 *
 */

router.post('/newUser', function (req, res, next) {
    var obj = req.body;
    var user = new User({
        username: obj.username,
        status: obj.status,
        picture: obj.picture,
        rate: 0,
        gold: 0,
        silver: 0,
        bronze: 0,
        uid: obj.uid,
        joinedChallenges: [],
        organizedChallenges: []
    });
    User.findOne({'username': user.username}).exec(function (err, u) {
        if (err) res.send("Error!");
        else if (u) {
            res.send("already exists");
        }
        else {
            user.save(function (err) {
                if (err) res.send("Error");
                else res.send("User " + user.username + " created!");
            });
        }
    });

});

router.get('deleteUser/:user', function (req, res) {
    User.deleteOne({_id: req.params.user})
        .exec(function (err) {
            assert.equal(err, null);
            res.send('deleted');
        })
});

router.get('/allUsers', function (req, res) {
    User.find(function (err, users) {
        assert.equal(err, null);
        res.send(users);
    });
});

router.get('/findUsers/:user', function (req, res) {
    var user = req.params.user;
    User.find({'username': new RegExp('^' + user)}).exec(function (err, users) {
        if (err) res.send('Error');
        else res.send(users);
    });
});

router.get('/findUserByUid/:uid', function (req, res) {
    var user_id = req.params.uid;
    User.findOne({'uid': user_id})
        .exec(function (err, user) {
            if (err) res.send("Error");
            if (user)
                res.send(user);
            else
                res.send("No user found");
        });
});

module.exports = router;
<|endoftext|>


<commit_before>/**
 * Create self executing function to avoid global scope creation
 */
(function (angular, tinymce) {
    'use strict';
    angular
        .module('placesContent')
        .controller('ContentItemCtrl', ['$scope', 'Buildfire', 'DB', 'COLLECTIONS', '$routeParams', 'Location', 'Utils', '$timeout', 'EVENTS', 'PATHS', 'Messaging', 'item', 'placesInfo', 'DEFAULT_DATA','$rootScope',
            function ($scope, Buildfire, DB, COLLECTIONS, $routeParams, Location, Utils, $timeout, EVENTS, PATHS, Messaging, item, placesInfo, DEFAULT_DATA,$rootScope) {

                //Hide the INT header part.
                Buildfire.appearance.setHeaderVisibility(false);
                var isNewItemInserted = false;

                //Scroll current view to top when page loaded.
                Buildfire.navigation.scrollTop();

                var tmrDelayForItem = null
                    , Items = new DB(COLLECTIONS.Items)
                    , PlaceInfo = new DB(COLLECTIONS.PlaceInfo)
                    , updating = false;

                var background = new Buildfire.components.images.thumbnail("#background");

                var placeInfoData;
                if (placesInfo) {
                    placeInfoData = placesInfo;
                }
                else {
                    placeInfoData = DEFAULT_DATA.PLACE_INFO;
                }

                $scope.itemShow = 'Content';

                var ContentItem = this;
                ContentItem.currentAddress = null;
                ContentItem.validCoordinatesFailure = false;
                ContentItem.currentCoordinates = null;

                if (item) {
                    ContentItem.item = item;
                    ContentItem.masterItem = angular.copy(ContentItem.item);
                }
                else {
                    ContentItem.item = angular.copy(DEFAULT_DATA.ITEM);
                    if ($routeParams.sectionId != 'allitems')
                        ContentItem.item.data.sections.push($routeParams.sectionId);
                    ContentItem.masterItem = angular.copy(ContentItem.item);
                }

                if (ContentItem.item.data && ContentItem.item.data.backgroundImage) {
                    background.loadbackground(ContentItem.item.data.backgroundImage);
                }

                background.onChange = function (url) {
                    ContentItem.item.data.backgroundImage = url;
                    if (!$scope.$$phase && !$scope.$root.$$phase) {
                        $scope.$apply();
                    }
                };

                background.onDelete = function (url) {
                    ContentItem.item.data.backgroundImage = "";
                    if (!$scope.$$phase && !$scope.$root.$$phase) {
                        $scope.$apply();
                    }
                };

                //option for wysiwyg
                ContentItem.bodyWYSIWYGOptions = {
                    plugins: 'advlist autolink link image lists charmap print preview',
                    skin: 'lightgray',
                    trusted: true,
                    theme: 'modern',
                    plugin_preview_width : "500",
                    plugin_preview_height : "500"
                };
                // create a new instance of the buildfire action Items
                ContentItem.linkEditor = new Buildfire.components.actionItems.sortableList("#actionItems");
                // this method will be called when a new item added to the list
                ContentItem.linkEditor.onAddItems = function (items) {
                    if (!ContentItem.item.data.links)
                        ContentItem.item.data.links = [];
                    ContentItem.item.data.links.push(items);
                    if (!$scope.$$phase)$scope.$digest();
                };
                // this method will be called when an item deleted from the list
                ContentItem.linkEditor.onDeleteItem = function (item, index) {
                    ContentItem.item.data.links.splice(index, 1);
                    if (!$scope.$$phase)$scope.$digest();
                };
                // this method will be called when you edit item details
                ContentItem.linkEditor.onItemChange = function (item, index) {
                    ContentItem.item.data.links.splice(index, 1, item);
                    if (!$scope.$$phase)$scope.$digest();
                };
                // this method will be called when you change the order of items
                ContentItem.linkEditor.onOrderChange = function (item, oldIndex, newIndex) {
                    var temp = ContentItem.item.data.links[oldIndex];
                    ContentItem.item.data.links[oldIndex] = ContentItem.item.data.links[newIndex];
                    ContentItem.item.data.links[newIndex] = temp;
                    if (!$scope.$$phase)$scope.$digest();
                };

                /**
                 * Initialize the carousel and links
                 */
                if (ContentItem.item.data.links)
                    ContentItem.linkEditor.loadItems(ContentItem.item.data.links);
                if (ContentItem.item.data.address && ContentItem.item.data.address.aName) {
                    ContentItem.currentAddress = ContentItem.item.data.address.aName;
                    ContentItem.currentCoordinates = [ContentItem.item.data.address.lng, ContentItem.item.data.address.lat];
                }

                /**
                 * This updateMasterItem will update the ContentMedia.masterItem with passed item
                 * @param item
                 */
                function updateMasterItem(item) {
                    ContentItem.masterItem = angular.copy(item);
                }

                /**
                 * This resetItem will reset the ContentMedia.item with ContentMedia.masterItem
                 */
                function resetItem() {
                    ContentItem.item = angular.copy(ContentItem.masterItem);
                }

                /**
                 * isUnChanged to check whether there is change in controller media item or not
                 * @param item
                 * @returns {*|boolean}
                 */
                function isUnChanged(item) {
                    return angular.equals(item, ContentItem.masterItem);
                }

                function insertAndUpdate(_item) {
                    updating = true;
                    if (_item.id) {
                        Items.update(_item.id, _item.data).then(function (data) {
                            updating = false;
                        }, function (err) {
                            updating = false;
                            //console.log('Error while updating data---', err);
                        });
                    }
                    else if(!isNewItemInserted){
                        isNewItemInserted = true;
                        _item.data.rank = (placeInfoData.data.content.rankOfLastItemItems || 0) + 10;
                        _item.data.dateCreated = new Date();
                        Items.insert(_item.data).then(function (data) {
                            if (data && data.id) {
                                ContentItem.item.data.deepLinkUrl = Buildfire.deeplink.createLink({id: data.id});
                                ContentItem.item.id = data.id;
                                updateMasterItem(ContentItem.item);
                                placeInfoData.data.content.rankOfLastItemItems = _item.data.rank;
                                PlaceInfo.save(placeInfoData.data).then(function (data) {
                                    updating = false;
                                }, function (err) {
                                    updating = false;
                                });
                            }
                            else {
                                //isNewItemInserted = false;
                                updating = false;
                            }
                        }, function (err) {
                            //resetItem();
                            updating = false;
                            //isNewItemInserted = false;
                        });
                    }
                }

                /**
                 * updateItemsWithDelay called when ever there is some change in current media item
                 * @param _item
                 */
                function updateItemsWithDelay(_item) {
                    if (updating)
                        return;
                    if (tmrDelayForItem) {
                       $timeout.cancel(tmrDelayForItem);
                    }
                    ContentItem.isItemValid = isValidItem(ContentItem.item.data);
                    if (_item && !isUnChanged(_item) && ContentItem.isItemValid) {
                        tmrDelayForItem = $timeout(function () {
                            insertAndUpdate(_item);
                        }, 300);
                    }
                }

                //init();
                ContentItem.addListImage = function () {
                    var options = {showIcons: false, multiSelection: false},
                        listImgCB = function (error, result) {
                            if (error) {
                                console.error('Error:', error);
                            } else {
                                ContentItem.item.data.listImage = result.selectedFiles && result.selectedFiles[0] || null;
                                if (!$scope.$$phase)$scope.$digest();
                            }
                        };
                    Buildfire.imageLib.showDialog(options, listImgCB);
                };
                ContentItem.removeListImage = function () {
                    ContentItem.item.data.listImage = null;
                };
                /**
                 * done will close the single item view
                 */
                ContentItem.done = function () {
                    if ($routeParams.sectionId != 'allitems') {
                        Location.go('#/items/' + $routeParams.sectionId);
                    }
                    else {
                        Location.go('#/allitems')
                    }
                };
                ContentItem.setLocation = function (data) {
                    ContentItem.item.data.address = {
                        lng: data.coordinates[0],
                        lat: data.coordinates[1],
                        aName: data.location
                    };
                    ContentItem.currentAddress = data.location;
                    ContentItem.currentCoordinates = data.coordinates;
                    if (!$scope.$$phase)$scope.$digest();
                };
                ContentItem.setDraggedLocation = function (data) {
                    ContentItem.item.data.address = {
                        lng: data.coordinates[0],
                        lat: data.coordinates[1],
                        aName: data.location
                    };
                    ContentItem.currentAddress = data.location;
                    ContentItem.currentCoordinates = data.coordinates;
                    if (!$scope.$$phase)$scope.$digest();
                };
                ContentItem.setCoordinates = function () {
                    var latlng='';
                    console.log('ng-enter---------------------called------------------',ContentItem.currentAddress);
                    function successCallback(resp) {
                        if (resp) {
                            ContentItem.item.data.address = {
                                lng: ContentItem.currentAddress.split(",")[1].trim(),
                                lat: ContentItem.currentAddress.split(",")[0].trim(),
                                aName: ContentItem.currentAddress
                            };
                            ContentItem.currentCoordinates = [ContentItem.currentAddress.split(",")[1].trim(), ContentItem.currentAddress.split(",")[0].trim()];
                        } else {
                            //errorCallback();
                        }
                    }

                    function errorCallback(err) {
                        ContentItem.validCoordinatesFailure = true;
                        $timeout(function () {
                            ContentItem.validCoordinatesFailure = false;
                        }, 5000);
                    }
                    if(ContentItem.currentAddress){
                        latlng=ContentItem.currentAddress.split(',')[1]+","+ContentItem.currentAddress.split(',')[0]
                    }

                    Utils.validLongLats(latlng).then(successCallback, errorCallback);
                };
                ContentItem.clearData = function () {
                    if (!ContentItem.currentAddress) {
                        ContentItem.item.data.address = {
                            lng: '',
                            lat: '',
                            aName: ''
                        };
                        ContentItem.currentCoordinates = null;
                    }
                };

                ContentItem.validCopyAddressFailure = false;
                ContentItem.locationAutocompletePaste = function () {
                    function error() {
                        ContentItem.validCopyAddressFailure = true;
                        $timeout(function () {
                            ContentItem.validCopyAddressFailure = false;
                        }, 5000);

                    }
                    $timeout(function () {
                        console.log('val>>>',$("#googleMapAutocomplete").val());
                        console.log('.pac-container .pac-item',$(".pac-container .pac-item").length);
                        if ($(".pac-container .pac-item").length) {
                            var firstResult = $(".pac-container .pac-item:first").find('.pac-matched').map(function(){
                                    return $(this).text();
                                }).get().join() + ', ' + $(".pac-container .pac-item:first").find('span:last').text();
                            console.log('firstResult', firstResult);
                            var geocoder = new google.maps.Geocoder();
                            geocoder.geocode({"address": firstResult}, function (results, status) {
                                if (status == google.maps.GeocoderStatus.OK) {
                                    var lat = results[0].geometry.location.lat(),
                                        lng = results[0].geometry.location.lng();
                                    ContentItem.setLocation({location: firstResult, coordinates: [lng, lat]});
                                    $("#googleMapAutocomplete").blur();
                                }
                                else {
                                    error();
                                }
                            });
                        }
                        else {
                            error();
                        }
                    }, 1000);

                };

                //to validate the item
                function isValidItem(item) {
                    return item.itemTitle;
                }

                if($rootScope.dontPropagate == true)
                    $rootScope.dontPropagate = false;
                else
                Messaging.sendMessageToWidget({
                    name: EVENTS.ROUTE_CHANGE,
                    message: {
                        path: PATHS.ITEM,
                        //id: ContentItem.item ? ContentItem.item.id : "",
                        id: $routeParams.itemId,
                        secId: $routeParams.sectionId
                    }
                });

                $scope.$watch(function () {
                    return ContentItem.item;
                }, updateItemsWithDelay, true);
            }]);
})(window.angular, window.tinymce);
<commit_msg>google map paste issue fixed<commit_after>/**
 * Create self executing function to avoid global scope creation
 */
(function (angular, tinymce) {
    'use strict';
    angular
        .module('placesContent')
        .controller('ContentItemCtrl', ['$scope', 'Buildfire', 'DB', 'COLLECTIONS', '$routeParams', 'Location', 'Utils', '$timeout', 'EVENTS', 'PATHS', 'Messaging', 'item', 'placesInfo', 'DEFAULT_DATA','$rootScope',
            function ($scope, Buildfire, DB, COLLECTIONS, $routeParams, Location, Utils, $timeout, EVENTS, PATHS, Messaging, item, placesInfo, DEFAULT_DATA,$rootScope) {

                //Hide the INT header part.
                Buildfire.appearance.setHeaderVisibility(false);
                var isNewItemInserted = false;

                //Scroll current view to top when page loaded.
                Buildfire.navigation.scrollTop();

                var tmrDelayForItem = null
                    , Items = new DB(COLLECTIONS.Items)
                    , PlaceInfo = new DB(COLLECTIONS.PlaceInfo)
                    , updating = false;

                var background = new Buildfire.components.images.thumbnail("#background");

                var placeInfoData;
                if (placesInfo) {
                    placeInfoData = placesInfo;
                }
                else {
                    placeInfoData = DEFAULT_DATA.PLACE_INFO;
                }

                $scope.itemShow = 'Content';

                var ContentItem = this;
                ContentItem.currentAddress = null;
                ContentItem.validCoordinatesFailure = false;
                ContentItem.currentCoordinates = null;

                if (item) {
                    ContentItem.item = item;
                    ContentItem.masterItem = angular.copy(ContentItem.item);
                }
                else {
                    ContentItem.item = angular.copy(DEFAULT_DATA.ITEM);
                    if ($routeParams.sectionId != 'allitems')
                        ContentItem.item.data.sections.push($routeParams.sectionId);
                    ContentItem.masterItem = angular.copy(ContentItem.item);
                }

                if (ContentItem.item.data && ContentItem.item.data.backgroundImage) {
                    background.loadbackground(ContentItem.item.data.backgroundImage);
                }

                background.onChange = function (url) {
                    ContentItem.item.data.backgroundImage = url;
                    if (!$scope.$$phase && !$scope.$root.$$phase) {
                        $scope.$apply();
                    }
                };

                background.onDelete = function (url) {
                    ContentItem.item.data.backgroundImage = "";
                    if (!$scope.$$phase && !$scope.$root.$$phase) {
                        $scope.$apply();
                    }
                };

                //option for wysiwyg
                ContentItem.bodyWYSIWYGOptions = {
                    plugins: 'advlist autolink link image lists charmap print preview',
                    skin: 'lightgray',
                    trusted: true,
                    theme: 'modern',
                    plugin_preview_width : "500",
                    plugin_preview_height : "500"
                };
                // create a new instance of the buildfire action Items
                ContentItem.linkEditor = new Buildfire.components.actionItems.sortableList("#actionItems");
                // this method will be called when a new item added to the list
                ContentItem.linkEditor.onAddItems = function (items) {
                    if (!ContentItem.item.data.links)
                        ContentItem.item.data.links = [];
                    ContentItem.item.data.links.push(items);
                    if (!$scope.$$phase)$scope.$digest();
                };
                // this method will be called when an item deleted from the list
                ContentItem.linkEditor.onDeleteItem = function (item, index) {
                    ContentItem.item.data.links.splice(index, 1);
                    if (!$scope.$$phase)$scope.$digest();
                };
                // this method will be called when you edit item details
                ContentItem.linkEditor.onItemChange = function (item, index) {
                    ContentItem.item.data.links.splice(index, 1, item);
                    if (!$scope.$$phase)$scope.$digest();
                };
                // this method will be called when you change the order of items
                ContentItem.linkEditor.onOrderChange = function (item, oldIndex, newIndex) {
                    var temp = ContentItem.item.data.links[oldIndex];
                    ContentItem.item.data.links[oldIndex] = ContentItem.item.data.links[newIndex];
                    ContentItem.item.data.links[newIndex] = temp;
                    if (!$scope.$$phase)$scope.$digest();
                };

                /**
                 * Initialize the carousel and links
                 */
                if (ContentItem.item.data.links)
                    ContentItem.linkEditor.loadItems(ContentItem.item.data.links);
                if (ContentItem.item.data.address && ContentItem.item.data.address.aName) {
                    ContentItem.currentAddress = ContentItem.item.data.address.aName;
                    ContentItem.currentCoordinates = [ContentItem.item.data.address.lng, ContentItem.item.data.address.lat];
                }

                /**
                 * This updateMasterItem will update the ContentMedia.masterItem with passed item
                 * @param item
                 */
                function updateMasterItem(item) {
                    ContentItem.masterItem = angular.copy(item);
                }

                /**
                 * This resetItem will reset the ContentMedia.item with ContentMedia.masterItem
                 */
                function resetItem() {
                    ContentItem.item = angular.copy(ContentItem.masterItem);
                }

                /**
                 * isUnChanged to check whether there is change in controller media item or not
                 * @param item
                 * @returns {*|boolean}
                 */
                function isUnChanged(item) {
                    return angular.equals(item, ContentItem.masterItem);
                }

                function insertAndUpdate(_item) {
                    updating = true;
                    if (_item.id) {
                        Items.update(_item.id, _item.data).then(function (data) {
                            updating = false;
                        }, function (err) {
                            updating = false;
                            //console.log('Error while updating data---', err);
                        });
                    }
                    else if(!isNewItemInserted){
                        isNewItemInserted = true;
                        _item.data.rank = (placeInfoData.data.content.rankOfLastItemItems || 0) + 10;
                        _item.data.dateCreated = new Date();
                        Items.insert(_item.data).then(function (data) {
                            if (data && data.id) {
                                ContentItem.item.data.deepLinkUrl = Buildfire.deeplink.createLink({id: data.id});
                                ContentItem.item.id = data.id;
                                updateMasterItem(ContentItem.item);
                                placeInfoData.data.content.rankOfLastItemItems = _item.data.rank;
                                PlaceInfo.save(placeInfoData.data).then(function (data) {
                                    updating = false;
                                }, function (err) {
                                    updating = false;
                                });
                            }
                            else {
                                //isNewItemInserted = false;
                                updating = false;
                            }
                        }, function (err) {
                            //resetItem();
                            updating = false;
                            //isNewItemInserted = false;
                        });
                    }
                }

                /**
                 * updateItemsWithDelay called when ever there is some change in current media item
                 * @param _item
                 */
                function updateItemsWithDelay(_item) {
                    if (updating)
                        return;
                    if (tmrDelayForItem) {
                       $timeout.cancel(tmrDelayForItem);
                    }
                    ContentItem.isItemValid = isValidItem(ContentItem.item.data);
                    if (_item && !isUnChanged(_item) && ContentItem.isItemValid) {
                        tmrDelayForItem = $timeout(function () {
                            insertAndUpdate(_item);
                        }, 300);
                    }
                }

                //init();
                ContentItem.addListImage = function () {
                    var options = {showIcons: false, multiSelection: false},
                        listImgCB = function (error, result) {
                            if (error) {
                                console.error('Error:', error);
                            } else {
                                ContentItem.item.data.listImage = result.selectedFiles && result.selectedFiles[0] || null;
                                if (!$scope.$$phase)$scope.$digest();
                            }
                        };
                    Buildfire.imageLib.showDialog(options, listImgCB);
                };
                ContentItem.removeListImage = function () {
                    ContentItem.item.data.listImage = null;
                };
                /**
                 * done will close the single item view
                 */
                ContentItem.done = function () {
                    if ($routeParams.sectionId != 'allitems') {
                        Location.go('#/items/' + $routeParams.sectionId);
                    }
                    else {
                        Location.go('#/allitems')
                    }
                };
                ContentItem.setLocation = function (data) {
                    ContentItem.item.data.address = {
                        lng: data.coordinates[0],
                        lat: data.coordinates[1],
                        aName: data.location
                    };
                    ContentItem.currentAddress = data.location;
                    ContentItem.currentCoordinates = data.coordinates;
                    if (!$scope.$$phase)$scope.$digest();
                };
                ContentItem.setDraggedLocation = function (data) {
                    ContentItem.item.data.address = {
                        lng: data.coordinates[0],
                        lat: data.coordinates[1],
                        aName: data.location
                    };
                    ContentItem.currentAddress = data.location;
                    ContentItem.currentCoordinates = data.coordinates;
                    if (!$scope.$$phase)$scope.$digest();
                };
                ContentItem.setCoordinates = function () {
                    var latlng='';
                    console.log('ng-enter---------------------called------------------',ContentItem.currentAddress);
                    function successCallback(resp) {
                        if (resp) {
                            ContentItem.item.data.address = {
                                lng: ContentItem.currentAddress.split(",")[1].trim(),
                                lat: ContentItem.currentAddress.split(",")[0].trim(),
                                aName: ContentItem.currentAddress
                            };
                            ContentItem.currentCoordinates = [ContentItem.currentAddress.split(",")[1].trim(), ContentItem.currentAddress.split(",")[0].trim()];
                        } else {
                            //errorCallback();
                        }
                    }

                    function errorCallback(err) {
                        ContentItem.validCoordinatesFailure = true;
                        $timeout(function () {
                            ContentItem.validCoordinatesFailure = false;
                        }, 5000);
                    }
                    if(ContentItem.currentAddress){
                        latlng=ContentItem.currentAddress.split(',')[1]+","+ContentItem.currentAddress.split(',')[0]
                    }

                    Utils.validLongLats(latlng).then(successCallback, errorCallback);
                };
                ContentItem.clearData = function () {
                    if (!ContentItem.currentAddress) {
                        ContentItem.item.data.address = {
                            lng: '',
                            lat: '',
                            aName: ''
                        };
                        ContentItem.currentCoordinates = null;
                    }
                };

                ContentItem.validCopyAddressFailure = false;
                ContentItem.locationAutocompletePaste = function () {
                    function error() {
                        ContentItem.validCopyAddressFailure = true;
                        $timeout(function () {
                            ContentItem.validCopyAddressFailure = false;
                        }, 5000);

                    }
                    $timeout(function () {
                        console.log('val>>>',$("#googleMapAutocomplete").val());
                        console.log('.pac-container .pac-item',$(".pac-container .pac-item").length);
                        if ($(".pac-container .pac-item").length) {
                            var firstResult = $(".pac-container .pac-item:first").find('.pac-matched').map(function(){
                                return $(this).text();
                            }).get().join(); // + ', ' + $(".pac-container .pac-item:first").find('span:last').text();
                            console.log('firstResult', firstResult);
                            var geocoder = new google.maps.Geocoder();
                            geocoder.geocode({"address": firstResult}, function (results, status) {
                                if (status == google.maps.GeocoderStatus.OK) {
                                    var lat = results[0].geometry.location.lat(),
                                        lng = results[0].geometry.location.lng();
                                    ContentItem.setLocation({location: firstResult, coordinates: [lng, lat]});
                                    $("#googleMapAutocomplete").blur();
                                }
                                else {
                                    error();
                                }
                            });
                        }
                        else {
                            error();
                        }
                    }, 1000);

                };

                //to validate the item
                function isValidItem(item) {
                    return item.itemTitle;
                }

                if($rootScope.dontPropagate == true)
                    $rootScope.dontPropagate = false;
                else
                Messaging.sendMessageToWidget({
                    name: EVENTS.ROUTE_CHANGE,
                    message: {
                        path: PATHS.ITEM,
                        //id: ContentItem.item ? ContentItem.item.id : "",
                        id: $routeParams.itemId,
                        secId: $routeParams.sectionId
                    }
                });

                $scope.$watch(function () {
                    return ContentItem.item;
                }, updateItemsWithDelay, true);
            }]);
})(window.angular, window.tinymce);
<|endoftext|>


<commit_before>'use strict';

// MODULES //

var resolve = require( 'path' ).resolve;
var exec = require( 'child_process' ).exec;
var tape = require( 'tape' );
var IS_BROWSER = require( '@stdlib/assert/is-browser' );
var IS_WINDOWS = require( '@stdlib/assert/is-windows' );
var readFileSync = require( '@stdlib/fs/read-file' ).sync;

// VARIABLES //

var fpath = resolve( __dirname, '..', 'bin', 'cli' );
var opts = {
	'skip': IS_BROWSER || IS_WINDOWS
};

// FIXTURES //

var PKG_VERSION = require('./../package.json' ).version;

// TESTS //

tape( 'command-line interface', function test( t ) {
	t.ok( true, __filename );
	t.end();
});

tape( 'when invoked with a `--help` flag, the command-line interface prints the help text to `stderr`', opts, function test( t ) {
	var expected;
	var cmd;

	expected = readFileSync( resolve( __dirname, '..', 'bin', 'usage.txt' ), {
		'encoding': 'utf8'
	});
	cmd = [
		process.execPath,
		fpath,
		'--help'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), expected+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `-h` flag, the command-line interface prints the help text to `stderr`', opts, function test( t ) {
	var expected;
	var cmd;

	expected = readFileSync( resolve( __dirname, '..', 'bin', 'usage.txt' ), {
		'encoding': 'utf8'
	});
	cmd = [
		process.execPath,
		fpath,
		'-h'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), expected+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `--version` flag, the command-line interface prints the version to `stderr`', opts, function test( t ) {
	var cmd = [
		process.execPath,
		fpath,
		'--version'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), PKG_VERSION+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `-V` flag, the command-line interface prints the version to `stderr`', opts, function test( t ) {
	var cmd = [
		process.execPath,
		fpath,
		'-V'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), PKG_VERSION+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'the function returns an HTML string for inlining an SVG equation in Markdown', opts, function test( t ) {
	var expected;
	var file;
	var cmd;

	cmd = [
		process.execPath,
		fpath,
		'--class \'equation\'',
		'--align \'center\'',
		'--raw \'y = mx + b\'',
		'--label \'eq:line\''
	];

	file = resolve( __dirname, 'fixtures', 'expected.txt' );
	expected = readFileSync( file );

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), expected.toString(), 'returns expected value' );
			t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' );
		}
		t.end();
	}
});

// TODO: add test for when an error is encountered
<commit_msg>Fix description<commit_after>'use strict';

// MODULES //

var resolve = require( 'path' ).resolve;
var exec = require( 'child_process' ).exec;
var tape = require( 'tape' );
var IS_BROWSER = require( '@stdlib/assert/is-browser' );
var IS_WINDOWS = require( '@stdlib/assert/is-windows' );
var readFileSync = require( '@stdlib/fs/read-file' ).sync;

// VARIABLES //

var fpath = resolve( __dirname, '..', 'bin', 'cli' );
var opts = {
	'skip': IS_BROWSER || IS_WINDOWS
};

// FIXTURES //

var PKG_VERSION = require('./../package.json' ).version;

// TESTS //

tape( 'command-line interface', function test( t ) {
	t.ok( true, __filename );
	t.end();
});

tape( 'when invoked with a `--help` flag, the command-line interface prints the help text to `stderr`', opts, function test( t ) {
	var expected;
	var cmd;

	expected = readFileSync( resolve( __dirname, '..', 'bin', 'usage.txt' ), {
		'encoding': 'utf8'
	});
	cmd = [
		process.execPath,
		fpath,
		'--help'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), expected+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `-h` flag, the command-line interface prints the help text to `stderr`', opts, function test( t ) {
	var expected;
	var cmd;

	expected = readFileSync( resolve( __dirname, '..', 'bin', 'usage.txt' ), {
		'encoding': 'utf8'
	});
	cmd = [
		process.execPath,
		fpath,
		'-h'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), expected+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `--version` flag, the command-line interface prints the version to `stderr`', opts, function test( t ) {
	var cmd = [
		process.execPath,
		fpath,
		'--version'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), PKG_VERSION+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `-V` flag, the command-line interface prints the version to `stderr`', opts, function test( t ) {
	var cmd = [
		process.execPath,
		fpath,
		'-V'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), PKG_VERSION+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'the command-line interface generates an HTML string for inlining an SVG equation in Markdown', opts, function test( t ) {
	var expected;
	var file;
	var cmd;

	cmd = [
		process.execPath,
		fpath,
		'--class \'equation\'',
		'--align \'center\'',
		'--raw \'y = mx + b\'',
		'--label \'eq:line\''
	];

	file = resolve( __dirname, 'fixtures', 'expected.txt' );
	expected = readFileSync( file );

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), expected.toString(), 'returns expected value' );
			t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' );
		}
		t.end();
	}
});

// TODO: add test for when an error is encountered
<|endoftext|>