<commit_before>// FIXME add minZoom support

goog.provide('ol.source.TiledWMS');

goog.require('goog.array');
goog.require('ol.Extent');
goog.require('ol.TileCoord');
goog.require('ol.TileUrlFunction');
goog.require('ol.source.ImageTileSource');

/**
 * @constructor
 * @extends {ol.source.ImageTileSource}
 * @param {ol.source.TiledWMSOptions} tiledWMSOptions options.
 */
ol.source.TiledWMS = function(tiledWMSOptions) {
  var tileGrid;
  if (goog.isDef(tiledWMSOptions.tileGrid)) {
    tileGrid = tiledWMSOptions.tileGrid;
  }
  var version = tiledWMSOptions.version;

  var tileUrlFunction;
  if (tiledWMSOptions.urls) {
    var tileUrlFunctions = goog.array.map(
        tiledWMSOptions.urls, function(url) {
          return ol.TileUrlFunction.createWMSParams(
              url, tiledWMSOptions.params, version);
        });
    tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions(
        tileUrlFunctions);
  } else if (tiledWMSOptions.url) {
    tileUrlFunction = ol.TileUrlFunction.createWMSParams(
        tiledWMSOptions.url, tiledWMSOptions.params, version);
  } else {
    tileUrlFunction = ol.TileUrlFunction.nullTileUrlFunction;
  }
  var transparent = goog.isDef(tiledWMSOptions.transparent) ?
      tiledWMSOptions.transparent : true;
  var extent = tiledWMSOptions.extent;

  var tileCoordTransform = function(tileCoord, tileGrid, projection) {
    if (tileGrid.getResolutions().length <= tileCoord.z) {
      return null;
    }
    var x = tileCoord.x;
    var tileExtent = tileGrid.getTileCoordExtent(tileCoord);
    var projectionExtent = projection.getExtent();
    var extent = goog.isDef(tiledWMSOptions.extent) ?
        tiledWMSOptions.extent : projectionExtent;
    // FIXME do we want a wrapDateLine param? The code below will break maps
    // with projections that do not span the whole world width.
    if (extent.minX === projectionExtent.minX &&
        extent.maxX === projectionExtent.maxX) {
      var numCols = Math.ceil(
          (extent.maxX - extent.minX) / (tileExtent.maxX - tileExtent.minX));
      x = goog.math.modulo(x, numCols);
      tileExtent = tileGrid.getTileCoordExtent(
          new ol.TileCoord(tileCoord.z, x, tileCoord.y));
    }
    // FIXME We shouldn't need a typecast here.
    if (!tileExtent.intersects(/** @type {ol.Extent} */ (extent))) {
      return null;
    }
    return new ol.TileCoord(tileCoord.z, x, tileCoord.y);
  };

  goog.base(this, {
    attributions: tiledWMSOptions.attributions,
    crossOrigin: tiledWMSOptions.crossOrigin,
    extent: extent,
    tileGrid: tiledWMSOptions.tileGrid,
    opaque: !transparent,
    projection: tiledWMSOptions.projection,
    tileUrlFunction: ol.TileUrlFunction.withTileCoordTransform(
        tileCoordTransform, tileUrlFunction)
  });

};
goog.inherits(ol.source.TiledWMS, ol.source.ImageTileSource);
<commit_msg>Do not use tiledWMSOptions in closure function<commit_after>// FIXME add minZoom support

goog.provide('ol.source.TiledWMS');

goog.require('goog.array');
goog.require('ol.Extent');
goog.require('ol.TileCoord');
goog.require('ol.TileUrlFunction');
goog.require('ol.source.ImageTileSource');

/**
 * @constructor
 * @extends {ol.source.ImageTileSource}
 * @param {ol.source.TiledWMSOptions} tiledWMSOptions options.
 */
ol.source.TiledWMS = function(tiledWMSOptions) {
  var tileGrid;
  if (goog.isDef(tiledWMSOptions.tileGrid)) {
    tileGrid = tiledWMSOptions.tileGrid;
  }
  var version = tiledWMSOptions.version;

  var tileUrlFunction;
  if (tiledWMSOptions.urls) {
    var tileUrlFunctions = goog.array.map(
        tiledWMSOptions.urls, function(url) {
          return ol.TileUrlFunction.createWMSParams(
              url, tiledWMSOptions.params, version);
        });
    tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions(
        tileUrlFunctions);
  } else if (tiledWMSOptions.url) {
    tileUrlFunction = ol.TileUrlFunction.createWMSParams(
        tiledWMSOptions.url, tiledWMSOptions.params, version);
  } else {
    tileUrlFunction = ol.TileUrlFunction.nullTileUrlFunction;
  }
  var transparent = goog.isDef(tiledWMSOptions.transparent) ?
      tiledWMSOptions.transparent : true;
  var extent = tiledWMSOptions.extent;

  var tileCoordTransform = function(tileCoord, tileGrid, projection) {
    if (tileGrid.getResolutions().length <= tileCoord.z) {
      return null;
    }
    var x = tileCoord.x;
    var tileExtent = tileGrid.getTileCoordExtent(tileCoord);
    var projectionExtent = projection.getExtent();
    extent = goog.isDef(extent) ? extent : projectionExtent;
    // FIXME do we want a wrapDateLine param? The code below will break maps
    // with projections that do not span the whole world width.
    if (extent.minX === projectionExtent.minX &&
        extent.maxX === projectionExtent.maxX) {
      var numCols = Math.ceil(
          (extent.maxX - extent.minX) / (tileExtent.maxX - tileExtent.minX));
      x = goog.math.modulo(x, numCols);
      tileExtent = tileGrid.getTileCoordExtent(
          new ol.TileCoord(tileCoord.z, x, tileCoord.y));
    }
    // FIXME We shouldn't need a typecast here.
    if (!tileExtent.intersects(/** @type {ol.Extent} */ (extent))) {
      return null;
    }
    return new ol.TileCoord(tileCoord.z, x, tileCoord.y);
  };

  goog.base(this, {
    attributions: tiledWMSOptions.attributions,
    crossOrigin: tiledWMSOptions.crossOrigin,
    extent: extent,
    tileGrid: tiledWMSOptions.tileGrid,
    opaque: !transparent,
    projection: tiledWMSOptions.projection,
    tileUrlFunction: ol.TileUrlFunction.withTileCoordTransform(
        tileCoordTransform, tileUrlFunction)
  });

};
goog.inherits(ol.source.TiledWMS, ol.source.ImageTileSource);
<|endoftext|>


<commit_before>var request = require('request'),
	JSONStream = require('JSONStream');

// credentials
	// flowdock
var apiToken = "",
	flows = [],
	// github
	githubToken = "",
	githubDomain = null, // null for default
	// weather underground
	wunderToken = "";

// get flow data
var flowData = {};
for (var i = 0; i < flows.length; i++) {
	request(encodeURI("https://" + apiToken + ":DUMMY@api.flowdock.com/flows/" + flows[i]), function(error, response, body) {
		if (!error && response.statusCode == 200) {
			var flow = JSON.parse(body);
			flowData[flow.id] = { name: flow.organization.parameterized_name + "/" + flow.parameterized_name, token: flow.api_token };
		}
		else console.log("Error getting flow data: " + (error || response) + "\n");
	});
}

// stream messages
var stream = request(encodeURI("https://" + apiToken + ":DUMMY@stream.flowdock.com/flows?filter=" + flows.join(",")))
	.pipe(JSONStream.parse());
stream.on('data', function(data) {
	if (data.event == "message" && typeof data.content == "string") {

		// check if message is for CheezeBot
		var match = data.content.match(/chee(?:s|z)ebot (.+)/i);
		if (match) {
			var message = match[1];

			// post reply
			var reply;
			for (var i = 0; i < commands.length; i++) {
				var command = commands[i];
				var match = message.match(command.pattern);
				if (match) {
					reply = command.reply(match, data);
					break;
				}
			}
			if (reply != null && reply != undefined) post(reply, data);
		}
	}
});

// post a message
function post(reply, data) {
	var flow = flowData[data.flow];
	var options = {
		url: encodeURI("https://api.flowdock.com/v1/messages/chat/" + flow.token),
		method: "POST",
		headers: { "Content-Type": "application/json" },
		body: JSON.stringify({ "content": reply.toString(), "external_user_name": "CheezeBot" })
	};
	request(options, function(error, response, body) {
		// log
		if (!error && response.statusCode == 200) {
			if (data) console.log("---" + flow.name + "---\n" + data.user + ": " + data.content);
			console.log("CheezeBot: " + reply + "\n");
		}
		else console.log("Error posting reply: " + (error || response) + "\n");
	});
}

// timer data
var timers = [];

/* commands:
   each command requires
	 * a description (for the help listing)
	 * a regex pattern to trigger the command
	 * a reply method which returns CheezeBot's reply (or null for no reply)
	   (alternately, reply can call the "post" method directly, which is useful inside a callback)
*/
var commands = [
	{
		description: "help:\t\t\t\tdisplay this message",
		pattern: /^help/,
		reply: function(match) {
			var help = "CheezeBot commands:";
			for (var i = 0; i < commands.length; i++) {
				var command = commands[i];
				help += "\n\t" + command.description;
			}
			return help;
		}
	},
	{
		description: "cheese:\t\t\t\tname a type of cheese",
		pattern: /^chee(?:s|z)e/,
		reply: function(match) {
			var cheeses = ["Anejo", "Asiago", "Blue", "Brie", "Butterkase", "Camembert", "Cheddar", "Chevres",
						   "Colby", "Cotija", "Edam", "Feta", "Fontina", "Gorgonzola", "Gouda", "Gruyere",
						   "Havarti", "Limburger", "Monterey Jack", "Mozzarella", "Munster", "Neufchatel",
						   "Parmesan", "Provolone", "Queso Blanco", "Raclette", "Romano", "Swiss"];
			return cheeses[Math.floor(Math.random() * cheeses.length)];
		}
	},
	{
		description: "now:\t\t\t\tcurrent date and time",
		pattern: /^now/,
		reply: function(match) {
			var date = new Date();
			return date.toDateString() + " - " + date.toTimeString();
		}
	},
	{
		description: "gif {search string}:\t\tshow a gif based on a search string",
		pattern: /^gif (.+)/,
		reply: function(match, data) {
			request(encodeURI("http://api.giphy.com/v1/gifs/search?api_key=dc6zaTOxFJmzC&limit=1&q=" + match[1]),
				function(error, response, body) {
					if (!error && response.statusCode == 200) {
						var imageData = JSON.parse(body).data[0];
						if (imageData) post(imageData.images.original.url, data);
						else post("No suitable gif found - try a different search", data);
					}
					else console.log("Error requesting gif: " + (error || response) + "\n");
				});
		}
	},
	{
		description: "timer [start|stop]:\t\tstart/stop a timer",
		pattern: /^timer(?: (start|stop))?/,
		reply: function(match, data) {
			var command = match[1];
			var time = 0;
			if (command == "start") timers[data.user] = new Date().getTime();
			else {
				time = (new Date().getTime() - timers[data.user]) / 1000;
				if (command == "stop") timers[data.user] = undefined;
			}
			return "timer: " + time + " s";
		}
	},
	{
		description: "roll {dice}d{sides}:\t\troll dice (eg roll 2d6)",
		pattern: /^roll (\d*)d(\d+)/,
		reply: function(match) {
			var dice = Number(match[1]) || 1;
			var sides = Number(match[2]);
			var result = "";
			for (var i = 0; i < dice; i++) {
				result += (Math.floor(Math.random() * sides) + 1) + " ";
			}
			return result;
		}
	},
	{
		description: "math {func} [{params...}]:\tmath functions (eg cos, floor, pow)",
		pattern: /^math( [^ ]+)+/,
		reply: function(match) {
			var args = match[0].split(" ");
			var func = Math[args[1]];
			if (typeof func == "function") {
				args = args.slice(2).map(function(x) { return Number(x); });
				return func.apply(this, args);
			}
			else if (func != undefined) {
				return func;
			}
			return "math function unknown: " + args[1];
		}
	},
	{
		description: "pullrequests {user}/{repo}:\tlist open pull requests",
		pattern: /^pullrequests (.+\/.+)/,
		reply: function(match, data) {
			var repo = match[1].trim();
			var domain = githubDomain ? githubDomain + "/api/v3" : "https://api.github.com";
			var options = {
				url: encodeURI(domain + "/repos/" + repo + "/pulls?access_token=" + githubToken),
				method: "GET",
				rejectUnauthorized: false,
				headers: { "User-Agent": "CheezeBot" }
			};
			request(options, function(error, response, body) {
				if (!error && response.statusCode == 200) {
					var prs = JSON.parse(body);
					if (prs.length) {
						var result = "Pull requests for " + repo + ":";
						for (var i = 0; i < prs.length; i++) {
							var pr = prs[i];
							result += "\n\t*  " + pr.title + ": " + pr.html_url;
						}
						post(result, data);
					}
					else post("no open pull requests for " + repo, data);
				}
				else console.log("Error requesting github data: " + (error || response) + "\n");
			});
		}
	},
	{
		description: "weather {city}:\t\t\tweather forecast information",
		pattern: /^weather (.+)/,
		reply: function(match, data) {
			request(encodeURI("http://autocomplete.wunderground.com/aq?query=" + match[1]), function(error, response, body) {
				if (!error && response.statusCode == 200) {
					var cities = JSON.parse(body).RESULTS;
					if (cities.length)  {
						request(encodeURI("http://api.wunderground.com/api/" + wunderToken + "/forecast10day" + cities[0].l + ".json"),
							function(error, response, body) {
								if (!error && response.statusCode == 200) {
									var forecast = JSON.parse(body).forecast;
									if (forecast) {
										var forecastDays = forecast.simpleforecast.forecastday;
										var result = "Weather forecast for " + cities[0].name + ":";
										for (var i = 0; i < 7; i++) {
											var day = forecastDays[i];
											result += "\n\t*  " + day.date.weekday + ":\t" + pad(20, day.conditions).substr(0, 20) + "| " +
													  day.high.celsius + "/" + day.low.celsius + "°C\t| " +
													  day.avewind.kph + "kph " + day.avewind.dir;
										}
										post(result, data);
									}
									else post("No weather information found", data);
								}
								else console.log("Error requesting weather information: " + (error || response) + "\n");
							});
					}
					else post("No city found matching search", data);
				}
				else console.log("Error requesting weather information: " + (error || response) + "\n");
			});
		}
	},
	{
		description: "about:\t\t\t\tdeveloper and source info",
		pattern: /^about/,
		reply: function() {
			return "CheezeBot by Adam-G\nSource: https://github.com/akg1852/CheezeBot\nSuggestions or contributions welcome.";
		}
	},
];

