<commit_before>/*jslint nomen: true */
/*globals define: true */

define(function (require) {
  'use strict';

  var $ = require('jquery');
  var _ = require('lib/underscore');
  var settings = require('settings');
  var api = require('api');
  var L = require('lib/leaflet');

  return function (app, mapContainerId) {

    var map, marker, circle;
    var markers = {};
    var numObjectsOnMap = 0;
    var parcelIdsOnTheMap = {};
    var parcelsLayerGroup = new L.LayerGroup();
    var doneMarkersLayer = new L.LayerGroup();
    var pointMarkersLayer = new L.LayerGroup();

    var selectedLayer = null;
    var selectedPolygon = null;
    var selectedCentroid = null;
    var selectedObjectJSON = null;

    /* Styles for parcel outlines */
    var defaultStyle = {
      'opacity': 1,
      'fillOpacity': 0,
      'weight': 3,
      'color': 'white',
      'dashArray': '5,5'
    };

    var selectedStyle = {
      'opacity': 1,
      'fillOpacity': 0.25,
      'weight': 3,
      'color': 'yellow',
      'fillColor': 'yellow',
      'dashArray': '1'

    };

    this.init = function() {
      console.log("Initialize map");
      map = new L.Map(mapContainerId, {minZoom:13, maxZoom:21});

      map.addLayer(parcelsLayerGroup);
      map.addLayer(doneMarkersLayer);

      var bing = new L.BingLayer(settings.bing_key, {maxZoom:21, type:"AerialWithLabels"});
      map.addLayer(bing);

      $.subscribe("successfulSubmit", getResponsesInMap);

      // Show which parcels have responses when the map is moved.
      map.on('moveend', function(e) {
        try {
          getResponsesInMap();
          renderParcelsInBounds();
        } catch(e){}
      });

      // Location handlers
      // Used for centering the map when we're using geolocation.
      map.on('locationfound', onLocationFound);
      map.on('locationerror', onLocationError);

      map.locate({setView: true, maxZoom: 19});

      // Mark a location on the map.
      // Primarily used with browser-based geolocation (aka "where am I?")
      function onLocationFound(e) {
        // Remove the old circle if we have one
        if (circle !== undefined) {
          map.removeLayer(circle);
        };

        // Add the accuracy circle to the map
        var radius = e.accuracy / 2;
        circle = new L.Circle(e.latlng, radius);
        map.addLayer(circle);

        getResponsesInMap();
        renderParcelsInBounds();
      }

      function onLocationError(e) {
        alert(e.message);
      }

      // Map tools ...............................................................

      // Handle searching for addresses
      $("#address-search-toggle").click(function(){
        $("#address-search").slideToggle();
        $("#address-search-prompt").slideToggle();
      });

      $("#address-submit").click(function(){
        goToAddress($("#address-input").val());
      });

      $("#geolocate").click(function(){
        map.locate({setView: true, maxZoom: 19});
      });

    }; // end init

    // Map information used by other parts of the app ..........................

    this.getSelectedCentroid = function() {
      return app.selectedObject.centroid;
    };

    // Return the bounds of the map as a string
    this.getMapBounds = function() {
      var bounds = "";
      bounds += map.getBounds().getNorthWest().toString();
      bounds += " " + map.getBounds().getSouthEast().toString();
      return bounds;
    };

    // Icons ...................................................................
    var CheckIcon = L.Icon.extend({
      options: {
        className: 'CheckIcon',
        iconUrl: 'img/icons/check-16.png',
        shadowUrl: 'img/icons/check-16.png',
        iconSize: new L.Point(16, 16),
        shadowSize: new L.Point(16, 16),
        iconAnchor: new L.Point(8, 8),
        popupAnchor: new L.Point(8, 8)
      }
    });

    // Move the map ............................................................
    // Attempt to center the map on an address using Google's geocoder.
    // This should probably live in APIs.
    var goToAddress = function(address) {
      api.codeAddress(address, function(latlng){
        if (circle !== undefined) {
          map.removeLayer(circle);
        }

        // Add the accuracy circle to the map
        var radius = 4;
        circle = new L.Circle(latlng, radius);
        map.addLayer(circle);
        map.setView(latlng, 19);

        // Scroll to the top so users can
        window.scrollTo(0,0);
        $("#address-search").slideToggle();
        $("#address-search-prompt").slideToggle();

      });
    };

    // Handle selecting objects ................................................

    // Render parcels that are currently visible in the map
    // Gets geodata from our api
    var renderParcelsInBounds = function() {
      console.log("Rendering parcels in bounds");

      // Don't add any parcels if the zoom is really far out.
      var zoom = map.getZoom();
      if(zoom < 17) {
        return;
      }

      // If we have too many objects, let's delete them
      // Keeps the app responsive
      console.log(numObjectsOnMap);
      if(numObjectsOnMap > 250) {
        parcelsLayerGroup.clearLayers();
        // TODO - does setting this to an empty object
        // result in good garbage collection? Or do we have references to
        // layers still floating around?
        parcelIdsOnTheMap = {};
        numObjectsOnMap = 0;
      }

      if(_.isEmpty(parcelIdsOnTheMap)) {
        $.mobile.showPageLoadingMsg();
      };

      // Get parcel data in the bounds
      api.getObjectsInBounds(map.getBounds(), function(results) {
        console.log("Received parcel data");

        $.each(results, function(key, elt) {

          // We don't want to re-draw parcels that are already on the map
          // So we keep a hash map with the layers so we can unrender them
          if (parcelIdsOnTheMap[elt.parcelId] === undefined){

            // Make sure the format fits Leaflet's geoJSON expectations
            elt.geometry = elt.polygon;
            elt.type = "Feature";

            // Create a new geojson layer and style it.
            var geojsonLayer = new L.GeoJSON();
            geojsonLayer.addData(elt);
            geojsonLayer.setStyle(defaultStyle);

            // Handle clicks on the layer
            geojsonLayer.on('click', function(e){

              // Deselect the previous layer, if any
              if (selectedLayer !== null) {
                selectedLayer.setStyle(defaultStyle);
              }

              // Keep track of the selected object centrally
              app.selectedObject.id = elt.parcelId;
              app.selectedObject.humanReadableName = elt['address'];
              app.selectedObject.centroid = elt['centroid'];
              app.selectedObject.geometry = elt.geometry;
              console.log(app.selectedObject);

              // Select the current layer
              selectedLayer = e.layer;
              selectedLayer.setStyle(selectedStyle);

              // Let other parts of the app know that we've selected something.
              $.publish("objectSelected");

            });

            // Add the layer to the layergroup and the hashmap
            parcelsLayerGroup.addLayer(geojsonLayer);
            parcelIdsOnTheMap[elt.parcelId] = geojsonLayer;
            numObjectsOnMap++;

          };
        }); // done getting parcels
        // Hide the spinner
        $.mobile.hidePageLoadingMsg();

      });
    };

    // Outline the given polygon
    // expects polygon to be {coordinates: [[x,y], [x,y], ...] }
    var highlightObject = function(selectedObjectJSON) {
      polygonJSON = selectedObjectJSON.polygon;

      // Remove existing highlighting
      if(selectedPolygon) {
        map.removeLayer(selectedPolygon);
      };

      // Add the new polygon
      var polypoints = new Array();
      for (var i = polygonJSON.coordinates[0].length - 1; i >= 0; i--){
        point = new L.LatLng(polygonJSON.coordinates[0][i][1], polygonJSON.coordinates[0][i][0]);
        polypoints.push(point);
      };
      options = {
        color: 'red',
        fillColor: 'transparent',
        fillOpacity: 0.5
      };
      selectedPolygon = new L.Polygon(polypoints, options);
      map.addLayer(selectedPolygon);
    };

    // Adds a checkbox marker to the given point
    var addDoneMarker = function(latlng, id) {
      // Only add markers if they aren't already on the map.
      if (markers[id] == undefined){
        var doneIcon = new CheckIcon();
        var doneMarker = new L.Marker(latlng, {icon: doneIcon});
        doneMarkersLayer.addLayer(doneMarker);
        markers[id] = doneMarker;
      };
    };

    // Get all the responses in a map
    var getResponsesInMap = function(){
      console.log("Getting responses in the map");

      // Don't add any markers if the zoom is really far out.
      var zoom = map.getZoom();
      if(zoom < 17) {
        return;
      }

      // Get the objects in the bounds
      // And add them to the map
      api.getResponsesInBounds(map.getBounds(), function(results) {
        console.log(results);
        $.each(results, function(key, elt) {
          var p = new L.LatLng(elt.geo_info.centroid[0], elt.geo_info.centroid[1]);
          var id = elt.parcel_id;
          addDoneMarker(p, id);
        });
      });

    };

    // Map init ================================================================
    this.init();
  };
});
<commit_msg>Decrease number of parcels on the map before reset<commit_after>/*jslint nomen: true */
/*globals define: true */

define(function (require) {
  'use strict';

  var $ = require('jquery');
  var _ = require('lib/underscore');
  var settings = require('settings');
  var api = require('api');
  var L = require('lib/leaflet');

  return function (app, mapContainerId) {

    var map, marker, circle;
    var markers = {};
    var numObjectsOnMap = 0;
    var parcelIdsOnTheMap = {};
    var parcelsLayerGroup = new L.LayerGroup();
    var doneMarkersLayer = new L.LayerGroup();
    var pointMarkersLayer = new L.LayerGroup();

    var selectedLayer = null;
    var selectedPolygon = null;
    var selectedCentroid = null;
    var selectedObjectJSON = null;

    /* Styles for parcel outlines */
    var defaultStyle = {
      'opacity': 1,
      'fillOpacity': 0,
      'weight': 3,
      'color': 'white',
      'dashArray': '5,5'
    };

    var selectedStyle = {
      'opacity': 1,
      'fillOpacity': 0.25,
      'weight': 3,
      'color': 'yellow',
      'fillColor': 'yellow',
      'dashArray': '1'

    };

    this.init = function() {
      console.log("Initialize map");
      map = new L.Map(mapContainerId, {minZoom:13, maxZoom:21});

      map.addLayer(parcelsLayerGroup);
      map.addLayer(doneMarkersLayer);

      var bing = new L.BingLayer(settings.bing_key, {maxZoom:21, type:"AerialWithLabels"});
      map.addLayer(bing);

      $.subscribe("successfulSubmit", getResponsesInMap);

      // Show which parcels have responses when the map is moved.
      map.on('moveend', function(e) {
        try {
          getResponsesInMap();
          renderParcelsInBounds();
        } catch(e){}
      });

      // Location handlers
      // Used for centering the map when we're using geolocation.
      map.on('locationfound', onLocationFound);
      map.on('locationerror', onLocationError);

      map.locate({setView: true, maxZoom: 19});

      // Mark a location on the map.
      // Primarily used with browser-based geolocation (aka "where am I?")
      function onLocationFound(e) {
        // Remove the old circle if we have one
        if (circle !== undefined) {
          map.removeLayer(circle);
        };

        // Add the accuracy circle to the map
        var radius = e.accuracy / 2;
        circle = new L.Circle(e.latlng, radius);
        map.addLayer(circle);

        getResponsesInMap();
        renderParcelsInBounds();
      }

      function onLocationError(e) {
        alert(e.message);
      }

      // Map tools ...............................................................

      // Handle searching for addresses
      $("#address-search-toggle").click(function(){
        $("#address-search").slideToggle();
        $("#address-search-prompt").slideToggle();
      });

      $("#address-submit").click(function(){
        goToAddress($("#address-input").val());
      });

      $("#geolocate").click(function(){
        map.locate({setView: true, maxZoom: 19});
      });

    }; // end init

    // Map information used by other parts of the app ..........................

    this.getSelectedCentroid = function() {
      return app.selectedObject.centroid;
    };

    // Return the bounds of the map as a string
    this.getMapBounds = function() {
      var bounds = "";
      bounds += map.getBounds().getNorthWest().toString();
      bounds += " " + map.getBounds().getSouthEast().toString();
      return bounds;
    };

    // Icons ...................................................................
    var CheckIcon = L.Icon.extend({
      options: {
        className: 'CheckIcon',
        iconUrl: 'img/icons/check-16.png',
        shadowUrl: 'img/icons/check-16.png',
        iconSize: new L.Point(16, 16),
        shadowSize: new L.Point(16, 16),
        iconAnchor: new L.Point(8, 8),
        popupAnchor: new L.Point(8, 8)
      }
    });

    // Move the map ............................................................
    // Attempt to center the map on an address using Google's geocoder.
    // This should probably live in APIs.
    var goToAddress = function(address) {
      api.codeAddress(address, function(latlng){
        if (circle !== undefined) {
          map.removeLayer(circle);
        }

        // Add the accuracy circle to the map
        var radius = 4;
        circle = new L.Circle(latlng, radius);
        map.addLayer(circle);
        map.setView(latlng, 19);

        // Scroll to the top so users can
        window.scrollTo(0,0);
        $("#address-search").slideToggle();
        $("#address-search-prompt").slideToggle();

      });
    };

    // Render parcels that are currently visible in the map
    // Gets geodata from our api
    var renderParcelsInBounds = function() {
      console.log("Rendering parcels in bounds");

      // Don't add any parcels if the zoom is really far out.
      var zoom = map.getZoom();
      if(zoom < 17) {
        return;
      }

      // If we have too many objects, let's delete them
      // This keep the app responsive
      console.log(numObjectsOnMap);
      if(numObjectsOnMap > 175) {
        parcelsLayerGroup.clearLayers();
        // TODO - does setting this to an empty object
        // result in good garbage collection? Or do we have references to
        // layers still floating around?
        parcelIdsOnTheMap = {};
        numObjectsOnMap = 0;
      }

      if(_.isEmpty(parcelIdsOnTheMap)) {
        $.mobile.showPageLoadingMsg();
      };

      // Get parcel data in the bounds
      api.getObjectsInBounds(map.getBounds(), function(results) {
        console.log("Received parcel data");

        $.each(results, function(key, elt) {

          // We don't want to re-draw parcels that are already on the map
          // So we keep a hash map with the layers so we can unrender them
          if (parcelIdsOnTheMap[elt.parcelId] === undefined){

            // Make sure the format fits Leaflet's geoJSON expectations
            elt.geometry = elt.polygon;
            elt.type = "Feature";

            // Create a new geojson layer and style it.
            var geojsonLayer = new L.GeoJSON();
            geojsonLayer.addData(elt);
            geojsonLayer.setStyle(defaultStyle);

            // Handle clicks on the layer
            geojsonLayer.on('click', function(e){

              // Deselect the previous layer, if any
              if (selectedLayer !== null) {
                selectedLayer.setStyle(defaultStyle);
              }

              // Keep track of the selected object centrally
              app.selectedObject.id = elt.parcelId;
              app.selectedObject.humanReadableName = elt['address'];
              app.selectedObject.centroid = elt['centroid'];
              app.selectedObject.geometry = elt.geometry;
              console.log(app.selectedObject);

              // Select the current layer
              selectedLayer = e.layer;
              selectedLayer.setStyle(selectedStyle);

              // Let other parts of the app know that we've selected something.
              $.publish("objectSelected");

            });

            // Add the layer to the layergroup and the hashmap
            parcelsLayerGroup.addLayer(geojsonLayer);
            parcelIdsOnTheMap[elt.parcelId] = geojsonLayer;
            numObjectsOnMap++;

          };
        }); // done getting parcels
        // Hide the spinner
        $.mobile.hidePageLoadingMsg();

      });
    };

    // Outline the given polygon
    // expects polygon to be {coordinates: [[x,y], [x,y], ...] }
    var highlightObject = function(selectedObjectJSON) {
      polygonJSON = selectedObjectJSON.polygon;

      // Remove existing highlighting
      if(selectedPolygon) {
        map.removeLayer(selectedPolygon);
      };

      // Add the new polygon
      var polypoints = new Array();
      for (var i = polygonJSON.coordinates[0].length - 1; i >= 0; i--){
        point = new L.LatLng(polygonJSON.coordinates[0][i][1], polygonJSON.coordinates[0][i][0]);
        polypoints.push(point);
      };
      options = {
        color: 'red',
        fillColor: 'transparent',
        fillOpacity: 0.5
      };
      selectedPolygon = new L.Polygon(polypoints, options);
      map.addLayer(selectedPolygon);
    };

    // Adds a checkbox marker to the given point
    var addDoneMarker = function(latlng, id) {
      // Only add markers if they aren't already on the map.
      if (markers[id] == undefined){
        var doneIcon = new CheckIcon();
        var doneMarker = new L.Marker(latlng, {icon: doneIcon});
        doneMarkersLayer.addLayer(doneMarker);
        markers[id] = doneMarker;
      };
    };

    // Get all the responses in a map
    var getResponsesInMap = function(){
      console.log("Getting responses in the map");

      // Don't add any markers if the zoom is really far out.
      var zoom = map.getZoom();
      if(zoom < 17) {
        return;
      }

      // Get the objects in the bounds
      // And add them to the map
      api.getResponsesInBounds(map.getBounds(), function(results) {
        console.log(results);
        $.each(results, function(key, elt) {
          var p = new L.LatLng(elt.geo_info.centroid[0], elt.geo_info.centroid[1]);
          var id = elt.parcel_id;
          addDoneMarker(p, id);
        });
      });

    };

    // Map init ================================================================
    this.init();
  };
});
<|endoftext|>


<commit_before>window.animatePaper = require("./export");
window.paper = require("paper");<commit_msg>remove export-browser<commit_after><|endoftext|>


<commit_before>if (!token) {
	alert('you need a token to run the sample!');
}

var scenario = 'eu';
var itineraryLanguage = 'EN';
var routingProfile = 'carfast';
var alternativeRoutes = 0;
var routingControl;

// initialize the map
var map = L.map('map', {
	fullscreenControl: true,
	fullscreenControlOptions: {
		fullscreenElement: document.getElementById('map-container').parentNode // needed for sidebar!
	},
	contextmenu: true,
	contextmenuWidth: 200,
	contextmenuItems: [{
		text: 'Add Waypoint At Start',
		callback: function (ev) {
			if (routingControl._plan._waypoints[0].latLng) {
				routingControl.spliceWaypoints(0, 0, ev.latlng);
			} else {
				routingControl.spliceWaypoints(0, 1, ev.latlng);
			}
		}
	}, {
		text: 'Add Waypoint At End',
		callback: function (ev) {
			if (routingControl._plan._waypoints[routingControl._plan._waypoints.length - 1].latLng) {
				routingControl.spliceWaypoints(routingControl._plan._waypoints.length, 0, ev.latlng);
			} else {
				routingControl.spliceWaypoints(routingControl._plan._waypoints.length - 1, 1, ev.latlng);
			}
		}
	}]
});

// get the start and end coordinates for a scenario
var getPlan = function () {
	if (scenario.indexOf('na') > -1) {
		return [
			L.latLng(40.71454, -74.00711),
			L.latLng(42.35867, -71.05672)
		];
	} else if (scenario.indexOf('au') > -1) {
		return [
			L.latLng(-33.86959, 151.20694),
			L.latLng(-35.3065, 149.12659)
		];
	} else {
		return [
			L.latLng(48.8588, 2.3469),
			L.latLng(52.3546, 4.9039)
		];
	}
};

// returns a layer group for xmap back- and foreground layers
function getXMapBaseLayers(style, token, labelPane) {
	var attribution = '© 2021 PTV AG, HERE';

	var background = L.tileLayer('https://xmap-eu-n-test.cloud.ptvgroup.com/WMS/GetTile/xmap-' + style + 'bg/{x}/{y}/{z}.png', {
		minZoom: 0,
		maxZoom: 19,
		opacity: 1.0,
		attribution: attribution,
		subdomains: '1234'
	});

	var foreground = L.nonTiledLayer.wms('https://xmap-eu-n-test.cloud.ptvgroup.com/WMS/WMS?xtok=' + token, {
		minZoom: 0,
		maxZoom: 19,
		opacity: 1.0,
		layers: 'xmap-' + style + 'fg',
		format: 'image/png',
		transparent: true,
		attribution: attribution,
		pane: 'labels'
	});

	return L.layerGroup([background, foreground]);
}

map.createPane('labels');
map.getPane('labels').style.zIndex = 500;
map.getPane('labels').style.pointerEvents = 'none';

var baseLayers = {
	'PTV classic': getXMapBaseLayers('ajax', token, map._panes.labelPane),
	'PTV gravelpit': getXMapBaseLayers('gravelpit-', token, map._panes.labelPane),
	'PTV silkysand': getXMapBaseLayers('silkysand-', token, map._panes.labelPane).addTo(map),
	'PTV sandbox': getXMapBaseLayers('sandbox-', token, map._panes.labelPane)
};

L.control.scale().addTo(map);
L.control.layers(baseLayers, [], {
	position: 'bottomleft'
}).addTo(map);