// utility functions
function pad(len, str) {
	while (str.length < len) str += " ";
	return str;
}
<commit_msg>shorten source url<commit_after>var request = require('request'),
	JSONStream = require('JSONStream');

// credentials
	// flowdock
var apiToken = "",
	flows = [],
	// github
	githubToken = "",
	githubDomain = null, // null for default
	// weather underground
	wunderToken = "";

// get flow data
var flowData = {};
for (var i = 0; i < flows.length; i++) {
	request(encodeURI("https://" + apiToken + ":DUMMY@api.flowdock.com/flows/" + flows[i]), function(error, response, body) {
		if (!error && response.statusCode == 200) {
			var flow = JSON.parse(body);
			flowData[flow.id] = { name: flow.organization.parameterized_name + "/" + flow.parameterized_name, token: flow.api_token };
		}
		else console.log("Error getting flow data: " + (error || response) + "\n");
	});
}

// stream messages
var stream = request(encodeURI("https://" + apiToken + ":DUMMY@stream.flowdock.com/flows?filter=" + flows.join(",")))
	.pipe(JSONStream.parse());
stream.on('data', function(data) {
	if (data.event == "message" && typeof data.content == "string") {

		// check if message is for CheezeBot
		var match = data.content.match(/chee(?:s|z)ebot (.+)/i);
		if (match) {
			var message = match[1];

			// post reply
			var reply;
			for (var i = 0; i < commands.length; i++) {
				var command = commands[i];
				var match = message.match(command.pattern);
				if (match) {
					reply = command.reply(match, data);
					break;
				}
			}
			if (reply != null && reply != undefined) post(reply, data);
		}
	}
});

// post a message
function post(reply, data) {
	var flow = flowData[data.flow];
	var options = {
		url: encodeURI("https://api.flowdock.com/v1/messages/chat/" + flow.token),
		method: "POST",
		headers: { "Content-Type": "application/json" },
		body: JSON.stringify({ "content": reply.toString(), "external_user_name": "CheezeBot" })
	};
	request(options, function(error, response, body) {
		// log
		if (!error && response.statusCode == 200) {
			if (data) console.log("---" + flow.name + "---\n" + data.user + ": " + data.content);
			console.log("CheezeBot: " + reply + "\n");
		}
		else console.log("Error posting reply: " + (error || response) + "\n");
	});
}

// timer data
var timers = [];

/* commands:
   each command requires
	 * a description (for the help listing)
	 * a regex pattern to trigger the command
	 * a reply method which returns CheezeBot's reply (or null for no reply)
	   (alternately, reply can call the "post" method directly, which is useful inside a callback)
*/
var commands = [
	{
		description: "help:\t\t\t\tdisplay this message",
		pattern: /^help/,
		reply: function(match) {
			var help = "CheezeBot commands:";
			for (var i = 0; i < commands.length; i++) {
				var command = commands[i];
				help += "\n\t" + command.description;
			}
			return help;
		}
	},
	{
		description: "cheese:\t\t\t\tname a type of cheese",
		pattern: /^chee(?:s|z)e/,
		reply: function(match) {
			var cheeses = ["Anejo", "Asiago", "Blue", "Brie", "Butterkase", "Camembert", "Cheddar", "Chevres",
						   "Colby", "Cotija", "Edam", "Feta", "Fontina", "Gorgonzola", "Gouda", "Gruyere",
						   "Havarti", "Limburger", "Monterey Jack", "Mozzarella", "Munster", "Neufchatel",
						   "Parmesan", "Provolone", "Queso Blanco", "Raclette", "Romano", "Swiss"];
			return cheeses[Math.floor(Math.random() * cheeses.length)];
		}
	},
	{
		description: "now:\t\t\t\tcurrent date and time",
		pattern: /^now/,
		reply: function(match) {
			var date = new Date();
			return date.toDateString() + " - " + date.toTimeString();
		}
	},
	{
		description: "gif {search string}:\t\tshow a gif based on a search string",
		pattern: /^gif (.+)/,
		reply: function(match, data) {
			request(encodeURI("http://api.giphy.com/v1/gifs/search?api_key=dc6zaTOxFJmzC&limit=1&q=" + match[1]),
				function(error, response, body) {
					if (!error && response.statusCode == 200) {
						var imageData = JSON.parse(body).data[0];
						if (imageData) post(imageData.images.original.url, data);
						else post("No suitable gif found - try a different search", data);
					}
					else console.log("Error requesting gif: " + (error || response) + "\n");
				});
		}
	},
	{
		description: "timer [start|stop]:\t\tstart/stop a timer",
		pattern: /^timer(?: (start|stop))?/,
		reply: function(match, data) {
			var command = match[1];
			var time = 0;
			if (command == "start") timers[data.user] = new Date().getTime();
			else {
				time = (new Date().getTime() - timers[data.user]) / 1000;
				if (command == "stop") timers[data.user] = undefined;
			}
			return "timer: " + time + " s";
		}
	},
	{
		description: "roll {dice}d{sides}:\t\troll dice (eg roll 2d6)",
		pattern: /^roll (\d*)d(\d+)/,
		reply: function(match) {
			var dice = Number(match[1]) || 1;
			var sides = Number(match[2]);
			var result = "";
			for (var i = 0; i < dice; i++) {
				result += (Math.floor(Math.random() * sides) + 1) + " ";
			}
			return result;
		}
	},
	{
		description: "math {func} [{params...}]:\tmath functions (eg cos, floor, pow)",
		pattern: /^math( [^ ]+)+/,
		reply: function(match) {
			var args = match[0].split(" ");
			var func = Math[args[1]];
			if (typeof func == "function") {
				args = args.slice(2).map(function(x) { return Number(x); });
				return func.apply(this, args);
			}
			else if (func != undefined) {
				return func;
			}
			return "math function unknown: " + args[1];
		}
	},
	{
		description: "pullrequests {user}/{repo}:\tlist open pull requests",
		pattern: /^pullrequests (.+\/.+)/,
		reply: function(match, data) {
			var repo = match[1].trim();
			var domain = githubDomain ? githubDomain + "/api/v3" : "https://api.github.com";
			var options = {
				url: encodeURI(domain + "/repos/" + repo + "/pulls?access_token=" + githubToken),
				method: "GET",
				rejectUnauthorized: false,
				headers: { "User-Agent": "CheezeBot" }
			};
			request(options, function(error, response, body) {
				if (!error && response.statusCode == 200) {
					var prs = JSON.parse(body);
					if (prs.length) {
						var result = "Pull requests for " + repo + ":";
						for (var i = 0; i < prs.length; i++) {
							var pr = prs[i];
							result += "\n\t*  " + pr.title + ": " + pr.html_url;
						}
						post(result, data);
					}
					else post("no open pull requests for " + repo, data);
				}
				else console.log("Error requesting github data: " + (error || response) + "\n");
			});
		}
	},
	{
		description: "weather {city}:\t\t\tweather forecast information",
		pattern: /^weather (.+)/,
		reply: function(match, data) {
			request(encodeURI("http://autocomplete.wunderground.com/aq?query=" + match[1]), function(error, response, body) {
				if (!error && response.statusCode == 200) {
					var cities = JSON.parse(body).RESULTS;
					if (cities.length)  {
						request(encodeURI("http://api.wunderground.com/api/" + wunderToken + "/forecast10day" + cities[0].l + ".json"),
							function(error, response, body) {
								if (!error && response.statusCode == 200) {
									var forecast = JSON.parse(body).forecast;
									if (forecast) {
										var forecastDays = forecast.simpleforecast.forecastday;
										var result = "Weather forecast for " + cities[0].name + ":";
										for (var i = 0; i < 7; i++) {
											var day = forecastDays[i];
											result += "\n\t*  " + day.date.weekday + ":\t" + pad(20, day.conditions).substr(0, 20) + "| " +
													  day.high.celsius + "/" + day.low.celsius + "°C\t| " +
													  day.avewind.kph + "kph " + day.avewind.dir;
										}
										post(result, data);
									}
									else post("No weather information found", data);
								}
								else console.log("Error requesting weather information: " + (error || response) + "\n");
							});
					}
					else post("No city found matching search", data);
				}
				else console.log("Error requesting weather information: " + (error || response) + "\n");
			});
		}
	},
	{
		description: "about:\t\t\t\tdeveloper and source info",
		pattern: /^about/,
		reply: function() {
			return "CheezeBot by Adam-G\nSource: git.io/1roJvQ\nSuggestions or contributions welcome.";
		}
	},
];

// utility functions
function pad(len, str) {
	while (str.length < len) str += " ";
	return str;
}
<|endoftext|>