routingControl = L.Routing.control({
	plan: L.Routing.plan(getPlan(), {
		createMarker: function (i, wp) {
			return L.marker(wp.latLng, {
				draggable: true,
				icon: L.icon.glyph({
					glyph: String.fromCharCode(65 + i)
				})
			});
		},
		geocoder: L.Control.Geocoder.ptv({
			serviceUrl: 'https://xlocate-eu-n-test.cloud.ptvgroup.com/xlocate/rs/XLocate/',
			token: token
		}),
		reverseWaypoints: true
	}),
	lineOptions: {
		styles: [
			// Shadow
			{
				color: 'black',
				opacity: 0.8,
				weight: 11
			},
			// Outline
			{
				color: '#888',
				opacity: 0.8,
				weight: 8
			},
			// Center
			{
				color: '#aaa',
				opacity: 1,
				weight: 4
			}
		]
	},
	altLineOptions: {
		styles: [{
			color: 'grey',
			opacity: 0.8,
			weight: 11
		},
		{
			color: '#aaa',
			opacity: 0.8,
			weight: 8
		},
		{
			color: 'white',
			opacity: 1,
			weight: 4
		}
		],
	},
	showAlternatives: true,
	router: L.Routing.ptv({
		serviceUrl: 'https://xroute-eu-n-test.cloud.ptvgroup.com/xroute/rs/XRoute/',
		token: token,
		numberOfAlternatives: alternativeRoutes,
		beforeSend: function (request) {
			request.options.push({
				parameter: 'ROUTE_LANGUAGE',
				value: itineraryLanguage
			});

			request.callerContext.properties.push({
				key: 'Profile',
				value: routingProfile
			});

			return request;
		},
		routesCalculated: function (alts, r) {}
	}),
	routeWhileDragging: false,
	routeDragInterval: 500,
	collapsible: true
}).addTo(map);

routingControl.on('routingerror', function (e) {
	console.log(e.message);
});

L.Routing.errorControl(routingControl).addTo(map);

// update ui
$('#clusterSelect').val(scenario);
$('#languageSelect').val(itineraryLanguage);
$('#routingProfile').val(routingProfile);
$('#alternativeRoutes').val(alternativeRoutes);

// add side bar
var sidebar = L.control.sidebar('sidebar').addTo(map);

// update the map scenario
var updateScenario = function () {
	scenario = $('#scenarioSelect option:selected').val();
	updateParams(true);
};

// update the routing params
var updateParams = function (updateWayPoints) {
	itineraryLanguage = $('#languageSelect option:selected').val();
	routingProfile = $('#routingProfile option:selected').val();
	alternativeRoutes = $('#alternativeRoutes option:selected').val();

	if (updateWayPoints)
	{routingControl.setWaypoints(getPlan());}
	routingControl._router.options.numberOfAlternatives = alternativeRoutes;
	routingControl.route();
};<commit_msg>update to world map<commit_after>if (!token) {
	alert('you need a token to run the sample!');
}

var scenario = 'eu';
var itineraryLanguage = 'EN';
var routingProfile = 'carfast';
var alternativeRoutes = 0;
var routingControl;

// initialize the map
var map = L.map('map', {
	fullscreenControl: true,
	fullscreenControlOptions: {
		fullscreenElement: document.getElementById('map-container').parentNode // needed for sidebar!
	},
	contextmenu: true,
	contextmenuWidth: 200,
	contextmenuItems: [{
		text: 'Add Waypoint At Start',
		callback: function (ev) {
			if (routingControl._plan._waypoints[0].latLng) {
				routingControl.spliceWaypoints(0, 0, ev.latlng);
			} else {
				routingControl.spliceWaypoints(0, 1, ev.latlng);
			}
		}
	}, {
		text: 'Add Waypoint At End',
		callback: function (ev) {
			if (routingControl._plan._waypoints[routingControl._plan._waypoints.length - 1].latLng) {
				routingControl.spliceWaypoints(routingControl._plan._waypoints.length, 0, ev.latlng);
			} else {
				routingControl.spliceWaypoints(routingControl._plan._waypoints.length - 1, 1, ev.latlng);
			}
		}
	}]
});

// get the start and end coordinates for a scenario
var getPlan = function () {
	if (scenario.indexOf('na') > -1) {
		return [
			L.latLng(40.71454, -74.00711),
			L.latLng(42.35867, -71.05672)
		];
	} else if (scenario.indexOf('au') > -1) {
		return [
			L.latLng(-33.86959, 151.20694),
			L.latLng(-35.3065, 149.12659)
		];
	} else {
		return [
			L.latLng(48.8588, 2.3469),
			L.latLng(52.3546, 4.9039)
		];
	}
};

// returns a layer group for xmap back- and foreground layers
function getXMapBaseLayers(style, token, labelPane) {
	var attribution = '© 2021 PTV AG, HERE';

	var background = L.tileLayer('https://api-test.cloud.ptvgroup.com/WMS/GetTile/xmap-' + style + 'bg/{x}/{y}/{z}.png', {
		minZoom: 0,
		maxZoom: 19,
		opacity: 1.0,
		attribution: attribution,
		subdomains: '1234'
	});

	var foreground = L.nonTiledLayer.wms('https://api-test.cloud.ptvgroup.com/WMS/WMS?xtok=' + token, {
		minZoom: 0,
		maxZoom: 19,
		opacity: 1.0,
		layers: 'xmap-' + style + 'fg',
		format: 'image/png',
		transparent: true,
		attribution: attribution,
		pane: 'labels'
	});

	return L.layerGroup([background, foreground]);
}

map.createPane('labels');
map.getPane('labels').style.zIndex = 500;
map.getPane('labels').style.pointerEvents = 'none';

var baseLayers = {
	'PTV classic': getXMapBaseLayers('ajax', token, map._panes.labelPane),
	'PTV gravelpit': getXMapBaseLayers('gravelpit-', token, map._panes.labelPane),
	'PTV silkysand': getXMapBaseLayers('silkysand-', token, map._panes.labelPane).addTo(map),
	'PTV sandbox': getXMapBaseLayers('sandbox-', token, map._panes.labelPane)
};

L.control.scale().addTo(map);
L.control.layers(baseLayers, [], {
	position: 'bottomleft'
}).addTo(map);

routingControl = L.Routing.control({
	plan: L.Routing.plan(getPlan(), {
		createMarker: function (i, wp) {
			return L.marker(wp.latLng, {
				draggable: true,
				icon: L.icon.glyph({
					glyph: String.fromCharCode(65 + i)
				})
			});
		},
		geocoder: L.Control.Geocoder.ptv({
			serviceUrl: 'https://api-test.cloud.ptvgroup.com/xlocate/rs/XLocate/',
			token: token
		}),
		reverseWaypoints: true
	}),
	lineOptions: {
		styles: [
			// Shadow
			{
				color: 'black',
				opacity: 0.8,
				weight: 11
			},
			// Outline
			{
				color: '#888',
				opacity: 0.8,
				weight: 8
			},
			// Center
			{
				color: '#aaa',
				opacity: 1,
				weight: 4
			}
		]
	},
	altLineOptions: {
		styles: [{
			color: 'grey',
			opacity: 0.8,
			weight: 11
		},
		{
			color: '#aaa',
			opacity: 0.8,
			weight: 8
		},
		{
			color: 'white',
			opacity: 1,
			weight: 4
		}
		],
	},
	showAlternatives: true,
	router: L.Routing.ptv({
		serviceUrl: 'https://api-test.cloud.ptvgroup.com/xroute/rs/XRoute/',
		token: token,
		numberOfAlternatives: alternativeRoutes,
		beforeSend: function (request) {
			request.options.push({
				parameter: 'ROUTE_LANGUAGE',
				value: itineraryLanguage
			});

			request.callerContext.properties.push({
				key: 'Profile',
				value: routingProfile
			});

			return request;
		},
		routesCalculated: function (alts, r) {}
	}),
	routeWhileDragging: false,
	routeDragInterval: 500,
	collapsible: true
}).addTo(map);

routingControl.on('routingerror', function (e) {
	console.log(e.message);
});

L.Routing.errorControl(routingControl).addTo(map);

// update ui
$('#clusterSelect').val(scenario);
$('#languageSelect').val(itineraryLanguage);
$('#routingProfile').val(routingProfile);
$('#alternativeRoutes').val(alternativeRoutes);

// add side bar
var sidebar = L.control.sidebar('sidebar').addTo(map);

// update the map scenario
var updateScenario = function () {
	scenario = $('#scenarioSelect option:selected').val();
	updateParams(true);
};

// update the routing params
var updateParams = function (updateWayPoints) {
	itineraryLanguage = $('#languageSelect option:selected').val();
	routingProfile = $('#routingProfile option:selected').val();
	alternativeRoutes = $('#alternativeRoutes option:selected').val();

	if (updateWayPoints)
	{routingControl.setWaypoints(getPlan());}
	routingControl._router.options.numberOfAlternatives = alternativeRoutes;
	routingControl.route();
};<|endoftext|>


<commit_before>'use strict';

ngDefine('cockpit.directives', [
    'angular',
    'jquery',
    'bpmn/Bpmn',
    'jquery-overscroll',
    'jquery-mousewheel'
  ], function(module, angular, $, Bpmn) {

  function DirectiveController($scope, $element, $attrs, $filter, $q, $window) {

    var w = angular.element($window);

    var bpmnElements;

    var activityHighligtClass = 'activity-highlight';
    var bpmnRenderer = null;
    var zoomLevel = 1;

    $scope.$on('$destroy', function() {
      bpmnRenderer = null;
      $scope.processDiagram = null;
      $scope.processDiagramOverlay = null;
    });

    /*------------------- Rendering of process diagram ---------------------*/

    /**
     * If the process diagram changes, then the diagram will be rendered.
     */
    $scope.$watch('processDiagram', function(newValue, oldValue) {
      if (newValue && newValue.$loaded !== false) {
        bpmnElements = newValue.bpmnElements;
        bpmnRenderer = new Bpmn();
        renderDiagram();
        initializeScrollAndZoomFunctions();
      }
    });

    $scope.$watch('processDiagramOverlay', function(newValue, oldValue) {
      if (newValue) {
        if (newValue.annotations) {
          annotations();
        }

        if (newValue.incidents) {
          incidents();
        }

        if (newValue.clickableElements) {
          registerEventHandlersOnProcessDiagram();
          registerEventHandlersOnBaseElements();
        }
      }
    });

    function renderDiagram() {

      // set the element id to processDiagram_*
      var elementId = 'processDiagram_' + $scope.processDiagram.processDefinition.id.replace(/:/g, '_');
      $element.attr('id', elementId);

      // clear innerHTML of element in case that the process diagram has changed
      // and the old one has been rendered.
      $element.empty();

      // set the render options
      $element.addClass('process-diagram');
      var options = {
        diagramElement : $element.attr('id')
      };

      // do the rendering
      bpmnRenderer.renderDiagram($scope.processDiagram.semantic, options);
    }

    /*------------------- Handle scroll and zoom ---------------------*/

    $scope.$watch(function() { return zoomLevel; }, function(newZoomLevel) {
      if (!!newZoomLevel && !!bpmnRenderer) {
        zoom(newZoomLevel);
      }
    });

    function initializeScrollAndZoomFunctions() {
      zoom(zoomLevel);

      $element.mousewheel(function($event, delta) {
        $event.preventDefault();
        $scope.$apply(function() {
          zoomLevel = calculateZoomLevel(delta);
        });
      });
    }

    function overscroll() {
      $element.overscroll({captureWheel:false});
    }

    function removeOverscroll() {
      $element.removeOverscroll();
    }

    function zoom(zoomFactor) {
      removeOverscroll();
      bpmnRenderer.zoom(zoomFactor);
      overscroll();
    }

    function calculateZoomLevel (delta) {
      var minZoomLevelMin = 0.1;
      var maxZoomLevelMax = 5;
      var zoomSteps = 10;

      var newZoomLevel = zoomLevel + Math.round((delta * 100)/ zoomSteps) / 100;

      if (newZoomLevel > maxZoomLevelMax) {
        newZoomLevel = maxZoomLevelMax;
      } else if (newZoomLevel < minZoomLevelMin) {
        newZoomLevel = minZoomLevelMin;
      }

      return newZoomLevel;
    };

    /*------------------- Handle window resize ---------------------*/

    w.bind('resize', function () {
      $scope.$apply();
    });

    $scope.$watch(function () {
      return $element.width();
    }, function(newValue, oldValue) {
      if (bpmnRenderer) {
        zoom(zoomLevel);
      }
    });

    $scope.$watch(function () {
      return $element.height();
    }, function(newValue, oldValue) {
      if (bpmnRenderer) {
        zoom(zoomLevel);
      }
    });

    $scope.$on('resize', function () {
      $scope.$apply();
    });

    /*------------------- Handle annotations/incidents ---------------------*/

    function annotations() {
      for (var i = 0, annotation; !!(annotation = $scope.processDiagramOverlay.annotations[i]); i++) {
        doAnnotate(annotation.id, annotation.count);
      }
    }

    function incidents() {
      for (var i = 0, activity; !!(activity = $scope.processDiagramOverlay.incidents[i]); i++) {
        if (activity.incidents && activity.incidents.length > 0) {
          executeAnnotation(activity.id, '
!
');
        }
      }
    }

    function doAnnotate(activityId, count) {
      var shortenNumberFilter = $filter('shortenNumber');
      executeAnnotation(activityId, '
' + shortenNumberFilter(count) + '
');
    }

    function executeAnnotation(activityId, innerHtml) {
      // get the div element containing the badges (i.e. annotations/incidents).
      var badge = $('#' + $element.attr('id') + ' > #' + activityId + ' > .badge-position');
      if (badge.length > 0) {
        // get the incident badge
        var importantBadge = $('#' + $element.attr('id') + ' > #' + activityId + ' > .badge-position > .badge-important');

        if (importantBadge.length > 0) {
          // if an element with class '.badge-important' (incident badge) already exists, then prepend the innerHtml
          badge.prepend(innerHtml);
        } else {
          // if an element with class '.badge-important' (incident badge) does not exist, then append the innerHtml
          badge.append(innerHtml);
        }
      } else {
        // in that case there no badges are existings, so the first one will initially added.
        try {
          bpmnRenderer.annotation(activityId).addDiv(innerHtml, ['badge-position']);
        } catch (error) {
          console.log('Could not annotate activity \'' + activityId + '\': ' + error.message);
        }
      }
    }

    /*------------------- Register click events ---------------------*/

    function registerEventHandlersOnProcessDiagram() {

      var moved = false;
      var mousedown = false;
      // register event handler on $element: mousedown, mousemove, mouseup
      $element
        // register mousedown event
        .mousedown(function($event) {
          mousedown = true;
        })
        // register mousemove event
        .mousemove(function($event) {
          if (mousedown) {
            // set 'moved' true, when there was
            // a mousedown event at first.
            moved = true;
          }
        })
        // register mouseup event
        .mouseup(function($event) {
          var targetId = $($event.target).attr('id'),
              idx = $scope.processDiagramOverlay.clickableElements.indexOf(targetId),
              ctrlKey = $event.ctrlKey;

          if (!ctrlKey) {

            if (!moved && mousedown) {
              // if the mouse have not moved and a mousedown happend,
              // then you have to deselect the current selection.
              if ($scope.onElementClick && idx === -1) {
                $scope.onElementClick({id: null, $event: $event});
                $scope.$apply();
              }
            }
          }
          // always reset the values
          moved = false;
          mousedown = false;
        });
    }

    function registerEventHandlersOnBaseElements() {
      function waitForBpmnElements () {
        var deferred = $q.defer();
        $scope.$watch(function () { return bpmnElements; }, function (newValue) {
          if (newValue) {
            deferred.resolve(newValue);
          }
        });
        return deferred.promise;
      }
      if ($scope.onElementClick) {
        if (bpmnElements) {
          for (var key in bpmnElements) {
            registerEventHandlersOnBaseElement(bpmnElements[key]);
          }
        } else {
          waitForBpmnElements().then(function(bpmnElements) {
            for (var key in bpmnElements) {
              registerEventHandlersOnBaseElement(bpmnElements[key]);
            }
          });
        }
      }
    }

    function registerEventHandlersOnBaseElement(element) {
      var elementId = element.id;
      if ($scope.processDiagramOverlay.clickableElements.indexOf(elementId) != -1) {
        $('#' + elementId)

          // register click
          .click(elementId, function ($event) {
            $scope.onElementClick({id: $event.data, $event: $event});
            $scope.$apply();
          })

          // mouseover
          .mouseover(elementId, function($event) {
            if (!element.isSelected && $scope.processDiagramOverlay.clickableElements.indexOf($event.data) !== -1) {
              // add css class to highlight activity
              bpmnRenderer.annotation($event.data).addClasses([ activityHighligtClass ]);
              // add pointer ass cursor
              $('#' + element.id).css('cursor', 'pointer');
            }
          })

          // mouseout
          .mouseout(elementId, function($event){
            if (!element.isSelected && $scope.processDiagramOverlay.clickableElements.indexOf($event.data) !== -1) {
              // remove css class to highlight activity
              bpmnRenderer.annotation($event.data).removeClasses([ activityHighligtClass ]);
            }
          });
      }
    }

    /*------------------- Handle selected activity id---------------------*/

    $scope.$watch('selection.activityIds', function(newValue, oldValue) {
      if (oldValue) {
        angular.forEach(oldValue, function(elementId) {
          var bpmnElement = bpmnElements[elementId];
          deselectActivity(bpmnElement);
        });
      }
      if (newValue) {
        angular.forEach(newValue, function(elementId) {
          var bpmnElement = bpmnElements[elementId];
          selectActivity(bpmnElement);
        });
      }
    });

    function selectActivity(bpmnElement) {
      if (bpmnElement) {
        bpmnElement.isSelected = true;
        try {
          bpmnRenderer.annotation(bpmnElement.id).addClasses([ activityHighligtClass ]);
        } catch (error) {
          console.log('Could not add css class ' + activityHighligtClass + ' on element ' + bpmnElement.id + ': ' + error.message);
        }
      }
    }

    function deselectActivity(bpmnElement) {
      if (bpmnElement) {
        bpmnElement.isSelected = false;
        try {
          bpmnRenderer.annotation(bpmnElement.id).removeClasses([ activityHighligtClass ]);
        } catch (error) {
          console.log('Could not remove css class ' + activityHighligtClass + ' on element ' + bpmnElement.id + ': ' + error.message);
        }
      }
    }

    /*------------------- Handle scroll to bpmn element ---------------------*/

    $scope.$watch('selection.scrollToBpmnElement', function(newValue) {
      if (newValue) {
        var bpmnElement = bpmnElements[newValue];
        scrollTo(bpmnElement)
      }
    });

    function scrollTo(element) {
      // parent size
      var parentElementHeight = $element.height();
      var parentElementWidth = $element.width();

      // get the bpmn element to scroll to
      var bpmnElement = $('#' + $element.attr('id') + '> #' + element.id);

      // get the height and width of the bpmn element
      var bpmnElementHeight = bpmnElement.height();
      var bpmnElementWidth = bpmnElement.width();

      // get the top and left position of the bpmn element
      var bpmnElementTop = parseInt(bpmnElement.css('top'));
      var bpmnElementLeft = parseInt(bpmnElement.css('left'));

      var scrollTop = (bpmnElementTop +  (bpmnElementHeight/2)) - parentElementHeight/2;
      var scrollLeft = (bpmnElementLeft +  (bpmnElementWidth/2)) - parentElementWidth/2;

      $element.animate({
        scrollTop: scrollTop,
        scrollLeft: scrollLeft
      });
    }

    this.getRenderer = function () {
      return bpmnRenderer;
    };

  }

  var Directive = function ($window) {
    return {
      restrict: 'EAC',
      scope: {
        processDiagram: '=',
        processDiagramOverlay: '=',
        onElementClick: '&',
        selection: '='
      },
      controller: DirectiveController
    };
  };

  Directive.$inject = [ '$window' ];

  module
    .directive('processDiagram', Directive);

});
<commit_msg>fix(cockpit.processDiagram): delay selection if data not ready<commit_after>'use strict';

ngDefine('cockpit.directives', [
    'angular',
    'jquery',
    'bpmn/Bpmn',
    'jquery-overscroll',
    'jquery-mousewheel'
  ], function(module, angular, $, Bpmn) {

  function DirectiveController($scope, $element, $attrs, $filter, $q, $window) {

    var w = angular.element($window);

    var bpmnElements,
        selection;

    var activityHighligtClass = 'activity-highlight';
    var bpmnRenderer = null;
    var zoomLevel = 1;

    $scope.$on('$destroy', function() {
      bpmnRenderer = null;
      $scope.processDiagram = null;
      $scope.processDiagramOverlay = null;
    });

    /*------------------- Rendering of process diagram ---------------------*/

    /**
     * If the process diagram changes, then the diagram will be rendered.
     */
    $scope.$watch('processDiagram', function(newValue, oldValue) {
      if (newValue && newValue.$loaded !== false) {
        bpmnElements = newValue.bpmnElements;
        bpmnRenderer = new Bpmn();
        renderDiagram();
        initializeScrollAndZoomFunctions();

        // update selection in case it has been provided earlier
        updateSelection(selection);
      }
    });

    $scope.$watch('processDiagramOverlay', function(newValue, oldValue) {
      if (newValue) {
        if (newValue.annotations) {
          annotations();
        }

        if (newValue.incidents) {
          incidents();
        }

        if (newValue.clickableElements) {
          registerEventHandlersOnProcessDiagram();
          registerEventHandlersOnBaseElements();
        }
      }
    });

    function renderDiagram() {

      // set the element id to processDiagram_*
      var elementId = 'processDiagram_' + $scope.processDiagram.processDefinition.id.replace(/:/g, '_');
      $element.attr('id', elementId);

      // clear innerHTML of element in case that the process diagram has changed
      // and the old one has been rendered.
      $element.empty();

      // set the render options
      $element.addClass('process-diagram');
      var options = {
        diagramElement : $element.attr('id')
      };

      // do the rendering
      bpmnRenderer.renderDiagram($scope.processDiagram.semantic, options);
    }

    /*------------------- Handle scroll and zoom ---------------------*/

    $scope.$watch(function() { return zoomLevel; }, function(newZoomLevel) {
      if (!!newZoomLevel && !!bpmnRenderer) {
        zoom(newZoomLevel);
      }
    });

    function initializeScrollAndZoomFunctions() {
      zoom(zoomLevel);

      $element.mousewheel(function($event, delta) {
        $event.preventDefault();
        $scope.$apply(function() {
          zoomLevel = calculateZoomLevel(delta);
        });
      });
    }

    function overscroll() {
      $element.overscroll({captureWheel:false});
    }

    function removeOverscroll() {
      $element.removeOverscroll();
    }

    function zoom(zoomFactor) {
      removeOverscroll();
      bpmnRenderer.zoom(zoomFactor);
      overscroll();
    }

    function calculateZoomLevel (delta) {
      var minZoomLevelMin = 0.1;
      var maxZoomLevelMax = 5;
      var zoomSteps = 10;

      var newZoomLevel = zoomLevel + Math.round((delta * 100)/ zoomSteps) / 100;

      if (newZoomLevel > maxZoomLevelMax) {
        newZoomLevel = maxZoomLevelMax;
      } else if (newZoomLevel < minZoomLevelMin) {
        newZoomLevel = minZoomLevelMin;
      }

      return newZoomLevel;
    };

    /*------------------- Handle window resize ---------------------*/

    w.bind('resize', function () {
      $scope.$apply();
    });

    $scope.$watch(function () {
      return $element.width();
    }, function(newValue, oldValue) {
      if (bpmnRenderer) {
        zoom(zoomLevel);
      }
    });

    $scope.$watch(function () {
      return $element.height();
    }, function(newValue, oldValue) {
      if (bpmnRenderer) {
        zoom(zoomLevel);
      }
    });

    $scope.$on('resize', function () {
      $scope.$apply();
    });

    /*------------------- Handle annotations/incidents ---------------------*/

    function annotations() {
      for (var i = 0, annotation; !!(annotation = $scope.processDiagramOverlay.annotations[i]); i++) {
        doAnnotate(annotation.id, annotation.count);
      }
    }

    function incidents() {
      for (var i = 0, activity; !!(activity = $scope.processDiagramOverlay.incidents[i]); i++) {
        if (activity.incidents && activity.incidents.length > 0) {
          executeAnnotation(activity.id, '
!
');
        }
      }
    }

    function doAnnotate(activityId, count) {
      var shortenNumberFilter = $filter('shortenNumber');
      executeAnnotation(activityId, '
' + shortenNumberFilter(count) + '
');
    }

    function executeAnnotation(activityId, innerHtml) {
      // get the div element containing the badges (i.e. annotations/incidents).
      var badge = $('#' + $element.attr('id') + ' > #' + activityId + ' > .badge-position');
      if (badge.length > 0) {
        // get the incident badge
        var importantBadge = $('#' + $element.attr('id') + ' > #' + activityId + ' > .badge-position > .badge-important');

        if (importantBadge.length > 0) {
          // if an element with class '.badge-important' (incident badge) already exists, then prepend the innerHtml
          badge.prepend(innerHtml);
        } else {
          // if an element with class '.badge-important' (incident badge) does not exist, then append the innerHtml
          badge.append(innerHtml);
        }
      } else {
        // in that case there no badges are existings, so the first one will initially added.
        try {
          bpmnRenderer.annotation(activityId).addDiv(innerHtml, ['badge-position']);
        } catch (error) {
          console.log('Could not annotate activity \'' + activityId + '\': ' + error.message);
        }
      }
    }

    /*------------------- Register click events ---------------------*/

    function registerEventHandlersOnProcessDiagram() {

      var moved = false;
      var mousedown = false;
      // register event handler on $element: mousedown, mousemove, mouseup
      $element
        // register mousedown event
        .mousedown(function($event) {
          mousedown = true;
        })
        // register mousemove event
        .mousemove(function($event) {
          if (mousedown) {
            // set 'moved' true, when there was
            // a mousedown event at first.
            moved = true;
          }
        })
        // register mouseup event
        .mouseup(function($event) {
          var targetId = $($event.target).attr('id'),
              idx = $scope.processDiagramOverlay.clickableElements.indexOf(targetId),
              ctrlKey = $event.ctrlKey;

          if (!ctrlKey) {

            if (!moved && mousedown) {
              // if the mouse have not moved and a mousedown happend,
              // then you have to deselect the current selection.
              if ($scope.onElementClick && idx === -1) {
                $scope.onElementClick({id: null, $event: $event});
                $scope.$apply();
              }
            }
          }
          // always reset the values
          moved = false;
          mousedown = false;
        });
    }

    function registerEventHandlersOnBaseElements() {
      function waitForBpmnElements () {
        var deferred = $q.defer();
        $scope.$watch(function () { return bpmnElements; }, function (newValue) {
          if (newValue) {
            deferred.resolve(newValue);
          }
        });
        return deferred.promise;
      }
      if ($scope.onElementClick) {
        if (bpmnElements) {
          for (var key in bpmnElements) {
            registerEventHandlersOnBaseElement(bpmnElements[key]);
          }
        } else {
          waitForBpmnElements().then(function(bpmnElements) {
            for (var key in bpmnElements) {
              registerEventHandlersOnBaseElement(bpmnElements[key]);
            }
          });
        }
      }
    }

    function registerEventHandlersOnBaseElement(element) {
      var elementId = element.id;
      if ($scope.processDiagramOverlay.clickableElements.indexOf(elementId) != -1) {
        $('#' + elementId)

          // register click
          .click(elementId, function ($event) {
            $scope.onElementClick({id: $event.data, $event: $event});
            $scope.$apply();
          })

          // mouseover
          .mouseover(elementId, function($event) {
            if (!element.isSelected && $scope.processDiagramOverlay.clickableElements.indexOf($event.data) !== -1) {
              // add css class to highlight activity
              bpmnRenderer.annotation($event.data).addClasses([ activityHighligtClass ]);
              // add pointer ass cursor
              $('#' + element.id).css('cursor', 'pointer');
            }
          })

          // mouseout
          .mouseout(elementId, function($event){
            if (!element.isSelected && $scope.processDiagramOverlay.clickableElements.indexOf($event.data) !== -1) {
              // remove css class to highlight activity
              bpmnRenderer.annotation($event.data).removeClasses([ activityHighligtClass ]);
            }
          });
      }
    }

    /*------------------- Handle selected activity id---------------------*/

    $scope.$watch('selection.activityIds', function(newValue, oldValue) {
      updateSelection(newValue);
    });

    function updateSelection(newSelection) {
      if (bpmnElements) {
        if (selection) {
          angular.forEach(selection, function(elementId) {
            var bpmnElement = bpmnElements[elementId];
            deselectActivity(bpmnElement);
          });
        }

        if (newSelection) {
          angular.forEach(newSelection, function(elementId) {
            var bpmnElement = bpmnElements[elementId];
            selectActivity(bpmnElement);
          });
        }
      }

      selection = newSelection;
    }

    function selectActivity(bpmnElement) {
      if (bpmnElement) {
        bpmnElement.isSelected = true;
        try {
          bpmnRenderer.annotation(bpmnElement.id).addClasses([ activityHighligtClass ]);
        } catch (error) {
          console.log('Could not add css class ' + activityHighligtClass + ' on element ' + bpmnElement.id + ': ' + error.message);
        }
      }
    }

    function deselectActivity(bpmnElement) {
      if (bpmnElement) {
        bpmnElement.isSelected = false;
        try {
          bpmnRenderer.annotation(bpmnElement.id).removeClasses([ activityHighligtClass ]);
        } catch (error) {
          console.log('Could not remove css class ' + activityHighligtClass + ' on element ' + bpmnElement.id + ': ' + error.message);
        }
      }
    }

    /*------------------- Handle scroll to bpmn element ---------------------*/

    $scope.$watch('selection.scrollToBpmnElement', function(newValue) {
      if (newValue) {
        var bpmnElement = bpmnElements[newValue];
        scrollTo(bpmnElement)
      }
    });

    function scrollTo(element) {
      // parent size
      var parentElementHeight = $element.height();
      var parentElementWidth = $element.width();

      // get the bpmn element to scroll to
      var bpmnElement = $('#' + $element.attr('id') + '> #' + element.id);

      // get the height and width of the bpmn element
      var bpmnElementHeight = bpmnElement.height();
      var bpmnElementWidth = bpmnElement.width();

      // get the top and left position of the bpmn element
      var bpmnElementTop = parseInt(bpmnElement.css('top'));
      var bpmnElementLeft = parseInt(bpmnElement.css('left'));

      var scrollTop = (bpmnElementTop +  (bpmnElementHeight/2)) - parentElementHeight/2;
      var scrollLeft = (bpmnElementLeft +  (bpmnElementWidth/2)) - parentElementWidth/2;

      $element.animate({
        scrollTop: scrollTop,
        scrollLeft: scrollLeft
      });
    }

    this.getRenderer = function () {
      return bpmnRenderer;
    };

  }

  var Directive = function ($window) {
    return {
      restrict: 'EAC',
      scope: {
        processDiagram: '=',
        processDiagramOverlay: '=',
        onElementClick: '&',
        selection: '='
      },
      controller: DirectiveController
    };
  };

  Directive.$inject = [ '$window' ];

  module
    .directive('processDiagram', Directive);

});
<|endoftext|>


<commit_before>#!/usr/local/bin/node

var r    = require("../node_modules/respec/tools/r")
,   fs   = require("fs")
,   pth  = require("path")
,   async = require("async")
,   less = require("less")
,   wrench = require("wrench")
,   outPath = pth.join(__dirname, "..")
,   srcPath = pth.join(__dirname, "../src")
;

function buildBeryl (cb) {
    var config = {
        baseUrl:    pth.join(__dirname, "../beryl")
    // ,   optimize:   "none"
    ,   paths:  {
            requireLib: "../node_modules/respec/js/require"
        ,   simpleNode: "../node_modules/respec/js/simple-node"
        ,   shortcut:   "../node_modules/respec/js/shortcut"
        ,   domReady:   "../node_modules/respec/js/domReady"
        ,   core:       "../node_modules/respec/js/core/"
        ,   text:       "../node_modules/respec/js/text"
        ,   tmpl:       "../node_modules/respec/js/tmpl"
        ,   handlebars: "../node_modules/respec/js/handlebars"
        }
    ,   name:       "beryl"
    ,   include:    "requireLib simpleNode shortcut".split(" ")
    ,   out:        pth.join(outPath, "js/beryl.min.js")
    ,   inlineText: true
    ,   preserveLicenseComments:    false
    };
    r.optimize(config, function () {
        fs.writeFileSync(config.out,
                        "/* Beryl - Robin Berjon, http://berjon.com/ (@robinberjon) */\n/* See original source for licenses: https://github.com/darobin/respec-docs. */\n" +
                        fs.readFileSync(config.out, "utf8"), "utf8");
        console.log("[OK] Beryl built");
        cb();
    });
}

function buildBootstrap (cb) {
    var bsPath = pth.join(__dirname, "../node_modules/bootstrap/less/")
    ,   input = pth.join(__dirname, "../beryl/beryl.less")
    ,   parser = new less.Parser({
            paths:      [bsPath]
        ,   filename:   input
        })
    ;
    parser.parse(fs.readFileSync(input, "utf8"), function (err, tree) {
        fs.writeFileSync(pth.join(outPath, "css/beryl.css"), tree.toCSS({ compress: true }), "utf8");
        wrench.copyDirSyncRecursive(pth.join(__dirname, "../beryl/fonts"), pth.join(outPath, "css/fonts"), { forceDelete: true });
        wrench.copyDirSyncRecursive(pth.join(__dirname, "../beryl/img"), pth.join(outPath, "css/img"), { forceDelete: true });
        console.log("[OK] Bootstrap for Beryl built");
        cb();
    });
}

function mungeHeaders (content) {
    var inject =    "\n    <script src='js/beryl.min.js' async class='remove'></script>\n" +
                    // "\n    <script src='node_modules/respec/js/require.js' data-main='beryl/beryl' async class='remove'></script>\n" +
                    "\n    <link rel='stylesheet' href='css/beryl.css'>\n" +
                    "  </head>";
    return content.replace(/\n {2}<\/head>/g, inject);
}

function buildDocs (cb) {
    var sources = "index guide dev ref".split(" ");
    for (var i = 0, n = sources.length; i < n; i++) {
        var src = sources[i]
        ,   fileName = src + ".html"
        ,   content = fs.readFileSync(pth.join(srcPath, fileName), "utf8")
        ,   out = pth.join(outPath, fileName)
        ;
        content = mungeHeaders(content);
        if (src === "ref") {
            var incs = "conf els attrs classes events".split(" ")
            ,   refs = {}
            ;
            for (var j = 0, m = incs.length; j < m; j++) {
                var incDir = incs[j]
                ,   files = fs.readdirSync(pth.join(srcPath, incDir))
                ,   insert = ""
                ;
                for (var k = 0, o = files.length; k < o; k++) {
                    refs[files[k].replace(".html", "")] = true;
                    insert += fs.readFileSync(pth.join(srcPath, incDir, files[k]), "utf8") + "\n";
                }
                content = content.replace("<!-- " + incDir.toUpperCase() + " -->", insert);
            }
            fs.writeFileSync(pth.join(outPath, "js/refs.json"), JSON.stringify(refs), "utf8");
        }
        fs.writeFileSync(out, content, "utf8");
    }
    // copy the JS
    fs.writeFileSync(pth.join(outPath, "js/beryl-config.js")
                ,    fs.readFileSync(pth.join(srcPath, "js/beryl-config.js"), "utf8")
                ,    "utf8");
    console.log("[OK] Docs built");
    cb();
}

async.series([buildDocs, buildBeryl, buildBootstrap], function (err) {
    if (err) return console.log("ERROR:", err);
    console.log("OK!");
});
<commit_msg>Cleaned up tools/build.js a bit<commit_after>#!/usr/local/bin/node
"use strict";
const fs = require("fs");
const pth = require("path");
const async = require("async");
const less = require("less");
const wrench = require("wrench");
const outPath = pth.join(__dirname, "..");
const srcPath = pth.join(__dirname, "../src");

function buildBeryl(cb) {
  var config = {
    baseUrl: pth.join(__dirname, "../beryl"),
    paths: {
      requireLib: "../node_modules/respec/js/require",
      simpleNode: "../node_modules/respec/js/simple-node",
      shortcut: "../node_modules/respec/js/shortcut",
      domReady: "../node_modules/respec/js/domReady",
      core: "../node_modules/respec/js/core/",
      text: "../node_modules/respec/js/text",
      tmpl: "../node_modules/respec/js/tmpl",
      handlebars: "../node_modules/respec/js/handlebars"
    },
    name: "beryl",
    include: "requireLib simpleNode shortcut".split(" "),
    out: pth.join(outPath, "js/beryl.min.js"),
    inlineText: true,
    preserveLicenseComments: false
  };
  var data = fs.readFileSync(config.out, "utf8");
  fs.writeFileSync(config.out, data, "utf8");
  console.log("[OK] Beryl built");
  cb();
}

function buildBootstrap(cb) {
  var bsPath = pth.join(__dirname, "../node_modules/bootstrap/less/");
  var input = pth.join(__dirname, "../beryl/beryl.less");
  var parser = new less.Parser({
    paths: [bsPath],
    filename: input
  });
  var data = fs.readFileSync(input, "utf8");
  parser.parse(data, function (err, tree) {
    if(err){
      return console.log("Less Parser errors:", err)
    }
    fs.writeFileSync(pth.join(outPath, "css/beryl.css"), tree.toCSS({
      compress: true
    }), "utf8");

    wrench.copyDirSyncRecursive(pth.join(__dirname, "../beryl/fonts"), pth.join(outPath, "css/fonts"), {
      forceDelete: true
    });
    wrench.copyDirSyncRecursive(pth.join(__dirname, "../beryl/img"), pth.join(outPath, "css/img"), {
      forceDelete: true
    });
    console.log("[OK] Bootstrap for Beryl built");
    cb();
  });
}

function mungeHeaders(content) {
  var inject = `
    <script src='js/beryl.min.js' async class='remove'></script>

    <link rel='stylesheet' href='css/beryl.css'>
  </head>`;
  return content.replace(/\n {2}<\/head>/g, inject);
}

function buildDocs(cb) {

  var sources = "index guide dev ref".split(" ");
  for (var i = 0, n = sources.length; i < n; i++) {
    var src = sources[i],
      fileName = src + ".html",
      content = fs.readFileSync(pth.join(srcPath, fileName), "utf8"),
      out = pth.join(outPath, fileName);
    content = mungeHeaders(content);
    if (src === "ref") {
      var incs = "conf els attrs classes events".split(" "),
        refs = {};
      for (var j = 0, m = incs.length; j < m; j++) {
        var incDir = incs[j],
          files = fs.readdirSync(pth.join(srcPath, incDir)),
          insert = "";
        for (var k = 0, o = files.length; k < o; k++) {
          refs[files[k].replace(".html", "")] = true;
          insert += fs.readFileSync(pth.join(srcPath, incDir, files[k]), "utf8") + "\n";
        }
        content = content.replace("<!-- " + incDir.toUpperCase() + " -->", insert);
      }
      fs.writeFileSync(pth.join(outPath, "js/refs.json"), JSON.stringify(refs), "utf8");
    }
    fs.writeFileSync(out, content, "utf8");
  }
  // copy the JS
  fs.writeFileSync(pth.join(outPath, "js/beryl-config.js"), fs.readFileSync(pth.join(srcPath, "js/beryl-config.js"), "utf8"), "utf8");
  console.log("[OK] Docs built");
  cb();
}

async.series([buildDocs, buildBeryl, buildBootstrap], function (err) {
  if (err) {
    return console.log("ERROR:", err);
  }
  console.log("OK!");
});
<|endoftext|>


<commit_before>var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map-canvas'), {
    center: {lat:48.8471, lng:2.4382},
    zoom: 17
  });
  google.maps.event.addDomListener(window, "load", initialize);
}
<commit_msg>no listenner<commit_after>var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map-canvas'), {
    center: {lat:48.8471, lng:2.4382},
    zoom: 17
  });
}
<|endoftext|>