<commit_before>$(window).load(function(){

	$(".search-wrap .dropdown-menu li a").click(function(){
	  	$(".search-wrap .dropdown-toggle").html($(this).text() + ' ');
	});

	$('.btn-launch').hover(function(){
		$(this).parent().find('.image-container .after').show();
	},function(){
		$(this).parent().find('.image-container .after').hide();
	})

	$('.rating:not(.half) .icon').click(function(){
        var elem = $(this);

        elem.siblings('.icon').removeClass('active');
        elem.addClass('active');

        var rating = ($(this).closest('.rating').find('.icon').length - $(this).index());
        elem.trigger('clicked.rate', [rating]);
    });

    $('.rating:not(.half) .icon').on('clicked.rate', function(e, data){
        console.log(data);
    });

    $('.rating.half .icon').children().click(function(){
        var elem = $(this);

        elem.closest('.icon').siblings().removeClass('active');
        elem.siblings().removeClass('active');
        elem.closest('.icon').addClass('active');
        elem.addClass('active');

        var rating = function(){
            if(elem.index() > 0){
                return (elem.closest('.rating').find('.icon').length - elem.closest('.icon').index() - 1) + '.5';
            }
            else{
                return (elem.closest('.rating').find('.icon').length - elem.closest('.icon').index()) + '.0';
            }
        };

        elem.trigger('clicked.rate.half', [rating()]);
    });

    $('.rating.half .icon').children().on('clicked.rate.half', function(e, data){
        console.log(data);
    });

    /**
     * Affix spacer when media left is affixed
     */
    $('.sidebar-wrapper').on('affix.bs.affix',function(){
        $('.media').prepend('

')
    }).on('affixed-top.bs.affix',function(){
        $('.affix-spacer').remove();
    })

});
<commit_msg>Space hidden on small screens<commit_after>$(window).load(function(){

	$(".search-wrap .dropdown-menu li a").click(function(){
	  	$(".search-wrap .dropdown-toggle").html($(this).text() + ' ');
	});

	$('.btn-launch').hover(function(){
		$(this).parent().find('.image-container .after').show();
	},function(){
		$(this).parent().find('.image-container .after').hide();
	})

	$('.rating:not(.half) .icon').click(function(){
        var elem = $(this);

        elem.siblings('.icon').removeClass('active');
        elem.addClass('active');

        var rating = ($(this).closest('.rating').find('.icon').length - $(this).index());
        elem.trigger('clicked.rate', [rating]);
    });

    $('.rating:not(.half) .icon').on('clicked.rate', function(e, data){
        console.log(data);
    });

    $('.rating.half .icon').children().click(function(){
        var elem = $(this);

        elem.closest('.icon').siblings().removeClass('active');
        elem.siblings().removeClass('active');
        elem.closest('.icon').addClass('active');
        elem.addClass('active');

        var rating = function(){
            if(elem.index() > 0){
                return (elem.closest('.rating').find('.icon').length - elem.closest('.icon').index() - 1) + '.5';
            }
            else{
                return (elem.closest('.rating').find('.icon').length - elem.closest('.icon').index()) + '.0';
            }
        };

        elem.trigger('clicked.rate.half', [rating()]);
    });

    $('.rating.half .icon').children().on('clicked.rate.half', function(e, data){
        console.log(data);
    });

    /**
     * Affix spacer when media left is affixed
     */
    $('.sidebar-wrapper').on('affix.bs.affix',function(){
        $('.media').prepend('

')
    }).on('affixed-top.bs.affix',function(){
        $('.affix-spacer').remove();
    })

});
<|endoftext|>


<commit_before>var util = require('util');
var Socket = require('net').Socket;

var bindings = require(__dirname + '/../build/Debug/unix_stream.node');

var SOCK_STREAM  = bindings.SOCK_STREAM;
var AF_UNIX     = bindings.AF_UNIX;

var bind = bindings.bind;
var socket = bindings.socket;

function errnoException(errorno, syscall) {

    var e = new Error(syscall + ' ' + errorno);
    e.errno = e.code = errorno;
    e.syscall = syscall;
    return e;
}

exports.createSocket = function(local_path) {

    var fd;
    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) === -1)
        throw errnoException(errno, 'socket');

    var s = new Socket(fd);
    if (local_path) {
        if (bind(fd, local_path) == -1) {
            s.emit('error', errnoException(errno, 'bind'));
        }

        s.local_path = local_path;
    }

    return s;
};
<commit_msg>Emit bind error on next tick<commit_after>var util = require('util');
var Socket = require('net').Socket;

var bindings = require(__dirname + '/../build/Debug/unix_stream.node');

var SOCK_STREAM  = bindings.SOCK_STREAM;
var AF_UNIX     = bindings.AF_UNIX;

var bind = bindings.bind;
var socket = bindings.socket;

function errnoException(errorno, syscall) {

    var e = new Error(syscall + ' ' + errorno);
    e.errno = e.code = errorno;
    e.syscall = syscall;
    return e;
}

exports.createSocket = function(local_path) {

    var fd;
    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) === -1)
        throw errnoException(errno, 'socket');

    var s = new Socket(fd);
    if (local_path) {
        if (bind(fd, local_path) == -1) {
            process.nextTick(function() {
                s.emit('error', errnoException(errno, 'bind'));
            });
        }

        s.local_path = local_path;
    }

    return s;
};
<|endoftext|>


<commit_before>
var masterNotification;
var popupFileProgress = null;

function createBaseWindow(messageType)
{
    var backgroundDiv = createElement("div");
    backgroundDiv.id = "popupBackgroundDiv";
    $(backgroundDiv).addClass("PopupWindow");
    masterNotification.appendChild(backgroundDiv);

    var titleDiv = createElement("div");
    titleDiv.id = "popupTitleDiv";
    $(titleDiv).addClass("PopupWindow");
    backgroundDiv.appendChild(titleDiv);

    var titleText = createElement("p");
    titleText.id = "popupTitleText";
    $(titleText).addClass("PopupWindow");
    titleDiv.appendChild(titleText);
    switch (messageType)
    {
        case "Error":
            titleDiv.style.backgroundColor = "#D64531";
            backgroundDiv.style.backgroundColor = "#E94B35";
            titleText.style.color = "#E1EDD8";
            titleText.innerHTML = "Error";
            break;
        case "Info":
            titleDiv.style.backgroundColor = "#336B87";
            backgroundDiv.style.backgroundColor = "#90AFC5";
            titleText.style.color = "#E1EDD8";
            titleText.innerHTML = "Info";
            break;
        case "Progress":
            titleDiv.style.backgroundColor = "#6EB5C0";
            backgroundDiv.style.backgroundColor = "#E2E8E4";
            titleText.style.color = "#E1EDD8";
            titleText.innerHTML = "Foto Upload";
            break;
    }

    var innerDiv = createElement("div");
    innerDiv.id = "popupInnerDiv";
    $(innerDiv).addClass("PopupWindow");
    backgroundDiv.appendChild(innerDiv);
    return innerDiv;
}