<commit_before>/*
 * grunt-tools-dev
 * https://github.com/yanwsh/grunt-tools-dev
 *
 * Copyright (c) 2016 Wensheng Yan
 * Licensed under the MIT license.
 */

'use strict';

var request   = require('request'),
    _         = require('underscore'),
    jsonfile  = require('jsonfile'),
    inquirer  = require('inquirer'),
    Promise   = require('promise'),
    path      = require("path"),
    crypto    = require('crypto'),
    tools_api = require('./tools_api.js'),
    fs = require('fs'),
    async     = require("async");

var DEFAULT_CONFIG_FILE = ".tools.json";

module.exports = function(grunt) {

  grunt.registerMultiTask('tools_dev', 'automation tools for tools.complex.com', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      configFile: DEFAULT_CONFIG_FILE,
      campaignFile: 'campaign.json'
    });

    var configFile = options.configFile;
    var campaignFile = options.campaignFile;
    var createCampaign = grunt.option('create-campaign');
    var done = this.async();

    //get files info according to the settings.
    var files = [];
    this.files.forEach(function(file) {
      var cwd = file.cwd || '';
      files = files.concat(file.src.map(function(src) {
        var s = path.join(cwd, src);
        var filepath = src.substr(0, src.lastIndexOf('/') + 1);
        var filename_w_ext = src.replace(filepath, "");
        var filename = filename_w_ext.substr(0, filename_w_ext.lastIndexOf('.'));

        return {'path' : filepath, 'src':s, 'filename': filename, 'filenameWithExt': filename_w_ext};
      }));
    });

    function needSetting(){
      return function (answers) {
        return answers['isSetting'];
      }
    }

    function isNormalInteger(str) {
      var n = ~~Number(str);
      return String(n) === str && n >= 0;
    }

    var settings = {};
    var campaign = {};
    var creative = {};

    function handle_error(err) {
      if(err){
	grunt.fail.warn("Error:" + err);
      }

      done();
      //get rid of other error message and prevent continue running.
      return Promise.reject(false);
    }

    new Promise(function (resolve, reject) {
      //get or set config file
      if(!grunt.file.exists(configFile)){
        grunt.log.errorlns("Missing tools dev config file.");

        inquirer.prompt([
          {
            type: "confirm",
            name: "isSetting",
            message: "Do you want to set it up right now?",
            default: true
          },
          {
            type: "input",
            name: "toolsURL",
            message: "Please input tools url link.",
            default: "https://tools.complex.com/",
            when: needSetting()
          },
          {
            type: "input",
            name: "token",
            message: function(answer){
              return "please input your token for " + answer["toolsURL"] + "."
            },
            when: needSetting(),
            validate: function (input) {
              var key = new Buffer(input, 'base64').toString('ascii');
              var error_message = "The token which you provide is not valid. Please try again.";

              var index = key.indexOf('.');
              if(index <= 0){
                return false;
              }
              var id = key.substring(0, index);
              var realkey = key.substring(index + 1);
              var result = (isNormalInteger(id) && realkey.length === 16)? true : error_message;
              return result;
            }
          }
        ], function(answer){
          if(!answer.isSetting){
            reject(false);
          }else{
            settings = {
              url: answer.toolsURL,
              token: answer.token
            };
            jsonfile.writeFileSync(configFile, settings);
            resolve(settings);
          }
        });
      }else{
        settings = jsonfile.readFileSync(configFile);
        resolve(settings);
      }
    }).then(function (settings) {
      if(createCampaign){
        //create a campaign
        grunt.verbose.writeln("creating campaign...");
        return new Promise(function (resolve, reject) {
          if(createCampaign === true){
            reject("You need to set a campaign name. Usuage --create-campaign=\"test-campaign\"");
          }
          tools_api.create_new_campaign(settings, createCampaign, function (error, result) {
             if(error){
               reject(error);
             }else{
               grunt.log.writeln("campaign name: " + createCampaign + " created on tools.");
               jsonfile.writeFileSync(campaignFile, result);
	           done();
             }
          });
        });
      }

      return settings;
    }, handle_error)
    .then(function (settings) {
      //get or set campaign file
      grunt.verbose.writeln("get or set campaign from file...");
      if(!grunt.file.exists(campaignFile)){
        return new Promise(function (resolve, reject) {
          inquirer.prompt([
            {
              type: "confirm",
              name: "isSetting",
              message: "You didn't bind any campaign. Do you want to bind a campaign?",
              default: true
            }
          ], function (answer) {
            if(!answer.isSetting){
              reject(false);
            }
            resolve(answer.isSetting);
          });
        }).then(function () {
          return new Promise(function (resolve, reject) {
            async.retry(3,
                function (callback, result) {
                  inquirer.prompt([
                    {
                      type: "input",
                      name: "campaignId",
                      message: "Please input campaign id: "
                    }
                  ], function (answer) {
                    var link = 'api/campaigns/' + answer.campaignId;
                    var options = {
                      method: 'GET',
                      url: link,
                      baseUrl: settings.url,
                      jar: true,
                      headers: {
                        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36',
                        'X-Requested-With': 'XMLHttpRequest',
                        'auth-token': settings.token
                      }
                    };
                    request(options, function (error, response, body) {
                      if(error){
                        callback(error, null);
                      }
                      try{
                        var obj = JSON.parse(body);
                        var error;
                        if(obj.errors){
                          error = obj.errors.message;
                          grunt.log.errorlns("Error:" + error);
                        }
                        callback(error, obj);
                      }
                      catch(e){
                        callback(error, null);
                      }
                    });
                  });
                },
                function (err, result) {
                  if(err) reject(err);
                  campaign = result;
                  jsonfile.writeFileSync(campaignFile, campaign);
                  resolve(campaign);
                }
            );
          });
        });
      }else{
        campaign = jsonfile.readFileSync(campaignFile);
        return campaign;
      }
    }, handle_error)
    .then(function (campaign) {
        //get creative list first
      grunt.verbose.writeln("getting creative list...");
      return new Promise(function (resolve, reject) {
        tools_api.get_creative_list(settings, campaign, function (error, result) {
          if(error){
            reject(error);
          }
          creative = result;
          resolve(creative);
        });
      });
    }, handle_error)
    .then(function (creatives) {
      grunt.verbose.writeln("compare creative and local files...");
      //get txt files from settings and compare with local files
      return new Promise(function (resolve, reject) {
        var tasks = [];
        files.forEach(function(f, index){
          var creative = _.chain(creatives)
                          .find(function(obj){
                            return obj.creative_name === f.filename;
                          })
                          .value();
          if(creative){
            var localcontent = fs.readFileSync(f.src,'utf8');
            var localmd5 = crypto.createHash('md5');
            localcontent = localcontent.replace(/\r/g, "");
            localmd5.update(localcontent);
            var localmd5Hash = localmd5.digest('hex');
            var remotemd5 = crypto.createHash('md5');
            remotemd5.update(creative.content);
            var remotemd5Hash = remotemd5.digest('hex');

            if(localmd5Hash === remotemd5Hash){
              grunt.log.writeln("skip " + f.src + ".");
            }else{
              creative.content = localcontent;
              tasks.push(function (callback) {
                tools_api.replace_files_to_campaign(settings, campaign, creative, function (error, result) {
                  if(error){
                    callback(error, null);
                  }else{
                    grunt.log.writeln("replace " + f.src + ".");
                    if (result.is_staging === true) {
                        grunt.log.writeln('\n-----------------------------------------------');
                        grunt.log.writeln(result.creative_name + " IS IN STAGING."["red"].bold);
                        grunt.log.writeln("PLEASE GO TO"["yellow"] + " https://tools.complex.com/" + result.campaign_id + " TO PUBLISH IT."["yellow"]);
                        grunt.log.writeln('-----------------------------------------------\n');
                    }
                    callback(null, result);
                  }
                });
              });
            }
          }else{
            tasks.push(function (callback) {
              tools_api.upload_files_to_campaign(settings, campaign,  f.src, function (error, result) {
                if(error){
                  callback(error, null);
                }
                grunt.log.writeln("upload " + f.src + ".");
                callback(null, result);
              });
            });
          }
        });
        async.parallel(tasks, function (err, results) {
          if(err){
            reject(err);
          }
          resolve(results);
        });
      });
    }, handle_error)
    .done(function () {
      grunt.verbose.ok("done.");
       done();
    }, handle_error);
  });

};
<commit_msg>fix some logic errors.<commit_after>/*
 * grunt-tools-dev
 * https://github.com/yanwsh/grunt-tools-dev
 *
 * Copyright (c) 2016 Wensheng Yan
 * Licensed under the MIT license.
 */

'use strict';

var request   = require('request'),
    _         = require('underscore'),
    jsonfile  = require('jsonfile'),
    inquirer  = require('inquirer'),
    Promise   = require('promise'),
    path      = require("path"),
    crypto    = require('crypto'),
    tools_api = require('./tools_api.js'),
    fs = require('fs'),
    async     = require("async");

var DEFAULT_CONFIG_FILE = ".tools.json";

module.exports = function(grunt) {

  grunt.registerMultiTask('tools_dev', 'automation tools for tools.complex.com', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      configFile: DEFAULT_CONFIG_FILE,
      campaignFile: 'campaign.json'
    });

    var configFile = options.configFile;
    var campaignFile = options.campaignFile;
    var createCampaign = grunt.option('create-campaign');
    var done = this.async();

    //get files info according to the settings.
    var files = [];
    this.files.forEach(function(file) {
      var cwd = file.cwd || '';
      files = files.concat(file.src.map(function(src) {
        var s = path.join(cwd, src);
        var filepath = src.substr(0, src.lastIndexOf('/') + 1);
        var filename_w_ext = src.replace(filepath, "");
        var filename = filename_w_ext.substr(0, filename_w_ext.lastIndexOf('.'));

        return {'path' : filepath, 'src':s, 'filename': filename, 'filenameWithExt': filename_w_ext};
      }));
    });

    function needSetting(){
      return function (answers) {
        return answers['isSetting'];
      }
    }

    function isNormalInteger(str) {
      var n = ~~Number(str);
      return String(n) === str && n >= 0;
    }

    var settings = {};
    var campaign = {};
    var creative = {};

    function handle_error(err) {
      if(err){
	grunt.fail.warn("Error:" + err);
      }

      done();
      //get rid of other error message and prevent continue running.
      return Promise.reject(false);
    }

    new Promise(function (resolve, reject) {
      //get or set config file
      if(!grunt.file.exists(configFile)){
        grunt.log.errorlns("Missing tools dev config file.");

        inquirer.prompt([
          {
            type: "confirm",
            name: "isSetting",
            message: "Do you want to set it up right now?",
            default: true
          },
          {
            type: "input",
            name: "toolsURL",
            message: "Please input tools url link.",
            default: "https://tools.complex.com/",
            when: needSetting()
          },
          {
            type: "input",
            name: "token",
            message: function(answer){
              return "please input your token for " + answer["toolsURL"] + "."
            },
            when: needSetting(),
            validate: function (input) {
              var key = new Buffer(input, 'base64').toString('ascii');
              var error_message = "The token which you provide is not valid. Please try again.";

              var index = key.indexOf('.');
              if(index <= 0){
                return false;
              }
              var id = key.substring(0, index);
              var realkey = key.substring(index + 1);
              var result = (isNormalInteger(id) && realkey.length === 16)? true : error_message;
              return result;
            }
          }
        ], function(answer){
          if(!answer.isSetting){
            reject(false);
          }else{
            settings = {
              url: answer.toolsURL,
              token: answer.token
            };
            jsonfile.writeFileSync(configFile, settings);
            resolve(settings);
          }
        });
      }else{
        settings = jsonfile.readFileSync(configFile);
        resolve(settings);
      }
    }).then(function (settings) {
      if(createCampaign){
        //create a campaign
        grunt.verbose.writeln("creating campaign...");
        return new Promise(function (resolve, reject) {
          if(createCampaign === true){
            reject("You need to set a campaign name. Usuage --create-campaign=\"test-campaign\"");
          }
          tools_api.create_new_campaign(settings, createCampaign, function (error, result) {
             if(error){
               reject(error);
             }else{
               grunt.log.writeln("campaign name: " + createCampaign + " created on tools.");
               jsonfile.writeFileSync(campaignFile, result);
	           done();
             }
          });
        });
      }

      return settings;
    }, handle_error)
    .then(function (settings) {
      //get or set campaign file
      grunt.verbose.writeln("get or set campaign from file...");
      if(!grunt.file.exists(campaignFile)){
        return new Promise(function (resolve, reject) {
          inquirer.prompt([
            {
              type: "confirm",
              name: "isSetting",
              message: "You didn't bind any campaign. Do you want to bind a campaign?",
              default: true
            }
          ], function (answer) {
            if(!answer.isSetting){
              reject(false);
            }
            resolve(answer.isSetting);
          });
        }).then(function () {
          return new Promise(function (resolve, reject) {
            async.retry(3,
                function (callback, result) {
                  inquirer.prompt([
                    {
                      type: "input",
                      name: "campaignId",
                      message: "Please input campaign id: "
                    }
                  ], function (answer) {
                    var link = 'api/campaigns/' + answer.campaignId;
                    var options = {
                      method: 'GET',
                      url: link,
                      baseUrl: settings.url,
                      jar: true,
                      headers: {
                        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36',
                        'X-Requested-With': 'XMLHttpRequest',
                        'auth-token': settings.token
                      }
                    };
                    request(options, function (error, response, body) {
                      if(error){
                        callback(error, null);
                      }
                      try{
                        var obj = JSON.parse(body);
                        var error;
                        if(obj.errors){
                          error = obj.errors.message;
                          grunt.log.errorlns("Error:" + error);
                        }
                        callback(error, obj);
                      }
                      catch(e){
                        callback(error, null);
                      }
                    });
                  });
                },
                function (err, result) {
                  if(err) reject(err);
                  campaign = result;
                  jsonfile.writeFileSync(campaignFile, campaign);
                  resolve(campaign);
                }
            );
          });
        });
      }else{
        campaign = jsonfile.readFileSync(campaignFile);
        return campaign;
      }
    }, handle_error)
    .then(function (campaign) {
        //get creative list first
      grunt.verbose.writeln("getting creative list...");
      return new Promise(function (resolve, reject) {
        tools_api.get_creative_list(settings, campaign, function (error, result) {
          if(error){
            reject(error);
          }
          creative = result;
          resolve(creative);
        });
      });
    }, handle_error)
    .then(function (creatives) {
      grunt.verbose.writeln("compare creative and local files...");
      //get txt files from settings and compare with local files
      return new Promise(function (resolve, reject) {
        var tasks = [];
        files.forEach(function(f, index){
          var creative = _.chain(creatives)
                          .find(function(obj){
                            return obj.creative_name === f.filename;
                          })
                          .value();
          if(creative){
            var localcontent = fs.readFileSync(f.src,'utf8');
            var localmd5 = crypto.createHash('md5');
            localcontent = localcontent.replace(/\r/g, "");
            localmd5.update(localcontent);
            var localmd5Hash = localmd5.digest('hex');
            var remotemd5 = crypto.createHash('md5');
            remotemd5.update(creative.content);
            var remotemd5Hash = remotemd5.digest('hex');

            if(localmd5Hash === remotemd5Hash){
              grunt.log.writeln("skip " + f.src + ".");
            }else{
              creative.content = localcontent;
              tasks.push(function (callback) {
                tools_api.replace_files_to_campaign(settings, campaign, creative, function (error, result) {
                  if(error){
                    return callback(error, null);
                  }else{
                    grunt.log.writeln("replace " + f.src + ".");
                    if (result.is_staging === true) {
                        grunt.log.writeln('\n-----------------------------------------------');
                        grunt.log.writeln(result.creative_name + " IS IN STAGING."["red"].bold);
                        grunt.log.writeln("PLEASE GO TO"["yellow"] + " https://tools.complex.com/" + result.campaign_id + " TO PUBLISH IT."["yellow"]);
                        grunt.log.writeln('-----------------------------------------------\n');
                    }
                    callback(null, result);
                  }
                });
              });
            }
          }else{
            tasks.push(function (callback) {
              tools_api.upload_files_to_campaign(settings, campaign,  f.src, function (error, result) {
                if(error){
                  return callback(error, null);
                }
                grunt.log.writeln("upload " + f.src + ".");
                callback(null, result);
              });
            });
          }
        });
        async.parallel(tasks, function (err, results) {
          if(err){
            return reject(err);
          }
          resolve(results);
        });
      });
    }, handle_error)
    .done(function () {
      grunt.verbose.ok("done.");
       done();
    }, handle_error);
  });

};
<|endoftext|>