function createPopupError(message)
{
    var innerDiv = createBaseWindow("Error");
    var fullMessage = message;
    var regex1 = /(?=)(.*?)(?=<\/b>)/g;
    var str1 = message.match(regex1);

    for (var i = 0; i < str1.length; i++)
    {
        fullMessage = fullMessage.replace(str1[i].toString(), "");
    }

    var strWhereArray = str1[1].split('\\');

    var whereError = createElement("p");
    $(whereError).addClass("PopupWindow");
    whereError.innerHTML = "Location:
" + strWhereArray[strWhereArray.length - 2] + "/" + strWhereArray[strWhereArray.length - 1];
    innerDiv.appendChild(whereError);

    var lineError = createElement("p");
    $(lineError).addClass("PopupWindow");
    lineError.id = "lineError";
    lineError.innerHTML = "line: " + str1[2];
    innerDiv.appendChild(lineError);

    fullMessage = fullMessage.replace(new RegExp("
", "g"), "");
    fullMessage = fullMessage.replace(new RegExp("", "g"), "");

    var regex2 = /(:.*\.)/g;
    str2 = fullMessage.match(regex2);
    fullMessage = str2[0].replace(": ", "");

    var whatError = createElement("p");
    $(whatError).addClass("PopupWindow");
    whatError.innerHTML = "Error:
" + fullMessage;
    innerDiv.appendChild(whatError);

}

function createPopupFilesWarning(varArray)
{
    var innerDiv = createBaseWindow("Info");

    var whatInfo = createElement("p");
    $(whatInfo).addClass("PopupWindow");
    whatInfo.innerHTML = "Foto's die te groot zijn:";
    innerDiv.appendChild(whatInfo);

    var extraInfo = createElement("p");
    $(extraInfo).addClass("PopupWindow");
    extraInfo.id = "popupExtraInfo";
    extraInfo.innerHTML = "Maximum: " + ((varArray[0] / 1024) / 1024).toFixed(2) + " mb";
    innerDiv.appendChild(extraInfo);

    var str1 = "
";
    for (var i = 1; i < varArray.length; i++)
    {
        str1 = str1 + "
" + varArray[i] + "
";
    }
    str1 += "
";

    var whatText = createElement("p");
    $(whatText).addClass("PopupWindow");
    whatText.innerHTML = str1;
    innerDiv.appendChild(whatText);
}

function createPopupFilesProgress()
{
    var innerDiv = createBaseWindow("Progress");
    var listItem = createElement("div");
    $(listItem).addClass("PopupWindow");
    innerDiv.appendChild(listItem);
    popupFileProgress = listItem;
}

function popupAddProgressBar(xmlHttp)
{
    var progressBarBackground = createElement("div");
    progressBarBackground.id = "progressBarBackground";
    popupFileProgress.appendChild(progressBarBackground);

    var progressBar = createElement("div");
    progressBar.id = "progressBar";
    progressBar.style.width = "10%";
    progressBarBackground.appendChild(progressBar);

    var uploadText = createElement("p");
    uploadText.id = "uploadText";
    progressBarBackground.appendChild(uploadText);

    xmlHttp.upload.addEventListener('progress', function (e)
    {
        progressBar.style.width = Math.ceil(e.loaded / e.total) * 100 + '%';
        uploadText.innerHTML = Math.ceil(e.loaded / e.total) * 100 + '%';

    }, false);
}

$(document).ready(function ()
{
    masterNotification = createElement("div");
    masterNotification.id = "masterNotification";
    document.body.appendChild(masterNotification);

    $(document).on('click', '.PopupWindow', function (event)
    {
        $("#popupBackgroundDiv").last().animate({marginTop: "-260px"}, function ()
        {
            $("#popupBackgroundDiv").last().remove();
        });
        event.stopPropagation();
    });
});
<commit_msg>van links naar rechts<commit_after>
var masterNotification;
var popupFileProgress = null;

function createBaseWindow(messageType)
{
    var backgroundDiv = createElement("div");
    backgroundDiv.id = "popupBackgroundDiv";
    $(backgroundDiv).addClass("PopupWindow");
    masterNotification.appendChild(backgroundDiv);

    var titleDiv = createElement("div");
    titleDiv.id = "popupTitleDiv";
    $(titleDiv).addClass("PopupWindow");
    backgroundDiv.appendChild(titleDiv);

    var titleText = createElement("p");
    titleText.id = "popupTitleText";
    $(titleText).addClass("PopupWindow");
    titleDiv.appendChild(titleText);
    switch (messageType)
    {
        case "Error":
            titleDiv.style.backgroundColor = "#D64531";
            backgroundDiv.style.backgroundColor = "#E94B35";
            titleText.style.color = "#E1EDD8";
            titleText.innerHTML = "Error";
            break;
        case "Info":
            titleDiv.style.backgroundColor = "#336B87";
            backgroundDiv.style.backgroundColor = "#90AFC5";
            titleText.style.color = "#E1EDD8";
            titleText.innerHTML = "Info";
            break;
        case "Progress":
            titleDiv.style.backgroundColor = "#6EB5C0";
            backgroundDiv.style.backgroundColor = "#E2E8E4";
            titleText.style.color = "#E1EDD8";
            titleText.innerHTML = "Foto Upload";
            break;
    }

    var innerDiv = createElement("div");
    innerDiv.id = "popupInnerDiv";
    $(innerDiv).addClass("PopupWindow");
    backgroundDiv.appendChild(innerDiv);
    return innerDiv;
}

function createPopupError(message)
{
    var innerDiv = createBaseWindow("Error");
    var fullMessage = message;
    var regex1 = /(?=)(.*?)(?=<\/b>)/g;
    var str1 = message.match(regex1);

    for (var i = 0; i < str1.length; i++)
    {
        fullMessage = fullMessage.replace(str1[i].toString(), "");
    }

    var strWhereArray = str1[1].split('\\');

    var whereError = createElement("p");
    $(whereError).addClass("PopupWindow");
    whereError.innerHTML = "Location:
" + strWhereArray[strWhereArray.length - 2] + "/" + strWhereArray[strWhereArray.length - 1];
    innerDiv.appendChild(whereError);

    var lineError = createElement("p");
    $(lineError).addClass("PopupWindow");
    lineError.id = "lineError";
    lineError.innerHTML = "line: " + str1[2];
    innerDiv.appendChild(lineError);

    fullMessage = fullMessage.replace(new RegExp("
", "g"), "");
    fullMessage = fullMessage.replace(new RegExp("", "g"), "");

    var regex2 = /(:.*\.)/g;
    str2 = fullMessage.match(regex2);
    fullMessage = str2[0].replace(": ", "");

    var whatError = createElement("p");
    $(whatError).addClass("PopupWindow");
    whatError.innerHTML = "Error:
" + fullMessage;
    innerDiv.appendChild(whatError);

}

function createPopupFilesWarning(varArray)
{
    var innerDiv = createBaseWindow("Info");

    var whatInfo = createElement("p");
    $(whatInfo).addClass("PopupWindow");
    whatInfo.innerHTML = "Foto's die te groot zijn:";
    innerDiv.appendChild(whatInfo);

    var extraInfo = createElement("p");
    $(extraInfo).addClass("PopupWindow");
    extraInfo.id = "popupExtraInfo";
    extraInfo.innerHTML = "Maximum: " + ((varArray[0] / 1024) / 1024).toFixed(2) + " mb";
    innerDiv.appendChild(extraInfo);

    var str1 = "
";
    for (var i = 1; i < varArray.length; i++)
    {
        str1 = str1 + "
" + varArray[i] + "
";
    }
    str1 += "
";

    var whatText = createElement("p");
    $(whatText).addClass("PopupWindow");
    whatText.innerHTML = str1;
    innerDiv.appendChild(whatText);
}

function createPopupFilesProgress()
{
    var innerDiv = createBaseWindow("Progress");
    var listItem = createElement("div");
    $(listItem).addClass("PopupWindow");
    innerDiv.appendChild(listItem);
    popupFileProgress = listItem;
}

function popupAddProgressBar(xmlHttp)
{
    var progressBarBackground = createElement("div");
    progressBarBackground.id = "progressBarBackground";
    $(progressBarBackground).addClass("PopupWindow");
    popupFileProgress.appendChild(progressBarBackground);

    var progressBar = createElement("div");
    progressBar.id = "progressBar";
    $(progressBar).addClass("PopupWindow");
    progressBar.style.width = "10%";
    progressBarBackground.appendChild(progressBar);

    var uploadText = createElement("p");
    uploadText.id = "uploadText";
    $(uploadText).addClass("PopupWindow");
    progressBarBackground.appendChild(uploadText);

    xmlHttp.upload.addEventListener('progress', function (e)
    {
        progressBar.style.width = Math.ceil(e.loaded / e.total) * 100 + '%';
        uploadText.innerHTML = Math.ceil(e.loaded / e.total) * 100 + '%';

    }, false);
}

$(document).ready(function ()
{
    masterNotification = createElement("div");
    masterNotification.id = "masterNotification";
    document.body.appendChild(masterNotification);

    document.addEventListener('contextmenu', function (e)
    {
        if ($(e.target).hasClass("PopupWindow"))
        {
            $("#popupBackgroundDiv").last().animate({marginTop: "-260px"}, function ()
            {
                $("#popupBackgroundDiv").last().remove();
            });
            e.preventDefault();
        }
    }, false);
});
<|endoftext|>


<commit_before>define([
	'goo/sound/AudioContext',
	'goo/math/MathUtils',
	'goo/util/rsvp'
], function (
	AudioContext,
	MathUtils,
	RSVP
) {
	'use strict';

	/**
	 * A representation of a sound in the engine
	 */
	function Sound() {
		/** @type {string}
		 */
		this.id = null;
		/** @type {string}
		 */
		this.name = null;
		this._loop = false;
		this._rate = 1.0;
		this._offset = 0;
		this._duration = null;
		this._volume = 1.0;

		// Nodes
		this._buffer = null;
		this._stream = null;
		this._streamSource = null;
		this._currentSource = null;
		this._outNode = AudioContext.getContext().createGain();
		this.connectTo();

		// Playback memory
		this._playStart = 0;
		this._pausePos = 0;
		//this._endTimer = null;
		this._endPromise = null;

		this._paused = false;

		// #ifdef DEBUG
		Object.seal(this);
		// #endif
	}

	/**
	 * Plays the sound if it's not playing
	 * @param {number} when Time in seconds according to [AudioContext.currentTime]{@link https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/currentTime} when sound should start to play.
	 * @returns {RSVP.Promise} Resolves when sound has played through or when it's stopped.
	 * Looping sounds will never resolve
	 */
	Sound.prototype.play = function (when) {
		when = when || 0;
		if (this._currentSource) {
			return this._endPromise;
		}
		this._endPromise = new RSVP.Promise(); //! AT: this needs refactoring
		if (!this._buffer || this._stream) {
			return this._endPromise;
		}

		var currentSource = this._currentSource = AudioContext.getContext().createBufferSource();

		this._paused = false;
		this._currentSource.onended = function () {
			if (this._currentSource === currentSource && !this._paused) {
				this.stop();
			}
		}.bind(this);

		this._currentSource.playbackRate.value = this._rate;
		this._currentSource.connect(this._outNode);
		this._currentSource.buffer = this._buffer;
		this._currentSource.loop = this._loop;
		if (this._loop) {
			this._currentSource.loopStart = this._offset;
			this._currentSource.loopEnd = this._duration + this._offset;
		}

		this._playStart = AudioContext.getContext().currentTime - this._pausePos;
		var duration = this._duration - this._pausePos;

		if (this._loop) {
			this._currentSource.start(when, this._pausePos + this._offset);
		} else {
			this._currentSource.start(when, this._pausePos + this._offset, duration);
		}

		return this._endPromise;
	};

	/**
	 * Pauses the sound if it's playing
	 */
	Sound.prototype.pause = function () {

		if (!this._currentSource) {
			return;
		}
		this._paused = true;

		this._pausePos = (AudioContext.getContext().currentTime - this._playStart) % this._duration;
		this._pausePos /= this._rate;
		this._stop();
	};

	/**
	 * Stops the sound if it's playing
	 */
	Sound.prototype.stop = function () {
		this._paused = false;
		this._pausePos = 0;
		if (this._endPromise) {
			this._endPromise.resolve();
		}
		if (this._currentSource) {
			this._stop();
		}
	};

	Sound.prototype.fadeIn = function (time) {
		this.stop();
		var volume = this._volume;
		this._outNode.gain.value = 0;
		var p = this.fade(volume, time);
		this.play();
		return p;
	};

	Sound.prototype.fadeOut = function (time) {
		return this.fade(0, time);
	};

	Sound.prototype.fade = function (volume, time) {
		this._outNode.gain.setValueAtTime(this._outNode.gain.value, AudioContext.getContext().currentTime);
		this._outNode.gain.linearRampToValueAtTime(volume, AudioContext.getContext().currentTime + time);
		var p = new RSVP.Promise();
		setTimeout(function () {
			p.resolve();
		}, time * 1000);
		return p;
	};

	Sound.prototype.isPlaying = function () {
		return !!this._currentSource;
	};

	/**
	 * Does the actual stopping of the sound
	 * @private
	 */
	Sound.prototype._stop = function () {
		this._currentSource.stop(0);
		this._currentSource = null;
	};

	/**
	 * Updates the sound according to config
	 * @param {Object} [config]
	 * @param {boolean} [config.loop]
	 * @param {number} [config.volume]
	 * @param {number} [config.name] The sound name
	 * @param {number} [config.start] Start offset in seconds.
	 * Will be clamped to be in actual soundclip duration
	 * @param {number} [config.duration] Duration of the sound.
	 * Will be clamped to be in actual soundclip duration
	 * @param {number} [config.timeScale] Playback rate of the sound
	 */
	Sound.prototype.update = function (config) {
		config = config || {};
		if (config.id !== undefined) {
			this.id = config.id;
		}
		if (config.name !== undefined) {
			this.name = config.name;
		}
		if (config.loop !== undefined) {
			this._loop = !!config.loop;
			if (this._currentSource) {
				this._currentSource.loop = this._loop;
			}
		}
		if (config.volume !== undefined) {
			this._volume = MathUtils.clamp(config.volume, 0, 1);
			this._outNode.gain.value = this._volume;
		}
		if (config.offset !== undefined) {
			this._offset = config.offset;
		}
		if (config.duration !== undefined) {
			this._duration = config.duration;
		}
		if (config.timeScale !== undefined) {
			this._rate = config.timeScale;
			//! AT: should have the same name if they are the same thing
			// problem is that there are plenty of projects out there that have timeScale instead of rate
			// timeScale was considered because it's the same as for animations
			// rate would have been preferred to timeScale as it's the term used by WebAudio
			if (this._currentSource) {
				this._currentSource.playbackRate.value = config.timeScale;
			}
		}
		if (this._buffer) {
			this._clampInterval();
		}
	};

	/**
	 * Clamps the start offset and duration to be in sound range
	 * @private
	 */
	Sound.prototype._clampInterval = function () {
		this._offset = Math.min(this._offset, this._buffer.duration);
		if (this._duration !== null) {
			this._duration = Math.min(this._buffer.duration - this._offset, this._duration);
		} else {
			this._duration = this._buffer.duration - this._offset;
		}
		this._pausePos = MathUtils.clamp(this._pausePos, 0, this._duration);
	};

	/**
	 * Connect output of sound to audionodes
	 * @param {(Array<AudioNode> | AudioNode)} nodes
	 */
	Sound.prototype.connectTo = function (nodes) {
		if (!nodes) {
			return;
		}
		if (!(nodes instanceof Array)) {
			nodes = [nodes];
		}
		for (var i = 0; i < nodes.length; i++) {
			this._outNode.connect(nodes[i]);
		}
	};

	/**
	 * Disconnect output of sound from audionodes
	 * @param {AudioNode[]|AudioNode} nodes
	 */
	Sound.prototype.disconnectFrom = function (nodes) {
		if (!nodes) {
			return;
		}
		if (!(nodes instanceof Array)) {
			nodes = [nodes];
		}
		for (var i = 0; i < nodes.length; i++) {
			this._outNode.disconnect(nodes[i]);
		}
	};

	/**
	 * Sets the audio buffer which will be the sound source
	 * @param {AudioBuffer} buffer
	 */
	Sound.prototype.setAudioBuffer = function (buffer) {
		this.setAudioStream(null);
		this._buffer = buffer;
		this._clampInterval();
	};

	Sound.prototype.setAudioStream = function (stream) {
		if (!stream) {
			if (this._streamSource) {
				this._streamSource.disconnect();
				this._streamSource = null;
			}
			return;
		}
		this.stop();
		this._stream = stream;
		this._streamSource = AudioContext.getContext().createMediaStreamSource(stream);
		this._streamSource.connect(this._outNode);
	};

	return Sound;
});<commit_msg>Added timesynced stopping of sounds<commit_after>define([
	'goo/sound/AudioContext',
	'goo/math/MathUtils',
	'goo/util/rsvp'
], function (
	AudioContext,
	MathUtils,
	RSVP
) {
	'use strict';

	/**
	 * A representation of a sound in the engine
	 */
	function Sound() {
		/** @type {string}
		 */
		this.id = null;
		/** @type {string}
		 */
		this.name = null;
		this._loop = false;
		this._rate = 1.0;
		this._offset = 0;
		this._duration = null;
		this._volume = 1.0;

		// Nodes
		this._buffer = null;
		this._stream = null;
		this._streamSource = null;
		this._currentSource = null;
		this._outNode = AudioContext.getContext().createGain();
		this.connectTo();

		// Playback memory
		this._playStart = 0;
		this._pausePos = 0;
		//this._endTimer = null;
		this._endPromise = null;

		this._paused = false;

		// #ifdef DEBUG
		Object.seal(this);
		// #endif
	}

	/**
	 * Plays the sound if it's not playing
	 * @param {number} when Time in seconds according to [AudioContext.currentTime]{@link https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/currentTime} when sound should start to play.
	 * @returns {RSVP.Promise} Resolves when sound has played through or when it's stopped.
	 * Looping sounds will never resolve
	 */
	Sound.prototype.play = function (when) {
		when = when || 0;
		if (this._currentSource) {
			return this._endPromise;
		}
		this._endPromise = new RSVP.Promise(); //! AT: this needs refactoring
		if (!this._buffer || this._stream) {
			return this._endPromise;
		}

		var currentSource = this._currentSource = AudioContext.getContext().createBufferSource();

		this._paused = false;
		this._currentSource.onended = function () {
			if (this._currentSource === currentSource && !this._paused) {
				this.stop();
			}
		}.bind(this);

		this._currentSource.playbackRate.value = this._rate;
		this._currentSource.connect(this._outNode);
		this._currentSource.buffer = this._buffer;
		this._currentSource.loop = this._loop;
		if (this._loop) {
			this._currentSource.loopStart = this._offset;
			this._currentSource.loopEnd = this._duration + this._offset;
		}

		this._playStart = AudioContext.getContext().currentTime - this._pausePos;
		var duration = this._duration - this._pausePos;

		if (this._loop) {
			this._currentSource.start(when, this._pausePos + this._offset);
		} else {
			this._currentSource.start(when, this._pausePos + this._offset, duration);
		}

		return this._endPromise;
	};

	/**
	 * Pauses the sound if it's playing
	 */
	Sound.prototype.pause = function () {

		if (!this._currentSource) {
			return;
		}
		this._paused = true;

		this._pausePos = (AudioContext.getContext().currentTime - this._playStart) % this._duration;
		this._pausePos /= this._rate;
		this._stop();
	};

	/**
	 * Stops the sound if it's playing
	 * @param {number} when Time in seconds according to [AudioContext.currentTime]{@link https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/currentTime} when sound should stop.
	 */
	Sound.prototype.stop = function (when) {
		this._paused = false;
		this._pausePos = 0;
		if (this._endPromise) {
			this._endPromise.resolve();
		}
		if (this._currentSource) {
			this._stop(when);
		}
	};

	Sound.prototype.fadeIn = function (time) {
		this.stop();
		var volume = this._volume;
		this._outNode.gain.value = 0;
		var p = this.fade(volume, time);
		this.play();
		return p;
	};

	Sound.prototype.fadeOut = function (time) {
		return this.fade(0, time);
	};

	Sound.prototype.fade = function (volume, time) {
		this._outNode.gain.setValueAtTime(this._outNode.gain.value, AudioContext.getContext().currentTime);
		this._outNode.gain.linearRampToValueAtTime(volume, AudioContext.getContext().currentTime + time);
		var p = new RSVP.Promise();
		setTimeout(function () {
			p.resolve();
		}, time * 1000);
		return p;
	};

	Sound.prototype.isPlaying = function () {
		return !!this._currentSource;
	};

	/**
	 * Does the actual stopping of the sound
	 * @param {number} when Time in seconds according to [AudioContext.currentTime]{@link https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/currentTime} when sound should stop.
	 * @private
	 */
	Sound.prototype._stop = function (when) {
		when = when || 0;
		this._currentSource.stop(when);
		this._currentSource = null;
	};

	/**
	 * Updates the sound according to config
	 * @param {Object} [config]
	 * @param {boolean} [config.loop]
	 * @param {number} [config.volume]
	 * @param {number} [config.name] The sound name
	 * @param {number} [config.start] Start offset in seconds.
	 * Will be clamped to be in actual soundclip duration
	 * @param {number} [config.duration] Duration of the sound.
	 * Will be clamped to be in actual soundclip duration
	 * @param {number} [config.timeScale] Playback rate of the sound
	 */
	Sound.prototype.update = function (config) {
		config = config || {};
		if (config.id !== undefined) {
			this.id = config.id;
		}
		if (config.name !== undefined) {
			this.name = config.name;
		}
		if (config.loop !== undefined) {
			this._loop = !!config.loop;
			if (this._currentSource) {
				this._currentSource.loop = this._loop;
			}
		}
		if (config.volume !== undefined) {
			this._volume = MathUtils.clamp(config.volume, 0, 1);
			this._outNode.gain.value = this._volume;
		}
		if (config.offset !== undefined) {
			this._offset = config.offset;
		}
		if (config.duration !== undefined) {
			this._duration = config.duration;
		}
		if (config.timeScale !== undefined) {
			this._rate = config.timeScale;
			//! AT: should have the same name if they are the same thing
			// problem is that there are plenty of projects out there that have timeScale instead of rate
			// timeScale was considered because it's the same as for animations
			// rate would have been preferred to timeScale as it's the term used by WebAudio
			if (this._currentSource) {
				this._currentSource.playbackRate.value = config.timeScale;
			}
		}
		if (this._buffer) {
			this._clampInterval();
		}
	};

	/**
	 * Clamps the start offset and duration to be in sound range
	 * @private
	 */
	Sound.prototype._clampInterval = function () {
		this._offset = Math.min(this._offset, this._buffer.duration);
		if (this._duration !== null) {
			this._duration = Math.min(this._buffer.duration - this._offset, this._duration);
		} else {
			this._duration = this._buffer.duration - this._offset;
		}
		this._pausePos = MathUtils.clamp(this._pausePos, 0, this._duration);
	};

	/**
	 * Connect output of sound to audionodes
	 * @param {(Array<AudioNode> | AudioNode)} nodes
	 */
	Sound.prototype.connectTo = function (nodes) {
		if (!nodes) {
			return;
		}
		if (!(nodes instanceof Array)) {
			nodes = [nodes];
		}
		for (var i = 0; i < nodes.length; i++) {
			this._outNode.connect(nodes[i]);
		}
	};

	/**
	 * Disconnect output of sound from audionodes
	 * @param {AudioNode[]|AudioNode} nodes
	 */
	Sound.prototype.disconnectFrom = function (nodes) {
		if (!nodes) {
			return;
		}
		if (!(nodes instanceof Array)) {
			nodes = [nodes];
		}
		for (var i = 0; i < nodes.length; i++) {
			this._outNode.disconnect(nodes[i]);
		}
	};

	/**
	 * Sets the audio buffer which will be the sound source
	 * @param {AudioBuffer} buffer
	 */
	Sound.prototype.setAudioBuffer = function (buffer) {
		this.setAudioStream(null);
		this._buffer = buffer;
		this._clampInterval();
	};

	Sound.prototype.setAudioStream = function (stream) {
		if (!stream) {
			if (this._streamSource) {
				this._streamSource.disconnect();
				this._streamSource = null;
			}
			return;
		}
		this.stop();
		this._stream = stream;
		this._streamSource = AudioContext.getContext().createMediaStreamSource(stream);
		this._streamSource.connect(this._outNode);
	};

	return Sound;
});<|endoftext|>


<commit_before>import React from 'react';
import { Alert } from 'react-native';
import { connect } from 'react-redux';
import { Actions } from 'react-native-router-flux';
import Toast from 'react-native-simple-toast';

import { updateMaster } from '../../actions/shuttle';
import CardComponent from '../card/CardComponent';
import ShuttleCard from './ShuttleCard';

import logger from '../../util/logger';

class ShuttleCardContainer extends CardComponent {
	componentDidMount() {
		logger.ga('Card Mounted: Shuttle');
		this.props.updateMaster();
	}

	render() {
		const { stopsData, savedStops, removeStop, closestStop, updateScroll, lastScroll } = this.props;

		const displayStops = savedStops.slice();
		if (closestStop) {
			displayStops.splice(closestStop.savedIndex, 0, closestStop);
		}

		return (<ShuttleCard
			savedStops={displayStops}
			stopsData={stopsData}
			gotoSavedList={this.gotoSavedList}
			gotoRoutesList={this.gotoRoutesList}
			removeStop={removeStop}
			updateScroll={updateScroll}
			lastScroll={lastScroll}
		/>);
	}

	gotoRoutesList = () => {
		if (this.props.savedStops.length < 10) {
			const { shuttle_routes } = this.props;
			// Sort routes by alphabet
			const alphaRoutes = [];
			Object.keys(shuttle_routes)
				.sort((a, b) => shuttle_routes[a].name.trim().localeCompare(shuttle_routes[b].name.trim()))
					.forEach((key) => {
						alphaRoutes.push(shuttle_routes[key]);
					});
			Actions.ShuttleRoutesListView({ shuttle_routes: alphaRoutes, gotoStopsList: this.gotoStopsList });
		} else {
			Alert.alert(
				'Add Stop',
				'Unable to add more than 10 stops, please remove a stop before trying.',
				[
					{ text: 'Manage Stops', onPress: () => this.gotoSavedList() },
					{ text: 'Cancel' }
				]
			);
		}
	}

	isSaved = (stop) => {
		const { savedStops } = this.props;

		for (let i = 0; i < savedStops.length; ++i) {
			if (savedStops[i].id === stop.id) {
				return true;
			}
		}
		return false;
	}

	gotoStopsList = (stops) => {
		// Sort stops by alphabet
		const alphaStops = [];
		Object.keys(stops)
			.sort((a, b) => stops[a].name.trim().localeCompare(stops[b].name.trim()))
				.forEach((key) => {
					const stop = Object.assign({}, stops[key]);

					if (this.isSaved(stop)) {
						stop.saved = true;
					}
					alphaStops.push(stop);
				});

		Actions.ShuttleStopsListView({ shuttle_stops: alphaStops, addStop: this.addStop });
	}

	gotoSavedList = () => {
		Actions.ShuttleSavedListView();
	}

	addStop = (stopID, stopName) => {
		logger.ga('Shuttle: Added stop "' + stopName + '"');
		Toast.showWithGravity('Stop added.', Toast.SHORT, Toast.CENTER);
		this.props.addStop(stopID); // dispatch saga
		Actions.popTo('Home'); // pop back to home
	}
}

function mapStateToProps(state, props) {
	return {
		closestStop: state.shuttle.closestStop,
		stopsData: state.shuttle.stops,
		shuttle_routes: state.shuttle.routes,
		shuttle_stops: state.shuttle.stops,
		savedStops: state.shuttle.savedStops,
		lastScroll: state.shuttle.lastScroll
	};
}

function mapDispatchtoProps(dispatch) {
	return {
		updateMaster: () => {
			dispatch(updateMaster());
		},
		addStop: (stopID) => {
			dispatch({ type: 'ADD_STOP', stopID });
		},
		updateScroll: (scrollX) => {
			dispatch({ type: 'UPDATE_SCROLL', scrollX });
		}
	};
}

const ActualShuttleCard = connect(
	mapStateToProps,
	mapDispatchtoProps
)(ShuttleCardContainer);

export default ActualShuttleCard;
<commit_msg>Update too many stops verbiage<commit_after>import React from 'react';
import { Alert } from 'react-native';
import { connect } from 'react-redux';
import { Actions } from 'react-native-router-flux';
import Toast from 'react-native-simple-toast';

import { updateMaster } from '../../actions/shuttle';
import CardComponent from '../card/CardComponent';
import ShuttleCard from './ShuttleCard';

import logger from '../../util/logger';

class ShuttleCardContainer extends CardComponent {
	componentDidMount() {
		logger.ga('Card Mounted: Shuttle');
		this.props.updateMaster();
	}

	render() {
		const { stopsData, savedStops, removeStop, closestStop, updateScroll, lastScroll } = this.props;

		const displayStops = savedStops.slice();
		if (closestStop) {
			displayStops.splice(closestStop.savedIndex, 0, closestStop);
		}

		return (<ShuttleCard
			savedStops={displayStops}
			stopsData={stopsData}
			gotoSavedList={this.gotoSavedList}
			gotoRoutesList={this.gotoRoutesList}
			removeStop={removeStop}
			updateScroll={updateScroll}
			lastScroll={lastScroll}
		/>);
	}

	gotoRoutesList = () => {
		if (this.props.savedStops.length < 10) {
			const { shuttle_routes } = this.props;
			// Sort routes by alphabet
			const alphaRoutes = [];
			Object.keys(shuttle_routes)
				.sort((a, b) => shuttle_routes[a].name.trim().localeCompare(shuttle_routes[b].name.trim()))
					.forEach((key) => {
						alphaRoutes.push(shuttle_routes[key]);
					});
			Actions.ShuttleRoutesListView({ shuttle_routes: alphaRoutes, gotoStopsList: this.gotoStopsList });
		} else {
			Alert.alert(
				'Add a Stop',
				'Unable to add more than 10 stops, please remove a stop and try again.',
				[
					{ text: 'Manage Stops', onPress: () => this.gotoSavedList() },
					{ text: 'Cancel' }
				]
			);
		}
	}

	isSaved = (stop) => {
		const { savedStops } = this.props;

		for (let i = 0; i < savedStops.length; ++i) {
			if (savedStops[i].id === stop.id) {
				return true;
			}
		}
		return false;
	}

	gotoStopsList = (stops) => {
		// Sort stops by alphabet
		const alphaStops = [];
		Object.keys(stops)
			.sort((a, b) => stops[a].name.trim().localeCompare(stops[b].name.trim()))
				.forEach((key) => {
					const stop = Object.assign({}, stops[key]);

					if (this.isSaved(stop)) {
						stop.saved = true;
					}
					alphaStops.push(stop);
				});

		Actions.ShuttleStopsListView({ shuttle_stops: alphaStops, addStop: this.addStop });
	}

	gotoSavedList = () => {
		Actions.ShuttleSavedListView();
	}

	addStop = (stopID, stopName) => {
		logger.ga('Shuttle: Added stop "' + stopName + '"');
		Toast.showWithGravity('Stop added.', Toast.SHORT, Toast.CENTER);
		this.props.addStop(stopID); // dispatch saga
		Actions.popTo('Home'); // pop back to home
	}
}

function mapStateToProps(state, props) {
	return {
		closestStop: state.shuttle.closestStop,
		stopsData: state.shuttle.stops,
		shuttle_routes: state.shuttle.routes,
		shuttle_stops: state.shuttle.stops,
		savedStops: state.shuttle.savedStops,
		lastScroll: state.shuttle.lastScroll
	};
}

function mapDispatchtoProps(dispatch) {
	return {
		updateMaster: () => {
			dispatch(updateMaster());
		},
		addStop: (stopID) => {
			dispatch({ type: 'ADD_STOP', stopID });
		},
		updateScroll: (scrollX) => {
			dispatch({ type: 'UPDATE_SCROLL', scrollX });
		}
	};
}

const ActualShuttleCard = connect(
	mapStateToProps,
	mapDispatchtoProps
)(ShuttleCardContainer);

export default ActualShuttleCard;
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

'use strict';

module.exports = {
  opts: {
    readme: './README.md',
    package: './package.json',
    template: './node_modules/jsdoc-fresh',
    recurse: true,
    verbose: true,
    destination: './docs/'
  },
  plugins: [
    'plugins/markdown',
    'jsdoc-region-tag'
  ],
  source: {
    excludePattern: '(^|\\/|\\\\)[._]',
    include: [
      'build/src'
    ],
    includePattern: '\\.js$'
  },
  templates: {
    copyright: 'Copyright 2019 Google, LLC.',
    includeDate: false,
    sourceFiles: false,
    systemName: '@google-cloud/web-risk',
    theme: 'lumen',
    default: {
      "outputSourceFiles": false
    }
  },
  markdown: {
    idInHeadings: true
  }
};
<commit_msg>chore: update jsdoc with macro license (#121)<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ** This file is automatically generated by gapic-generator-typescript. **
// ** https://github.com/googleapis/gapic-generator-typescript **
// ** All changes to this file may be overwritten. **

'use strict';

module.exports = {
  opts: {
    readme: './README.md',
    package: './package.json',
    template: './node_modules/jsdoc-fresh',
    recurse: true,
    verbose: true,
    destination: './docs/'
  },
  plugins: [
    'plugins/markdown',
    'jsdoc-region-tag'
  ],
  source: {
    excludePattern: '(^|\\/|\\\\)[._]',
    include: [
      'build/src'
    ],
    includePattern: '\\.js$'
  },
  templates: {
    copyright: 'Copyright 2019 Google, LLC.',
    includeDate: false,
    sourceFiles: false,
    systemName: '@google-cloud/web-risk',
    theme: 'lumen',
    default: {
      "outputSourceFiles": false
    }
  },
  markdown: {
    idInHeadings: true
  }
};
<|endoftext|>


<commit_before>/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';
import { Fragment } from '@wordpress/element';
import { PanelBody, SelectControl, withFallbackStyles } from '@wordpress/components';
import { RichText, InspectorControls, FontSizePicker, withFontSizes } from '@wordpress/editor';
import { compose } from '@wordpress/compose';

const { getComputedStyle } = window;

/**
 * Internal dependencies
 */
import getTagName from './getTagName';
import { AMP_STORY_FONTS } from '../../helpers';

const applyFallbackStyles = withFallbackStyles( ( node, ownProps ) => {
	const { fontSize, customFontSize } = ownProps.attributes;
	const editableNode = node.querySelector( '[contenteditable="true"]' );
	//verify if editableNode is available, before using getComputedStyle.
	const computedStyles = editableNode ? getComputedStyle( editableNode ) : null;

	return {
		fallbackFontSize: fontSize || customFontSize || ! computedStyles ? undefined : parseInt( computedStyles.fontSize ) || undefined,
	};
} );

function TextBlock( {
	attributes,
	setAttributes,
	className,
	fallbackFontSize,
	fontSize,
	setFontSize,
} ) {
	const { content, type, ampFontFamily } = attributes;
	const tagName = getTagName( attributes );

	const fontSizeClass = fontSize.class || undefined;

	return (
		<Fragment>
			<InspectorControls>
				<PanelBody title={ __( 'Text Settings', 'amp' ) }>
					<SelectControl
						key={ 'font-family' }
						label={ __( 'Font family', 'amp' ) }
						value={ ampFontFamily }
						options={ AMP_STORY_FONTS }
						onChange={ function( value ) {
							setAttributes( { ampFontFamily: value } );
						} }
					/>
					<FontSizePicker
						fallbackFontSize={ fallbackFontSize }
						value={ fontSize.size }
						onChange={ setFontSize }
					/>
					<SelectControl
						label={ __( 'Select text type', 'amp' ) }
						value={ type }
						onChange={ ( selected ) => setAttributes( { type: selected } ) }
						options={ [
							{ value: 'auto', label: __( 'Automatic', 'amp' ) },
							{ value: 'p', label: __( 'Paragraph', 'amp' ) },
							{ value: 'h1', label: __( 'Heading 1', 'amp' ) },
							{ value: 'h2', label: __( 'Heading 2', 'amp' ) },
						] }
					/>
				</PanelBody>
			</InspectorControls>
			<RichText
				identifier="content"
				wrapperClassName="wp-block-amp-story-text"
				tagName={ tagName }
				value={ content }
				onChange={ ( value ) => setAttributes( { content: value } ) }
				style={ {
					fontSize: fontSize.size ? fontSize.size + 'px' : undefined,
				} }
				className={ `${ className } ${ fontSizeClass }` }
				placeholder={ __( 'Write text…', 'amp' ) }
			/>
		</Fragment>
	);
}

const TextEdit = compose( [
	withFontSizes( 'fontSize' ),
	applyFallbackStyles,
] )( TextBlock );

export default TextEdit;
<commit_msg>Remove usage of getComputedStyle<commit_after>/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';
import { Fragment } from '@wordpress/element';
import { PanelBody, SelectControl, withFallbackStyles } from '@wordpress/components';
import { RichText, InspectorControls, FontSizePicker, withFontSizes } from '@wordpress/editor';
import { compose } from '@wordpress/compose';

/**
 * Internal dependencies
 */
import getTagName from './getTagName';
import { AMP_STORY_FONTS } from '../../helpers';

const applyFallbackStyles = withFallbackStyles( ( node, ownProps ) => {
	const { fontSize, customFontSize } = ownProps.attributes;

	return {
		fallbackFontSize: fontSize || customFontSize || undefined,
	};
} );

function TextBlock( {
	attributes,
	setAttributes,
	className,
	fallbackFontSize,
	fontSize,
	setFontSize,
} ) {
	const { content, type, ampFontFamily } = attributes;
	const tagName = getTagName( attributes );

	const fontSizeClass = fontSize.class || undefined;

	return (
		<Fragment>
			<InspectorControls>
				<PanelBody title={ __( 'Text Settings', 'amp' ) }>
					<SelectControl
						key={ 'font-family' }
						label={ __( 'Font family', 'amp' ) }
						value={ ampFontFamily }
						options={ AMP_STORY_FONTS }
						onChange={ function( value ) {
							setAttributes( { ampFontFamily: value } );
						} }
					/>
					<FontSizePicker
						fallbackFontSize={ fallbackFontSize }
						value={ fontSize.size }
						onChange={ setFontSize }
					/>
					<SelectControl
						label={ __( 'Select text type', 'amp' ) }
						value={ type }
						onChange={ ( selected ) => setAttributes( { type: selected } ) }
						options={ [
							{ value: 'auto', label: __( 'Automatic', 'amp' ) },
							{ value: 'p', label: __( 'Paragraph', 'amp' ) },
							{ value: 'h1', label: __( 'Heading 1', 'amp' ) },
							{ value: 'h2', label: __( 'Heading 2', 'amp' ) },
						] }
					/>
				</PanelBody>
			</InspectorControls>
			<RichText
				identifier="content"
				wrapperClassName="wp-block-amp-story-text"
				tagName={ tagName }
				value={ content }
				onChange={ ( value ) => setAttributes( { content: value } ) }
				style={ {
					fontSize: fontSize.size ? fontSize.size + 'px' : undefined,
				} }
				className={ `${ className } ${ fontSizeClass }` }
				placeholder={ __( 'Write text…', 'amp' ) }
			/>
		</Fragment>
	);
}

const TextEdit = compose( [
	withFontSizes( 'fontSize' ),
	applyFallbackStyles,
] )( TextBlock );

export default TextEdit;
<|endoftext|>


<commit_before>define(['lodash', 'angular', 'dragula', 'filters/lstring', 'directives/print-smart/print-smart-checkout', './meeting-document', 'authentication'], function(_, ng) {
    //'css!./agenda.css' // moved to template
    var currentUser;

	return ["$scope", "$route", "$http", '$q', '$location', 'meeting', 'authentication', function ($scope, $route, $http, $q, $location, meetingCode, authentication) {

        var _ctrl = $scope.documentsCtrl = this;
        var meeting;
        var documents;

        _ctrl.sort = $location.hash() == 'agenda' ? 'agenda' : 'document';
        _ctrl.switchTab  = switchTab;

        $scope.$watch('documentsCtrl.sort', function(s){
            $location.hash(s=='agenda' ? 'agenda' : null);
        });

        initAffix();
        initEditor();
        load();
        loadNotifications();

        //==============================
        //
        //==============================
        function load() {

            meeting = $http.get('/api/v2016/meetings/'+meetingCode, { params: { f : { EVT_TIT_EN:1, EVT_CD:1, print:1 , agenda:1 } } }).then(function(res){

                meeting = _.defaults(res.data, {
                    code: res.data.EVT_CD,
                    title: res.data.EVT_TIT_EN,
                    agenda: { items: [] }
                });

                _ctrl.meeting = meeting;
                _ctrl.agenda  = meeting.agenda;

                return meeting;
            });

            documents = $http.get('/api/v2016/meetings/'+meetingCode+'/documents', { params: {  } }).then(function(res){

                documents = _(res.data).map(function(d){
                    d.metadata = d.metadata || {};
                    _.defaults(d.metadata, {
                        printable: ['crp', 'limited', 'non-paper'].indexOf(d.type)>=0
                    });

                    return d;

                }).filter(function(d){

                    return _ctrl.editMode || (d.files && d.files.length);

                }).sortBy(sortKey).value();

                _ctrl.documents = documents;

                return meeting;

            }).then(function() {

                var agendaMap = _.reduce(meeting.agenda.items, function(r,v) { r[v.item] = v;  return r; }, {});

                documents.forEach(function(d) {
                    (d.agendaItems||[]).forEach(function(item) {

                        if(!agendaMap[item]) {
                            meeting.agenda.items.push(agendaMap[item] = { item: item, title: d.title.en + " (AUTO) "}); // LAZY during dev
                        }

                        agendaMap[item].documents = agendaMap[item].documents||[];
                        agendaMap[item].documents.push(d);
                    });
                });

                var tabs = [
                    { code: 'outcome'    , title: 'Outcomes',    documents: _.filter(documents, byTypes(['report',    'outcome'])) },
                    { code: 'in-session' , title: 'In-session',  documents: _.filter(documents, byTypes(['non-paper', 'crp', 'limited'])) },
                    { code: 'official'   , title: 'Official',    documents: _.filter(documents, byTypes(['official'   ])) },
                    { code: 'information', title: 'Information', documents: _.filter(documents, byTypes(['information'])) },
                    { code: 'other'      , title: 'Others',      documents: _.filter(documents, byTypes(['other'      ],  ['report', 'outcome', 'non-paper', 'crp', 'limited', 'official', 'information', 'statement'])) },
                    { code: 'statement'  , title: 'Statements',  documents: _.filter(documents, byTypes(['statement'  ])) },
                ];

                _ctrl.tabs = _(tabs).forEach(function(tab){

                    var itemIds = _(tab.documents).map('agendaItems').flatten().uniq().value();
                    var items   = _(meeting.agenda.items).filter(function(item) {

                        return ~itemIds.indexOf(item.item);

                    }).map(function(item){

                        return _.extend({}, item, {
                            documents : _.intersection(item.documents, tab.documents)
                        });
                    }).value();

                    var noAgendaDocs = _(tab.documents).difference(_(items).map('documents').flatten().value()).value();

                    tab.agenda = {
                        items : items,
                        otherDocuments : noAgendaDocs
                    };

                }).filter(function(t) {
                    return t.documents.length || t.code == 'in-session';
                }).value();

                injectNotifications();
                switchTab();

            }).catch(console.error);
        }

        //==============================
        //
        //==============================
        function byTypes(inTypes, outTypes) {
            return function(doc) {
                return (inTypes  &&  ~inTypes .indexOf(doc.type)) ||
                       (outTypes && !~outTypes.indexOf(doc.type));
            };
        }

        //==============================
        //
        //==============================
        function loadNotifications() {

            $http.get('/api/v2013/index', { params: { q : 'schema_s:notification AND meeting_ss:'+meetingCode, fl: 'id,symbol_s,reference_s,meeting_ss,sender_s,title_*,date_dt,actionDate_dt,recipient_ss,url_ss', rows:999 } }).then(function(res){

                _ctrl.notifications = _.map(res.data.response.docs, function(n) {
                    return _.defaults(n, {
                        _id: n.id,
                        symbol: n.reference_s || n.symbol_s,
                        number: n.symbol_s,
                        date:   n.date_dt,
                        type:  'notification',
                        title : { en : n.title_t },
                        sortKey : n.symbol_s,
                        files : urlToFiles(n.url_ss)
                    });
                });
            }).then(function(){

                injectNotifications();
                switchTab();

            }).catch(console.error);
        }

        //==============================
        //
        //==============================
        function injectNotifications(){

            if(!_ctrl.notifications || !_ctrl.notifications.length)
                return;

            _ctrl.tabs = _ctrl.tabs || [];

            if(!_.some(_ctrl.tabs, { code: 'notification'})) {

                _ctrl.documents = (_ctrl.documents).concat(_ctrl.notifications);

                _ctrl.tabs.push({
                    code : 'notification',
                    documents : _ctrl.notifications
                });
            }
        }

        //==============================
        //
        //==============================
        function switchTab(tab) {

            if(!tab && $location.search().tabFor) {
                tab = _(_ctrl.tabs).find(function(t) {
                    return _(t.documents).some({_id:$location.search().tabFor});
                });
            }

            if(tab && $location.search().tabFor)
                $location.search({tabFor:null});

            if(!tab && !_ctrl.currentTab)
                tab = _ctrl.tabs[0];

            if(!tab && _ctrl.currentTab)
                tab = _(_ctrl.tabs).findWhere({ code :_ctrl.currentTab });

            if(!tab)
                return;

            if(!tab.loaded && _ctrl.editMode) {
                initDragdrop();
            }

            tab.loaded=true;
            _ctrl.currentTab = tab.code;
        }

        //==============================
        //
        //==============================
        function initDragdrop() {

            setTimeout(function() {
            require(['dragula'], function(dragula) {

                ng.element("tbody.documents:not(.drag-ready)").each(function(i,element){

                    ng.element(element).addClass("drag-ready"); //prevent double initialization

                    dragula([element], {
                        moves: function (el, source, handle) {
                            return handle.classList.contains('handle');
                        },

                    }).on('drop', function(el) {

                        var curr = ng.element(el)       .attr('document-id');
                        var prev = ng.element(el).prev().attr('document-id') || "000000000000000000000000";
                        var next = ng.element(el).next().attr('document-id') || "ffffffffffffffffffffffff";

                        var data = { between : [prev, next] };

                        $http.put('/api/v2016/meetings/'+meetingCode+'/documents/'+curr+'/position', data).then(function(){
                            load();
                        }).catch(console.error);

                    });
                });

            });
        }, 100);
        }

        //==============================
        //
        //==============================
        function sortKey(d) {
            return ("000000000" + (d.position||9999)).slice(-9) + '_' + // pad with 0 eg: 150  =>  000000150
                   (d.symbol||"").replace(/\b(\d)\b/g, '0$1')
                                 .replace(/(\/REV)/gi, '0$1')
                                 .replace(/(\/ADD)/gi, '1$1');
        }

        //==============================
        //
        //==============================
        function urlToFiles(url_ss) {

            return _.map(url_ss||[], function(url){

                var mime;
                var locale;

                if(/\.pdf$/ .test(url)) mime = 'application/pdf';
                if(/\.doc$/ .test(url)) mime = 'application/msword';
                if(/\.docx$/.test(url)) mime = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';

                if(/-ar\.\w+$/ .test(url)) locale = 'ar';
                if(/-en\.\w+$/ .test(url)) locale = 'en';
                if(/-es\.\w+$/ .test(url)) locale = 'es';
                if(/-fr\.\w+$/ .test(url)) locale = 'fr';
                if(/-ru\.\w+$/ .test(url)) locale = 'ru';
                if(/-zh\.\w+$/ .test(url)) locale = 'zh';

                return {
                    mime : mime,
                    locale: locale,
                    url : 'https://www.cbd.int'+url
                };
            });
        }

        //==============================
        //
        //==============================
        function initAffix() {

            var affixReady = $scope.$watch(function() {

                var psc = ng.element('#print-smart-checkout');

                if(psc.size()) {
                    psc.affix({ offset: { top:psc.offset().top - 10 } });
                    affixReady();
                }
            });
        }

        // EDIT

        //==============================
        //
        //==============================
        function initEditor() {

            $q.when(currentUser || authentication.getUser()).then(function(user){
                currentUser = user;

                if(!user.isAuthenticated)
                    return;

                if(!_.intersection(user.roles||[], ["Administrator","EditorialService"]).length)
                    return;

                _ctrl.edit       = edit;
                _ctrl.editMode   = $scope.$root.documentEditMode;

                $scope.$watch('documentsCtrl.editMode', function(n,o){
                    $scope.$root.documentEditMode = n;
                    if(n!=o) load();
                });
            });
        }

        //==============================
        //
        //==============================
        function edit(doc) {

            var id = doc ? doc._id : 'new';

            $location.url('/management/'+meeting.code+ '/documents/'+id);
        }
	}];
});
<commit_msg>Fix Typo<commit_after>define(['lodash', 'angular', 'dragula', 'filters/lstring', 'directives/print-smart/print-smart-checkout', './meeting-document', 'authentication'], function(_, ng) {
    //'css!./agenda.css' // moved to template
    var currentUser;

	return ["$scope", "$route", "$http", '$q', '$location', 'meeting', 'authentication', function ($scope, $route, $http, $q, $location, meetingCode, authentication) {

        var _ctrl = $scope.documentsCtrl = this;
        var meeting;
        var documents;

        _ctrl.sort = $location.hash() == 'agenda' ? 'agenda' : 'document';
        _ctrl.switchTab  = switchTab;

        $scope.$watch('documentsCtrl.sort', function(s){
            $location.hash(s=='agenda' ? 'agenda' : null);
        });

        initAffix();
        initEditor();
        load();
        loadNotifications();

        //==============================
        //
        //==============================
        function load() {

            meeting = $http.get('/api/v2016/meetings/'+meetingCode, { params: { f : { EVT_TIT_EN:1, EVT_CD:1, print:1 , agenda:1 } } }).then(function(res){

                meeting = _.defaults(res.data, {
                    code: res.data.EVT_CD,
                    title: res.data.EVT_TIT_EN,
                    agenda: { items: [] }
                });

                _ctrl.meeting = meeting;
                _ctrl.agenda  = meeting.agenda;

                return meeting;
            });

            documents = $http.get('/api/v2016/meetings/'+meetingCode+'/documents', { params: {  } }).then(function(res){

                documents = _(res.data).map(function(d){
                    d.metadata = d.metadata || {};
                    _.defaults(d.metadata, {
                        printable: ['crp', 'limited', 'non-paper'].indexOf(d.type)>=0
                    });

                    return d;

                }).filter(function(d){

                    return _ctrl.editMode || (d.files && d.files.length);

                }).sortBy(sortKey).value();

                _ctrl.documents = documents;

                return meeting;

            }).then(function() {

                var agendaMap = _.reduce(meeting.agenda.items, function(r,v) { r[v.item] = v;  return r; }, {});

                documents.forEach(function(d) {
                    (d.agendaItems||[]).forEach(function(item) {

                        if(!agendaMap[item]) {
                            meeting.agenda.items.push(agendaMap[item] = { item: item, title: d.title.en + " (AUTO) "}); // LAZY during dev
                        }

                        agendaMap[item].documents = agendaMap[item].documents||[];
                        agendaMap[item].documents.push(d);
                    });
                });

                var tabs = [
                    { code: 'outcome'    , title: 'Outcomes',    documents: _.filter(documents, byTypes(['report',    'outcome'])) },
                    { code: 'in-session' , title: 'In-session',  documents: _.filter(documents, byTypes(['non-paper', 'crp', 'limited'])) },
                    { code: 'official'   , title: 'Official',    documents: _.filter(documents, byTypes(['official'   ])) },
                    { code: 'information', title: 'Information', documents: _.filter(documents, byTypes(['information'])) },
                    { code: 'other'      , title: 'Other',      documents: _.filter(documents, byTypes(['other'      ],  ['report', 'outcome', 'non-paper', 'crp', 'limited', 'official', 'information', 'statement'])) },
                    { code: 'statement'  , title: 'Statements',  documents: _.filter(documents, byTypes(['statement'  ])) },
                ];

                _ctrl.tabs = _(tabs).forEach(function(tab){

                    var itemIds = _(tab.documents).map('agendaItems').flatten().uniq().value();
                    var items   = _(meeting.agenda.items).filter(function(item) {

                        return ~itemIds.indexOf(item.item);

                    }).map(function(item){

                        return _.extend({}, item, {
                            documents : _.intersection(item.documents, tab.documents)
                        });
                    }).value();

                    var noAgendaDocs = _(tab.documents).difference(_(items).map('documents').flatten().value()).value();

                    tab.agenda = {
                        items : items,
                        otherDocuments : noAgendaDocs
                    };

                }).filter(function(t) {
                    return t.documents.length || t.code == 'in-session';
                }).value();

                injectNotifications();
                switchTab();

            }).catch(console.error);
        }

        //==============================
        //
        //==============================
        function byTypes(inTypes, outTypes) {
            return function(doc) {
                return (inTypes  &&  ~inTypes .indexOf(doc.type)) ||
                       (outTypes && !~outTypes.indexOf(doc.type));
            };
        }

        //==============================
        //
        //==============================
        function loadNotifications() {

            $http.get('/api/v2013/index', { params: { q : 'schema_s:notification AND meeting_ss:'+meetingCode, fl: 'id,symbol_s,reference_s,meeting_ss,sender_s,title_*,date_dt,actionDate_dt,recipient_ss,url_ss', rows:999 } }).then(function(res){

                _ctrl.notifications = _.map(res.data.response.docs, function(n) {
                    return _.defaults(n, {
                        _id: n.id,
                        symbol: n.reference_s || n.symbol_s,
                        number: n.symbol_s,
                        date:   n.date_dt,
                        type:  'notification',
                        title : { en : n.title_t },
                        sortKey : n.symbol_s,
                        files : urlToFiles(n.url_ss)
                    });
                });
            }).then(function(){

                injectNotifications();
                switchTab();

            }).catch(console.error);
        }

        //==============================
        //
        //==============================
        function injectNotifications(){

            if(!_ctrl.notifications || !_ctrl.notifications.length)
                return;

            _ctrl.tabs = _ctrl.tabs || [];

            if(!_.some(_ctrl.tabs, { code: 'notification', title: 'Notifications' })) {

                _ctrl.documents = (_ctrl.documents).concat(_ctrl.notifications);

                _ctrl.tabs.push({
                    code : 'notification',
                    documents : _ctrl.notifications
                });
            }
        }

        //==============================
        //
        //==============================
        function switchTab(tab) {

            if(!tab && $location.search().tabFor) {
                tab = _(_ctrl.tabs).find(function(t) {
                    return _(t.documents).some({_id:$location.search().tabFor});
                });
            }

            if(tab && $location.search().tabFor)
                $location.search({tabFor:null});

            if(!tab && !_ctrl.currentTab)
                tab = _ctrl.tabs[0];

            if(!tab && _ctrl.currentTab)
                tab = _(_ctrl.tabs).findWhere({ code :_ctrl.currentTab });

            if(!tab)
                return;

            if(!tab.loaded && _ctrl.editMode) {
                initDragdrop();
            }

            tab.loaded=true;
            _ctrl.currentTab = tab.code;
        }

        //==============================
        //
        //==============================
        function initDragdrop() {

            setTimeout(function() {
            require(['dragula'], function(dragula) {

                ng.element("tbody.documents:not(.drag-ready)").each(function(i,element){

                    ng.element(element).addClass("drag-ready"); //prevent double initialization

                    dragula([element], {
                        moves: function (el, source, handle) {
                            return handle.classList.contains('handle');
                        },

                    }).on('drop', function(el) {

                        var curr = ng.element(el)       .attr('document-id');
                        var prev = ng.element(el).prev().attr('document-id') || "000000000000000000000000";
                        var next = ng.element(el).next().attr('document-id') || "ffffffffffffffffffffffff";

                        var data = { between : [prev, next] };

                        $http.put('/api/v2016/meetings/'+meetingCode+'/documents/'+curr+'/position', data).then(function(){
                            load();
                        }).catch(console.error);

                    });
                });

            });
        }, 100);
        }

        //==============================
        //
        //==============================
        function sortKey(d) {
            return ("000000000" + (d.position||9999)).slice(-9) + '_' + // pad with 0 eg: 150  =>  000000150
                   (d.symbol||"").replace(/\b(\d)\b/g, '0$1')
                                 .replace(/(\/REV)/gi, '0$1')
                                 .replace(/(\/ADD)/gi, '1$1');
        }

        //==============================
        //
        //==============================
        function urlToFiles(url_ss) {

            return _.map(url_ss||[], function(url){

                var mime;
                var locale;

                if(/\.pdf$/ .test(url)) mime = 'application/pdf';
                if(/\.doc$/ .test(url)) mime = 'application/msword';
                if(/\.docx$/.test(url)) mime = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';

                if(/-ar\.\w+$/ .test(url)) locale = 'ar';
                if(/-en\.\w+$/ .test(url)) locale = 'en';
                if(/-es\.\w+$/ .test(url)) locale = 'es';
                if(/-fr\.\w+$/ .test(url)) locale = 'fr';
                if(/-ru\.\w+$/ .test(url)) locale = 'ru';
                if(/-zh\.\w+$/ .test(url)) locale = 'zh';

                return {
                    mime : mime,
                    locale: locale,
                    url : 'https://www.cbd.int'+url
                };
            });
        }

        //==============================
        //
        //==============================
        function initAffix() {

            var affixReady = $scope.$watch(function() {

                var psc = ng.element('#print-smart-checkout');

                if(psc.size()) {
                    psc.affix({ offset: { top:psc.offset().top - 10 } });
                    affixReady();
                }
            });
        }

        // EDIT

        //==============================
        //
        //==============================
        function initEditor() {

            $q.when(currentUser || authentication.getUser()).then(function(user){
                currentUser = user;

                if(!user.isAuthenticated)
                    return;

                if(!_.intersection(user.roles||[], ["Administrator","EditorialService"]).length)
                    return;

                _ctrl.edit       = edit;
                _ctrl.editMode   = $scope.$root.documentEditMode;

                $scope.$watch('documentsCtrl.editMode', function(n,o){
                    $scope.$root.documentEditMode = n;
                    if(n!=o) load();
                });
            });
        }

        //==============================
        //
        //==============================
        function edit(doc) {

            var id = doc ? doc._id : 'new';

            $location.url('/management/'+meeting.code+ '/documents/'+id);
        }
	}];
});
<|endoftext|>


<commit_before>import queryString from 'query-string';

import { baseLayers, overlayLayers } from 'fm3/mapDefinitions';
import { getTrasformedParamsIfIsOldFreemapUrl, getTrasformedParamsIfIsOldEmbeddedFreemapUrl } from 'fm3/oldFreemapUtils';

const baseLetters = baseLayers.map(({ type }) => type).join('');
const overlayLetters = ['I', ...overlayLayers.map(({ type }) => type).join('')];
const layersRegExp = new RegExp(`^[${baseLetters}][${overlayLetters}]*$`);

export function getMapStateFromUrl(location) {
  if (getTrasformedParamsIfIsOldEmbeddedFreemapUrl(location)) {
    const transformedParams = getTrasformedParamsIfIsOldEmbeddedFreemapUrl(location);
    return transformedParams;
  }

  if (getTrasformedParamsIfIsOldFreemapUrl(location)) {
    const transformedParams = getTrasformedParamsIfIsOldFreemapUrl(location);
    return transformedParams;
  }

  const query = queryString.parse(location.search);

  const [zoomFrag, latFrag, lonFrag] = (query.map || '').split('/');

  const lat = parseFloat(latFrag);
  const lon = parseFloat(lonFrag);
  const zoom = parseInt(zoomFrag, 10);

  const layers = query.layers || '';

  const layersOK = layersRegExp.test(layers);

  if (!layersOK || Number.isNaN(lat) || Number.isNaN(lon) || Number.isNaN(zoom)) {
    return null;
  }

  const mapType = layers.charAt(0);
  const overlays = layers.length > 1 ? layers.substring(1).split('') : [];

  return {
    lat, lon, zoom, mapType, overlays,
  };
}

export function getMapStateDiffFromUrl(state1, state2) {
  if (!state1 || !state2) {
    return null;
  }

  const {
    lat, lon, zoom, mapType, overlays,
  } = state1;
  const changes = {};

  if (mapType !== state2.mapType) {
    changes.mapType = mapType;
  }

  if (overlays.join('') !== state2.overlays.join('')) {
    changes.overlays = overlays;
  }

  if (Math.abs(lat - state2.lat) > 0.00001) {
    changes.lat = lat;
  }

  if (Math.abs(lon - state2.lon) > 0.00001) {
    changes.lon = lon;
  }

  if (zoom !== state2.zoom) {
    changes.zoom = zoom;
  }

  return changes;
}

<commit_msg>added support for incomplete map parameters (fixes #230)<commit_after>import queryString from 'query-string';

import { baseLayers, overlayLayers } from 'fm3/mapDefinitions';
import { getTrasformedParamsIfIsOldFreemapUrl, getTrasformedParamsIfIsOldEmbeddedFreemapUrl } from 'fm3/oldFreemapUtils';

const baseLetters = baseLayers.map(({ type }) => type).join('');
const overlayLetters = ['I', ...overlayLayers.map(({ type }) => type).join('')];
const layersRegExp = new RegExp(`^[${baseLetters}][${overlayLetters}]*$`);

export function getMapStateFromUrl(location) {
  if (getTrasformedParamsIfIsOldEmbeddedFreemapUrl(location)) {
    const transformedParams = getTrasformedParamsIfIsOldEmbeddedFreemapUrl(location);
    return transformedParams;
  }

  if (getTrasformedParamsIfIsOldFreemapUrl(location)) {
    const transformedParams = getTrasformedParamsIfIsOldFreemapUrl(location);
    return transformedParams;
  }

  const query = queryString.parse(location.search);

  const [zoomFrag, latFrag, lonFrag] = (query.map || '').split('/');

  const lat = undefineNaN(parseFloat(latFrag));
  const lon = undefineNaN(parseFloat(lonFrag));
  const zoom = undefineNaN(parseInt(zoomFrag, 10));

  const layers = query.layers || '';

  const layersOK = layersRegExp.test(layers);

  const mapType = layersOK ? layers.charAt(0) : undefined;
  const overlays = layersOK && layers.length > 1 ? layers.substring(1).split('') : [];

  return {
    lat, lon, zoom, mapType, overlays,
  };
}

function undefineNaN(val) {
  return Number.isNaN(val) ? undefined : val;
}

export function getMapStateDiffFromUrl(state1, state2) {
  if (!state1 || !state2) {
    return null;
  }

  const {
    lat, lon, zoom, mapType, overlays = [],
  } = state1;
  const changes = {};

  if (mapType && mapType !== state2.mapType) {
    changes.mapType = mapType;
  }

  if (overlays.join('') !== state2.overlays.join('')) {
    changes.overlays = overlays;
  }

  if (lat && Math.abs(lat - state2.lat) > 0.00001) {
    changes.lat = lat;
  }

  if (lon && Math.abs(lon - state2.lon) > 0.00001) {
    changes.lon = lon;
  }

  if (zoom && zoom !== state2.zoom) {
    changes.zoom = zoom;
  }

  return changes;
}

<|endoftext|>