<commit_before>import React, {
	PropTypes
} from 'react'

import {
	Table,
	Popconfirm,
	Button
} from 'antd'

const {
	Column,
	ColumnGroup
} = Table

const {
	ipcRenderer
} = require('electron')

class ContentTable extends React.Component {
	constructor(props) {
		super(props)
		this.state = {
			content: []
		}

		ipcRenderer.on('onefile-get', (event, file) => {
			let content = this.state.content
			this.setState({
				content: content.concat(file)
			})
		})
	}

	render() {
		return (

				<Column
					title="名称"
					dataIndex="name"
					key="name"
					width='300'
				/>
				<Column
					title="大小"
					dataIndex="size"
					key="size"
					width="100"
				/>
				<Column
					title="标签"
					dataIndex="tags"
					key="tags"
					width="200"
				/>
				<Column
					title="观看次数"
					dataIndex="times"
					key="times"
					width="100"
				/>

		)
	}
}

export default ContentTable<commit_msg>增加点击播放功能<commit_after>import React, {
	PropTypes
} from 'react'

import {
	Table,
	Popconfirm,
	Button
} from 'antd'

const {
	Column,
	ColumnGroup
} = Table

const {
	ipcRenderer,
	shell
} = require('electron')

class ContentTable extends React.Component {
	constructor(props) {
		super(props)
		this.state = {
			content: []
		}

		this.handleNameClick = function(event) {
			event.preventDefault()
				// console.log(event.target)
			console.log(this.filePath.href)
			console.log(shell.openItem(this.filePath.href))
		}.bind(this)

		ipcRenderer.on('onefile-get', (event, file) => {
			let content = this.state.content
			this.setState({
				content: content.concat(file)
			})
		})
	}

	render() {
		return (

				<Column
					title="名称"
					// dataIndex="name"
					key="name"
					width={300}
					render={(text,record, index) => (

							 {this.filePath = a}}
								onClick={this.handleNameClick}
							>
								{text.name}

					)}
				/>
				<Column
					title="大小"
					dataIndex="size"
					key="size"
					width={100}
				/>
				<Column
					title="标签"
					dataIndex="tags"
					key="tags"
					width={200}
				/>
				<Column
					title="观看次数"
					dataIndex="times"
					key="times"

				/>

		)
	}
}

export default ContentTable<|endoftext|>


<commit_before>myApp.directive('financeInput', function () {
	return {
		restrict: 'A',
		require: 'ngModel',
		link: function (scope, element, attrs, ctrl) {

			function clean(numericString) {
				//get rid of non numeric input
				return numericString.replace(/[^\d.]/g, '');
			}

			element.bind("keyup", function (evt) {
				if (evt.keyCode == 75) {
					var inputVal = element.val();
					inputVal = clean(inputVal);
					var parsedVal = parseFloat(inputVal);
					var final = parsedVal * 1000;
					if (final > 1000000000) {
						element.val(999999999);
					}
					else {
						element.val(final);
					}
				}

				if (evt.keyCode == 77) {
					var inputVal = element.val();
					inputVal = clean(inputVal);
					var parsedVal = parseFloat(inputVal);
					var final = parsedVal * 1000000;
					if (final > 1000000000) {
						element.val(999999999);
					}
					else {
						element.val(final);
					}
				}

				if (evt.keyCode == 66) {
					var inputVal = element.val();
					inputVal = clean(inputVal);
					var parsedVal = parseFloat(inputVal);
					var final = parsedVal * 1000000000;
					if (final > 1000000000) {
						element.val(999999999);
					}
					else {
						element.val(final);
					}
				}
			});

			element.bind("blur", function (evt) {

				var inputVal =  clean(element.val());
				parsed = parseFloat(inputVal).toString();
				//clear ending zeros
				element.val(addCommas(parsed));

			});

			function addCommas(inputVal) {
				var decimalSplit = inputVal.split(".");
				var intPart = decimalSplit[0];
				var decPart = decimalSplit[1];

				if (intPart.length > 3) {
					var intDiv = Math.floor(intPart.length / 3);
					while (intDiv > 0) {
						var lastComma = intPart.indexOf(",");
						if (lastComma < 0) {
							lastComma = intPart.length;
						}
						if (lastComma - 3 > 0) {
							intPart = intPart.slice(0, lastComma - 3) + "," + intPart.slice(lastComma - 3);
						}
						intDiv--;
					}
				}

				if (decPart === undefined) {
					decPart = "";
				}
				else {
					decPart = "." + decPart;
				}
				var res = intPart + decPart;
				return res;
			}

			return ctrl.$parsers.push(function (inputValue) {
				var inputVal = element.val();

				//get rid of bad input
				inputVal = clean(inputVal);

				//clear trailing zeros
				while (inputVal.charAt(0) == '0') {
					inputVal = inputVal.substr(1);
				}

				//we now have pure number, test for precision and remove least significant digit
				if (inputVal.replace(/[^0-9]/g, "").length > 10) {
					inputVal = inputVal.match(/(([0-9][,.]?){10})/).shift();
				}

				var res = addCommas(inputVal);
				if (res != inputValue) {
					ctrl.$setViewValue(res);
					ctrl.$render();
				}
			});

		}
	};
});<commit_msg>add commas while multipling<commit_after>myApp.directive('financeInput', function () {
	return {
		restrict: 'A',
		require: 'ngModel',
		link: function (scope, element, attrs, ctrl) {

			function clean(numericString) {
				//get rid of non numeric input
				return numericString.replace(/[^\d.]/g, '');
			}

			element.bind("keyup", function (evt) {
				if (evt.keyCode == 75) {
					var inputVal = element.val();
					inputVal = clean(inputVal);
					var parsedVal = parseFloat(inputVal);
					var final = parsedVal * 1000;
					if (final > 1000000000) {
						element.val(999999999);
					}
					else {
						element.val(addCommas(final));
					}
				}

				if (evt.keyCode == 77) {
					var inputVal = element.val();
					inputVal = clean(inputVal);
					var parsedVal = parseFloat(inputVal);
					var final = parsedVal * 1000000;
					if (final > 1000000000) {
						element.val(999999999);
					}
					else {
						element.val(final);
					}
				}

				if (evt.keyCode == 66) {
					var inputVal = element.val();
					inputVal = clean(inputVal);
					var parsedVal = parseFloat(inputVal);
					var final = parsedVal * 1000000000;
					if (final > 1000000000) {
						element.val(999999999);
					}
					else {
						element.val(final);
					}
				}
			});

			element.bind("blur", function (evt) {

				var inputVal =  clean(element.val());
				parsed = parseFloat(inputVal).toString();
				//clear ending zeros
				element.val(addCommas(parsed));

			});

			function addCommas(inputVal) {
				//сonvert to string
				inputVal = inputVal.toString();

				var decimalSplit = inputVal.split(".");
				var intPart = decimalSplit[0];
				var decPart = decimalSplit[1];

				if (intPart.length > 3) {
					var intDiv = Math.floor(intPart.length / 3);
					while (intDiv > 0) {
						var lastComma = intPart.indexOf(",");
						if (lastComma < 0) {
							lastComma = intPart.length;
						}
						if (lastComma - 3 > 0) {
							intPart = intPart.slice(0, lastComma - 3) + "," + intPart.slice(lastComma - 3);
						}
						intDiv--;
					}
				}

				if (decPart === undefined) {
					decPart = "";
				}
				else {
					decPart = "." + decPart;
				}
				var res = intPart + decPart;
				return res;
			}

			return ctrl.$parsers.push(function (inputValue) {
				var inputVal = element.val();

				//get rid of bad input
				inputVal = clean(inputVal);

				//clear trailing zeros
				while (inputVal.charAt(0) == '0') {
					inputVal = inputVal.substr(1);
				}

				//we now have pure number, test for precision and remove least significant digit
				if (inputVal.replace(/[^0-9]/g, "").length > 10) {
					inputVal = inputVal.match(/(([0-9][,.]?){10})/).shift();
				}

				var res = addCommas(inputVal);
				if (res != inputValue) {
					ctrl.$setViewValue(res);
					ctrl.$render();
				}
			});

		}
	};
});<|endoftext|>