<commit_before>dojo.provide("dijit.util.PopupManager");

dojo.require("dijit.util.BackgroundIframe");
dojo.require("dijit.util.FocusManager");
dojo.require("dijit.util.place");
dojo.require("dijit.util.window");

dijit.util.PopupManager = new function(){
	// summary:
	//		This class is used to show/hide popups.
	//
	//		The widget must implement a close() callback, which is called when someone
	//		clicks somewhere random on the screen.  It will hide the [chain of] context menus

	var stack = [];
	var beginZIndex=1000;

	this.open = function(/*Event*/ e, /*Widget*/widget, /*Object*/ padding){
		// summary:
		//		Open the widget at mouse position
		//		TODO: if widget has href, attach to onLoaded() and reposition

		var x = e.pageX, y = e.pageY;
		var win = dijit.util.window.getDocumentWindow(e.target.ownerDocument);
		var iframe = win._frameElement || win.frameElement;
		if(iframe){
			var cood = dojo.coords(iframe, true);
			x += cood.x - dojo.withGlobal(win, dijit.util.getScroll).left;
			y += cood.y - dojo.withGlobal(win, dijit.util.getScroll).top;
		}
		dijit.util.placeOnScreen(widget.domNode, x, y, padding, true);

		_open(widget);
	}

	this.openAround = function(/*Widget*/parent, /*Widget*/widget, /*String?*/orient, /*Array?*/padding){
		// summary:
		//		Open the widget relative to parent widget (typically as a drop down to that widget)
		//		TODO: if widget has href attach to onLoaded and reposition

		dijit.util.placeOnScreenAroundElement(widget.domNode, parent, padding, orient);

		_open(widget);
	};

	function _open(widget){
		// summary:
		//		Utility function to help opening

		// display temporarily, and move into position, then hide again
		with(widget.domNode.style){
			zIndex = beginZIndex + stack.length;
			position = "absolute";
		}

		if(stack.length == 0){
			beforeTopOpen(widget);
		}

		stack.push(widget);

		// TODO: use effects
		dojo.style(widget.domNode, "display", "");

		if(dojo.isIE && dojo.isIE < 7){
			if(!widget.bgIframe){
				widget.bgIframe = new dijit.util.BackgroundIframe();
				widget.bgIframe.setZIndex(widget.domNode);
			}
			widget.bgIframe.size(widget.domNode);
			widget.bgIframe.show();
		}

	};

	this.close = function(){
		// summary:
		//		Close top level popup

		var widget = stack.pop();

		dojo.style(widget.domNode, "display", "none");
		if(dojo.isIE && dojo.isIE < 7){
			widget.bgIframe.hide();
		}

		if(stack.length == 0){
			afterTopClose(widget);
		}
	};

	///////////////////////////////////////////////////////////////////////
	// Utility functions for making mouse click close popup chain
	var currentTrigger;

	function beforeTopOpen(/*Widget*/ button, /*Widget*/menu){
		// summary:
		//	Called when a popup is opened, typically a button opening a menu.
		//	Registers handlers so that clicking somewhere else on the screen will close the popup

		// TODO: should do this at every level of popup?
		dijit.util.FocusManager.save(menu);

		currentTrigger=button;

		// setup handlers to catch screen clicks and close current menu
		setWindowEvents("connect");
	};

	function afterTopClose(/*Widget*/menu){
		// summary:
		//	called when the top level popup is closed, but before it performs it's actions
		//	removes handlers for mouse movement detection

		// remove handlers to catch screen clicks and close current menu
		// TODO: this doesn't seem to have any effect; try it after scott's new event code.
		setWindowEvents("disconnect");

		currentTrigger = null;

		dijit.util.FocusManager.restore(menu);
	};

	function onKeyPress(/*Event*/e){
		// summary
		//	Handles keystrokes, passing them up the chain of menus
		if(!e.keyCode){ return; }
		if(stack.length==0){ return; }

		// loop from child menu up ancestor chain, ending at button that spawned the menu
		var m = stack[stack.length-1];
		while(m){
			if(m.processKey(e)){
				e.preventDefault();
				e.stopPropagation();
				break;
			}
			m = m.parentPopup || m.parentMenu;
		}
	};

	function onMouse(/*Event*/e){
		// summary
		// Monitor clicks in the screen.  If popup has requested it than
		// clicking anywhere on the screen will close the current menu hierarchy

		if(stack.length==0){ return; }

		//PORT from dojo.dom.isDescendantOf
		var isDescendantOf = function(/*Node*/node, /*Node*/ancestor){
			//	summary
			//	Returns boolean if node is a descendant of ancestor
			// guaranteeDescendant allows us to be a "true" isDescendantOf function

			while(node){
				if(node === ancestor){
					return true; // boolean
				}
				node = node.parentNode;
			}
			return false; // boolean
		}

		// if they clicked on the trigger node (often a button), ignore the click
		if(currentTrigger && isDescendantOf(e.target, currentTrigger)){
			return;
		}

		// if they clicked on the popup itself then ignore it
		if(dojo.some(stack, function(widget){
			return isDescendantOf(e.target, widget.domNode);
		}))
		{
			return;
		}

		// the click didn't fall within the open menu tree so close it
		stack[0].close(true);
	};

	function setWindowEvents(/*String*/ command, /*Window*/targetWindow){
		// summary:
		//		This function connects or disconnects listeners on all the iframes
		//		and the top window, so that whereever the user clicks in the page,
		//		the popup menu will be closed

		if(!targetWindow){ //see comment below
			targetWindow = dijit.util.window.getDocumentWindow(window.top && window.top.document || window.document);
		}

		if(command == 'connect'){
			targetWindow._onmousedownhandler = dojo.connect(targetWindow.document, 'onmousedown', null, onMouse);
			targetWindow._onscrollhandler = dojo.connect(targetWindow, "onscroll", null, onMouse);
			targetWindow._onkeyhandler = dojo.connect(targetWindow.document, "onkeypress", null, onKeyPress);
		}else{
			dojo.disconnect(targetWindow.document, 'onmousedown', targetWindow._onmousedownhandler);
			targetWindow._onmousedownhandler = null;
			dojo.disconnect(targetWindow, "onscroll", targetWindow._onscrollhandler);
			targetWindow._onscrollhandler = null;
			dojo.disconnect(targetWindow.document, "onkey", targetWindow._onkeyhandler);
			targetWindow._onkeyhandler = null;
		}

		for(var i = 0; i < targetWindow.frames.length; i++){
			try{
				//do not remove dijit.util.window.getDocumentWindow, see comment in it
				var win = dijit.util.window.getDocumentWindow(targetWindow.frames[i].document);
				if(win){
					setWindowEvents(command, win);
				}
			}catch(e){ /* squelch error for cross domain iframes */ }
		}
	};
	dojo.addOnUnload(function(){ setWindowEvents("disconnect"); });
}();<commit_msg>Missed a spot.  Refs #2727<commit_after>dojo.provide("dijit.util.PopupManager");

dojo.require("dijit.util.BackgroundIframe");
dojo.require("dijit.util.FocusManager");
dojo.require("dijit.util.place");
dojo.require("dijit.util.window");

dijit.util.PopupManager = new function(){
	// summary:
	//		This class is used to show/hide popups.
	//
	//		The widget must implement a close() callback, which is called when someone
	//		clicks somewhere random on the screen.  It will hide the [chain of] context menus

	var stack = [];
	var beginZIndex=1000;

	this.open = function(/*Event*/ e, /*Widget*/widget, /*Object*/ padding){
		// summary:
		//		Open the widget at mouse position
		//		TODO: if widget has href, attach to onLoaded() and reposition

		var x = e.pageX, y = e.pageY;
		var win = dijit.util.window.getDocumentWindow(e.target.ownerDocument);
		var iframe = win._frameElement || win.frameElement;
		if(iframe){
			var cood = dojo.coords(iframe, true);
			x += cood.x - dojo.withGlobal(win, dijit.util.getScroll).left;
			y += cood.y - dojo.withGlobal(win, dijit.util.getScroll).top;
		}
		dijit.util.placeOnScreen(widget.domNode, x, y, padding, true);

		_open(widget);
	}

	this.openAround = function(/*Widget*/parent, /*Widget*/widget, /*String?*/orient, /*Array?*/padding){
		// summary:
		//		Open the widget relative to parent widget (typically as a drop down to that widget)
		//		TODO: if widget has href attach to onLoaded and reposition

		dijit.util.placeOnScreenAroundElement(widget.domNode, parent, padding, orient);

		_open(widget);
	};

	function _open(widget){
		// summary:
		//		Utility function to help opening

		// display temporarily, and move into position, then hide again
		with(widget.domNode.style){
			zIndex = beginZIndex + stack.length;
			position = "absolute";
		}

		if(stack.length == 0){
			beforeTopOpen(widget);
		}

		stack.push(widget);

		// TODO: use effects
		dojo.style(widget.domNode, "display", "");

		if(dojo.isIE && dojo.isIE < 7){
			if(!widget.bgIframe){
				widget.bgIframe = new dijit.util.BackgroundIframe();
				widget.bgIframe.setZIndex(widget.domNode);
			}
			widget.bgIframe.size(widget.domNode);
			widget.bgIframe.show();
		}

	};

	this.close = function(){
		// summary:
		//		Close top level popup

		var widget = stack.pop();

		dojo.style(widget.domNode, "display", "none");
		if(dojo.isIE && dojo.isIE < 7){
			widget.bgIframe.hide();
		}

		if(stack.length == 0){
			afterTopClose(widget);
		}
	};

	///////////////////////////////////////////////////////////////////////
	// Utility functions for making mouse click close popup chain
	var currentTrigger;

	function beforeTopOpen(/*Widget*/ button, /*Widget*/menu){
		// summary:
		//	Called when a popup is opened, typically a button opening a menu.
		//	Registers handlers so that clicking somewhere else on the screen will close the popup

		// TODO: should do this at every level of popup?
		dijit.util.FocusManager.save(menu);

		currentTrigger=button;

		// setup handlers to catch screen clicks and close current menu
		setWindowEvents("connect");
	};

	function afterTopClose(/*Widget*/menu){
		// summary:
		//	called when the top level popup is closed, but before it performs it's actions
		//	removes handlers for mouse movement detection

		// remove handlers to catch screen clicks and close current menu
		// TODO: this doesn't seem to have any effect; try it after scott's new event code.
		setWindowEvents("disconnect");

		currentTrigger = null;

		dijit.util.FocusManager.restore(menu);
	};

	function onKeyPress(/*Event*/e){
		// summary
		//	Handles keystrokes, passing them up the chain of menus
		if(!e.keyCode){ return; }
		if(stack.length==0){ return; }

		// loop from child menu up ancestor chain, ending at button that spawned the menu
		var m = stack[stack.length-1];
		while(m){
			if(m.processKey(e)){
				e.preventDefault();
				e.stopPropagation();
				break;
			}
			m = m.parentPopup || m.parentMenu;
		}
	};

	function onMouse(/*Event*/e){
		// summary
		// Monitor clicks in the screen.  If popup has requested it than
		// clicking anywhere on the screen will close the current menu hierarchy

		if(stack.length==0){ return; }

		//PORT from dojo.dom.isDescendantOf
		var isDescendantOf = function(/*Node*/node, /*Node*/ancestor){
			//	summary
			//	Returns boolean if node is a descendant of ancestor
			// guaranteeDescendant allows us to be a "true" isDescendantOf function

			while(node){
				if(node === ancestor){
					return true; // boolean
				}
				node = node.parentNode;
			}
			return false; // boolean
		}

		// if they clicked on the trigger node (often a button), ignore the click
		if(currentTrigger && isDescendantOf(e.target, currentTrigger)){
			return;
		}

		// if they clicked on the popup itself then ignore it
		if(dojo.some(stack, function(widget){
			return isDescendantOf(e.target, widget.domNode);
		}))
		{
			return;
		}

		// the click didn't fall within the open menu tree so close it
		stack[0].close(true);
	};

	function setWindowEvents(/*String*/ command, /*Window*/targetWindow){
		// summary:
		//		This function connects or disconnects listeners on all the iframes
		//		and the top window, so that whereever the user clicks in the page,
		//		the popup menu will be closed

		if(!targetWindow){ //see comment below
			targetWindow = dijit.util.window.getDocumentWindow(window.top && window.top.document || window.document);
		}

		if(command == 'connect'){
			targetWindow._onmousedownhandler = dojo.connect(targetWindow.document, 'onmousedown', null, onMouse);
			targetWindow._onscrollhandler = dojo.connect(targetWindow, "onscroll", null, onMouse);
			targetWindow._onkeyhandler = dojo.connect(targetWindow.document, "onkeypress", null, onKeyPress);
		}else{
			dojo.disconnect(targetWindow.document, 'onmousedown', targetWindow._onmousedownhandler);
			targetWindow._onmousedownhandler = null;
			dojo.disconnect(targetWindow, "onscroll", targetWindow._onscrollhandler);
			targetWindow._onscrollhandler = null;
			dojo.disconnect(targetWindow.document, "onkeypress", targetWindow._onkeyhandler);
			targetWindow._onkeyhandler = null;
		}

		for(var i = 0; i < targetWindow.frames.length; i++){
			try{
				//do not remove dijit.util.window.getDocumentWindow, see comment in it
				var win = dijit.util.window.getDocumentWindow(targetWindow.frames[i].document);
				if(win){
					setWindowEvents(command, win);
				}
			}catch(e){ /* squelch error for cross domain iframes */ }
		}
	};
	dojo.addOnUnload(function(){ setWindowEvents("disconnect"); });
}();<|endoftext|>


<commit_before>/*
This is the defualt transformations library.
It works with the Tools API, which specifies
 */

var Hist = new Array();

// History framework
//{func: function, params: [x, y, z]}

function Trans(map){
	this.func = map['func'];
	this.params = map['params'];
	// automatically record
	this.index = this.record();
}

// calls a function
Trans.prototype.call = function(){
	this.func(this.params);
}

Trans.prototype.record = function(){
	Hist.push(this);
	return Hist.length - 1
}

Trans.prototype.toString = function(){
	var s = new Array();
	s.push(this.func.name, '(');
	var p = new Array();
	for (var i = 0; i < this.params.length; i++){
		p.push(this.params[i])
	}
	s.push(p.join(', '));
	s.push(')');
	return s.join('');
}

Trans.prototype.Set = function(){
	var s = document.createElement('p');
	s.appendChild(document.createTextNode(this.toString()));
	s.setAttribute('onclick', 'Hist['+this.index+'].call()')
	var h = document.getElementById('hist');
	h.insertBefore(s, h.firstChild);
}

// Default Transformations
var lastScale = [1.0,1.0,1.0]; // for reverting after scale
var lastRotate = [0.0,0.0,0.0];
var lastShift = [0.0, 0.0, 0.0];
var lastAutoCenter = [0.0,0.0,0.0];

// Set functions parse the
function setTrans(x, y, z, def, trans){
	if (isNaN(px = parseFloat(x))) {
		px = def;
	}
	if (isNaN(py = parseFloat(y))) {
		py = def;
	}
	if (isNaN(pz = parseFloat(z))) {
		pz = def;
	}
	var t = new Trans({
		func: trans,
		params: [px, py, pz]
	})
	t.call();
	t.Set(); // shows on page
}

function Scale(par){
	for (var i = 0; i < geometry.vertices.length; i++) {
		geometry.vertices[i].x *= (par[0]/lastScale[0]);
		geometry.vertices[i].y *= (par[1]/lastScale[1]);
		geometry.vertices[i].z *= (par[2]/lastScale[2]);
	}
	// save state
	lastScale[0] = par[0];
	lastScale[1] = par[1];
	lastScale[2] = par[2];

	geometry.verticesNeedUpdate = true;
}

function Shift(par){
	for (var i = 0; i < geometry.vertices.length; i++) {
		geometry.vertices[i].x += (par[0] - lastRotate[0]);
		geometry.vertices[i].y += (par[1] - lastRotate[1]);
		geometry.vertices[i].z += (par[2] - lastRotate[2]);
	}
	// save state
	lastShift[0] = par[0];
	lastShift[1] = par[1];
	lastShift[2] = par[2];
	geometry.verticesNeedUpdate = true;
}

function Rotate(par){
	var rotx = new THREE.Matrix4().makeRotationX(Math.PI*par[0]/180);
	var roty = new THREE.Matrix4().makeRotationY(Math.PI*par[1]/180);
	var rotz = new THREE.Matrix4().makeRotationZ(Math.PI*par[2]/180);

	geometry.applyMatrix(rotx.multiply(roty).multiply(rotz));
	lastRotate[0] = par[0];
	lastRotate[1] = par[1];
	lastRotate[2] = par[2];
	geometry.verticesNeedUpdate = true;
}

function AutoCenter(){
	geometry.computeBoundingBox ();
	var b =geometry.boundingBox;
	var lenX = (b.max.x - b.min.x)/2;
	var x = lenX - b.max.x;
	var lenY = (b.max.y - b.min.y)/2;
	var y = lenY - b.max.y;
	// do not center z, min should be 0
	var lenZ = (b.max.z - b.min.z);
	var z = (lenZ - b.max.z);
	//alert([x,y,z]);
	//Shift([x,y,z]);
	// use Shift invisibly
	var last = lastShift.slice(0);
	setTrans(x-lastAutoCenter[0], y-lastAutoCenter[1], z-lastAutoCenter[2], 0.0, Shift);
	lastShift = last.slice(0);
	// save
	lastAutoCenter[0] = x;
	lastAutoCenter[1] = y;
	lastAutoCenter[2] = z;
}

/*function Stats(){
	var b = cube.geometry.boundingBox;
	var s = ['Min x:', b.min.x, 'Min y:', b.min.y, 'Min z:', b.min.z];
	s.push('Max x:', b.max.x, 'Max y:', b.max.y, 'Min z:', b.max.z);
	var d = document.createElement('div');
	d.appendChild(document.createTextNode(s.join(' ')));
	var l = document.getElementById('hist');
	l.innerHTML = '';
	l.appendChild(d);
}*/
<commit_msg>AutoCenter needs to be on the stack<commit_after>/*
This is the defualt transformations library.
It works with the Tools API, which specifies
 */

var Hist = new Array();

// History framework
//{func: function, params: [x, y, z]}

function Trans(map){
	this.func = map['func'];
	this.params = map['params'];
	// automatically record
	this.index = this.record();
}

// calls a function
Trans.prototype.call = function(){
	this.func(this.params);
}

Trans.prototype.record = function(){
	Hist.push(this);
	return Hist.length - 1
}

Trans.prototype.toString = function(){
	var s = new Array();
	s.push(this.func.name, '(');
	var p = new Array();
	for (var i = 0; i < this.params.length; i++){
		p.push(this.params[i])
	}
	s.push(p.join(', '));
	s.push(')');
	return s.join('');
}

Trans.prototype.Set = function(){
	var s = document.createElement('p');
	s.appendChild(document.createTextNode(this.toString()));
	s.setAttribute('onclick', 'Hist['+this.index+'].call()')
	var h = document.getElementById('hist');
	h.insertBefore(s, h.firstChild);
}

// Default Transformations
var lastScale = [1.0,1.0,1.0]; // for reverting after scale
var lastRotate = [0.0,0.0,0.0];
var lastShift = [0.0, 0.0, 0.0];
var lastAutoCenter = [0.0,0.0,0.0];

// Set functions parse the
function setTrans(x, y, z, def, trans){
	if (isNaN(px = parseFloat(x))) {
		px = def;
	}
	if (isNaN(py = parseFloat(y))) {
		py = def;
	}
	if (isNaN(pz = parseFloat(z))) {
		pz = def;
	}
	var t = new Trans({
		func: trans,
		params: [px, py, pz]
	})
	t.call();
	t.Set(); // shows on page
}

function Scale(par){
	for (var i = 0; i < geometry.vertices.length; i++) {
		geometry.vertices[i].x *= (par[0]/lastScale[0]);
		geometry.vertices[i].y *= (par[1]/lastScale[1]);
		geometry.vertices[i].z *= (par[2]/lastScale[2]);
	}
	// save state
	lastScale[0] = par[0];
	lastScale[1] = par[1];
	lastScale[2] = par[2];

	geometry.verticesNeedUpdate = true;
}

function Shift(par){
	for (var i = 0; i < geometry.vertices.length; i++) {
		geometry.vertices[i].x += (par[0] - lastRotate[0]);
		geometry.vertices[i].y += (par[1] - lastRotate[1]);
		geometry.vertices[i].z += (par[2] - lastRotate[2]);
	}
	// save state
	lastShift[0] = par[0];
	lastShift[1] = par[1];
	lastShift[2] = par[2];
	geometry.verticesNeedUpdate = true;
}

function Rotate(par){
	var rotx = new THREE.Matrix4().makeRotationX(Math.PI*par[0]/180);
	var roty = new THREE.Matrix4().makeRotationY(Math.PI*par[1]/180);
	var rotz = new THREE.Matrix4().makeRotationZ(Math.PI*par[2]/180);

	geometry.applyMatrix(rotx.multiply(roty).multiply(rotz));
	lastRotate[0] = par[0];
	lastRotate[1] = par[1];
	lastRotate[2] = par[2];
	geometry.verticesNeedUpdate = true;
}

// TODO: Get this to show up on stack.
function AutoCenter(){
	geometry.computeBoundingBox ();
	var b =geometry.boundingBox;
	var lenX = (b.max.x - b.min.x)/2;
	var x = lenX - b.max.x;
	var lenY = (b.max.y - b.min.y)/2;
	var y = lenY - b.max.y;
	// do not center z, min should be 0
	var lenZ = (b.max.z - b.min.z);
	var z = (lenZ - b.max.z);
	//alert([x,y,z]);
	Shift([x,y,z]);
	// use Shift invisibly
	//var last = lastShift.slice(0);
	//setTrans(x-lastAutoCenter[0], y-lastAutoCenter[1], z-lastAutoCenter[2], 0.0, Shift);
	//lastShift = last.slice(0);
	// save
	lastAutoCenter[0] = x;
	lastAutoCenter[1] = y;
	lastAutoCenter[2] = z;
}

/*function Stats(){
	var b = cube.geometry.boundingBox;
	var s = ['Min x:', b.min.x, 'Min y:', b.min.y, 'Min z:', b.min.z];
	s.push('Max x:', b.max.x, 'Max y:', b.max.y, 'Min z:', b.max.z);
	var d = document.createElement('div');
	d.appendChild(document.createTextNode(s.join(' ')));
	var l = document.getElementById('hist');
	l.innerHTML = '';
	l.appendChild(d);
}*/
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var argscheck = cordova.require('cordova/argscheck');
var Event = require('org.chromium.chrome-common.events');
var stubs = require('org.chromium.chrome-common.stubs');
var helpers = require('org.chromium.chrome-common.helpers');

var manifestJson = null;

exports.onSuspend = new Event('onSuspend');
exports.onInstalled = new Event('onInstalled');
exports.onStartup = new Event('onStartup');
exports.onSuspendCanceled = new Event('onSuspendCanceled');
exports.onUpdateAvailable = new Event('onUpdateAvailable');
//exports.onBrowserUpdateAvailable = new Event('onBrowserUpdateAvailable');
//exports.onConnect = new Event('onConnect');
//exports.onConnectExternal = new Event('onConnectExternal');
//exports.onMessage = new Event('onMessage');
//exports.onMessageExternal = new Event('onMessageExternal');

// Uses a trampoline to bind the Cordova pause event on the first call.
var original_onSuspend_addListener = exports.onSuspend.addListener;
exports.onSuspend.addListener = function(f) {
  window.document.addEventListener('pause', function() {
    retval = exports.onSuspend.fire.apply(exports.onSuspend, arguments);
    chrome.storage.internal.set({"shutdownClean":true});
    return retval;
  }, false);
  exports.onSuspend.addListener = original_onSuspend_addListener;
  exports.onSuspend.addListener(f);
};

// Uses a trampoline to bind the Cordova resume event on the first call.
var original_onSuspendCanceled_addListener = exports.onSuspendCanceled.addListener;
exports.onSuspendCanceled.addListener = function(f) {
  window.document.addEventListener('resume', function() {
    chrome.storage.internal.remove("shutdownClean");
    return exports.onSuspendCanceled.fire.apply(exports.onSuspendCanceled, arguments);
  }, false);
  exports.onSuspendCanceled.addListener = original_onSuspendCanceled_addListener;
  exports.onSuspendCanceled.addListener(f);
};

exports.getManifest = function() {
  if (!manifestJson) {
    // May need to use origXMLHttpRequest here to access file w/o whitelist
    var xhr = new (window.origXMLHttpRequest || XMLHttpRequest)();
    xhr.open('GET', 'manifest.json', false /* sync */);
    xhr.send(null);
    manifestJson = eval('(' + xhr.responseText + ')'); //JSON.parse(xhr.responseText);
  }
  return manifestJson;
};

// This is an extension for vanilla cordova apps
exports.setManifest = function(manifest) {
  manifestJson = manifest;
  calculateAndCacheAppId();
}

exports.getBackgroundPage = function(callback) {
  try {
  var mobile = require('org.chromium.chrome-bootstrap.mobile.impl');
  } catch(e) {}
  argscheck.checkArgs('f', 'chrome.runtime.getBackgroundPage', arguments);
  setTimeout(function() {
    callback(typeof mobile !== 'undefined' ? mobile.bgWindow : undefined);
  }, 0);
};

exports.getURL = function(subResource) {
  argscheck.checkArgs('s', 'chrome.runtime.getURL', arguments);
  if (subResource.charAt(0) == '/') {
    subResource = subResource.slice(1);
  }
  var prefix = location.href.replace(/[^\/]*$/, '');
  return prefix + subResource;
};

exports.reload = function() {
  location.reload();
};

function calculateAndCacheAppId() {
  var appId;
  try {
    require('org.chromium.chrome-bootstrap.bootstrap');
    var key = exports.getManifest()['key'];
    if (typeof key === 'undefined') {
      // For development, we want a consistent ID even without a public key.  Chrome uses the app path instead of name.
      appId = helpers.mapAppNameToAppId(exports.getManifest()['name']);
    } else {
      try {
        appId = helpers.mapAppKeyToAppId(key);
      } catch (e) {
        // If you are a mobile chrome app, and you do have a key in your manifest, and its invalid, we shouldn't pretend to return a valid appId
        console.error('Your manifest file has an invalid \'key\', cannot produce application id.');
        // leaving appId undefined.
      }
    }
  } catch (e) {
    // TODO: return fully qualified name given during cordova project creation
    appId = exports.getManifest()['name'];
  }
  exports.__defineGetter__("id", function() {
    return appId;
  });
  return appId;
}
exports.__defineGetter__("id", calculateAndCacheAppId);

stubs.createStub(exports, 'requestUpdateCheck', function(){});
<commit_msg>Make chrome.runtime.getManifest() return null when no manifest exists.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var argscheck = cordova.require('cordova/argscheck');
var Event = require('org.chromium.chrome-common.events');
var stubs = require('org.chromium.chrome-common.stubs');
var helpers = require('org.chromium.chrome-common.helpers');

var manifestJson;

exports.onSuspend = new Event('onSuspend');
exports.onInstalled = new Event('onInstalled');
exports.onStartup = new Event('onStartup');
exports.onSuspendCanceled = new Event('onSuspendCanceled');
exports.onUpdateAvailable = new Event('onUpdateAvailable');
//exports.onBrowserUpdateAvailable = new Event('onBrowserUpdateAvailable');
//exports.onConnect = new Event('onConnect');
//exports.onConnectExternal = new Event('onConnectExternal');
//exports.onMessage = new Event('onMessage');
//exports.onMessageExternal = new Event('onMessageExternal');

// Uses a trampoline to bind the Cordova pause event on the first call.
var original_onSuspend_addListener = exports.onSuspend.addListener;
exports.onSuspend.addListener = function(f) {
  window.document.addEventListener('pause', function() {
    retval = exports.onSuspend.fire.apply(exports.onSuspend, arguments);
    chrome.storage.internal.set({"shutdownClean":true});
    return retval;
  }, false);
  exports.onSuspend.addListener = original_onSuspend_addListener;
  exports.onSuspend.addListener(f);
};

// Uses a trampoline to bind the Cordova resume event on the first call.
var original_onSuspendCanceled_addListener = exports.onSuspendCanceled.addListener;
exports.onSuspendCanceled.addListener = function(f) {
  window.document.addEventListener('resume', function() {
    chrome.storage.internal.remove("shutdownClean");
    return exports.onSuspendCanceled.fire.apply(exports.onSuspendCanceled, arguments);
  }, false);
  exports.onSuspendCanceled.addListener = original_onSuspendCanceled_addListener;
  exports.onSuspendCanceled.addListener(f);
};

exports.getManifest = function() {
  if (typeof manifestJson == 'undefined') {
    // May need to use origXMLHttpRequest here to access file w/o whitelist
    var xhr = new (window.origXMLHttpRequest || XMLHttpRequest)();
    xhr.open('GET', 'manifest.json', false /* sync */);
    xhr.send(null);
    if (xhr.status >= 200 && xhr.status < 300) {
      // Don't use JSON.parse, since it fails on comments.
      manifestJson = eval('(' + xhr.responseText + ')');
    } else {
      manifestJson = null;
    }
  }
  return manifestJson;
};

// This is an extension for vanilla cordova apps
exports.setManifest = function(manifest) {
  manifestJson = manifest;
  calculateAndCacheAppId();
}

exports.getBackgroundPage = function(callback) {
  try {
  var mobile = require('org.chromium.chrome-bootstrap.mobile.impl');
  } catch(e) {}
  argscheck.checkArgs('f', 'chrome.runtime.getBackgroundPage', arguments);
  setTimeout(function() {
    callback(typeof mobile !== 'undefined' ? mobile.bgWindow : undefined);
  }, 0);
};

exports.getURL = function(subResource) {
  argscheck.checkArgs('s', 'chrome.runtime.getURL', arguments);
  if (subResource.charAt(0) == '/') {
    subResource = subResource.slice(1);
  }
  var prefix = location.href.replace(/[^\/]*$/, '');
  return prefix + subResource;
};

exports.reload = function() {
  location.reload();
};

function calculateAndCacheAppId() {
  var appId;
  try {
    require('org.chromium.chrome-bootstrap.bootstrap');
    var key = exports.getManifest()['key'];
    if (typeof key === 'undefined') {
      // For development, we want a consistent ID even without a public key.  Chrome uses the app path instead of name.
      appId = helpers.mapAppNameToAppId(exports.getManifest()['name']);
    } else {
      try {
        appId = helpers.mapAppKeyToAppId(key);
      } catch (e) {
        // If you are a mobile chrome app, and you do have a key in your manifest, and its invalid, we shouldn't pretend to return a valid appId
        console.error('Your manifest file has an invalid \'key\', cannot produce application id.');
        // leaving appId undefined.
      }
    }
  } catch (e) {
    // TODO: return fully qualified name given during cordova project creation
    appId = exports.getManifest()['name'];
  }
  exports.__defineGetter__("id", function() {
    return appId;
  });
  return appId;
}
exports.__defineGetter__("id", calculateAndCacheAppId);

stubs.createStub(exports, 'requestUpdateCheck', function(){});
<|endoftext|>


<commit_before>// ==UserScript==
// @id             iitc-plugin-raw-portal-data
// @name           IITC plugin: Debug: Raw portal JSON data
// @category       Debug
// @version        0.2.2.@@DATETIMEVERSION@@
// @namespace      rawdata
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] Developer debugging aid: Adds a link to the portal details to show the raw data of a portal
// @include        https://www.ingress.com/intel*
// @include        http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

@@PLUGINSTART@@

// PLUGIN START ////////////////////////////////////////////////////////

// use own namespace for plugin
window.plugin.rawdata = function() {};

window.plugin.rawdata.setupCallback = function() {
    addHook('portalDetailsUpdated', window.plugin.rawdata.addLink);
}

window.plugin.rawdata.addLink = function(d) {
  $('.linkdetails').append('Raw Data');
}

window.plugin.rawdata.showPortalData = function(guid) {
  if (!window.portals[guid]) {
    console.warn ('Error: failed to find portal details for guid '+guid+' - failed to show debug data');
    return;
  }

  var d = window.portals[guid].options.details;
  var ts = window.portals[guid].options.timestamp;

  var title = 'Raw portal data: ' + (d.portalV2.descriptiveText.TITLE || '<no title>') + ' ('+guid+')';

  var body =
    'Portal GUID: '+guid+'
' +
    'Entity timestamp: '+ts+' - '+window.unixTimeToDateTimeString(ts,true)+'
' +
    '
'+JSON.stringify(d,null,2)+'
';

  body += '
Links referencing this portal
';
  var haslinks = false;
  for (var lguid in window.links) {
    var l = window.links[lguid];
    var ld = l.options.details;
    if (ld.edge.originPortalGuid == guid || ld.edge.destinationPortalGuid == guid) {
      body += 'Link GUID: '+l.options.guid+'

'+JSON.stringify(ld,null,2)+'
';
      haslinks = true;
    }
  }
  if (!haslinks) body += '
No links to/from this portal
';

  body += '
Fields referencing this portal
';
  var hasfields = false;
  for (var fguid in window.fields) {
    var f = window.fields[fguid];
    var fd = f.options.details;
    if (fd.capturedRegion.vertexA.guid == guid ||
        fd.capturedRegion.vertexB.guid == guid ||
        fd.capturedRegion.vertexC.guid == guid) {
      body += 'Field guid: '+f.options.guid+'

'+JSON.stringify(fd,null,2)+'
';
      hasfields = true;
    }
  }
  if (!hasfields) body += '
No fields linked to this portal
';

  dialog({
    title: title,
    html: body,
    id: 'dialog-rawdata',
    dialogClass: 'ui-dialog-rawdata',
  });
}

var setup = function () {
  window.plugin.rawdata.setupCallback();
  $('head').append('');
}

// PLUGIN END //////////////////////////////////////////////////////////

@@PLUGINEND@@
<commit_msg>plugin: debug-raw-data fixed<commit_after>// ==UserScript==
// @id             iitc-plugin-raw-portal-data
// @name           IITC plugin: Debug: Raw portal JSON data
// @category       Debug
// @version        0.2.3.@@DATETIMEVERSION@@
// @namespace      rawdata
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] Developer debugging aid: Adds a link to the portal details to show the raw data of a portal
// @include        https://www.ingress.com/intel*
// @include        http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

@@PLUGINSTART@@

// PLUGIN START ////////////////////////////////////////////////////////

// use own namespace for plugin
window.plugin.rawdata = function() {};

window.plugin.rawdata.setupCallback = function() {
    addHook('portalDetailsUpdated', window.plugin.rawdata.addLink);
}

window.plugin.rawdata.addLink = function(d) {
  $('.linkdetails').append('Raw Data');
}

window.plugin.rawdata.showPortalData = function(guid) {
  if (!window.portals[guid]) {
    console.warn ('Error: failed to find portal details for guid '+guid+' - failed to show debug data');
    return;
  }

  var data = window.portals[guid].options.data;
  var ts = window.portals[guid].options.timestamp;

  var title = 'Raw portal data: ' + (data.title || '<no title>') + ' ('+guid+')';

  var body =
    'Portal GUID: '+guid+'
' +
    'Entity timestamp: '+ts+' - '+window.unixTimeToDateTimeString(ts,true)+'
' +
    '
'+JSON.stringify(data,null,2)+'
';

  var details = portalDetail.get(guid);
  if (details) {
    body += 'Portal details:
'+JSON.stringify(details,null,2)+'
';
  }

  body += '
Links referencing this portal
';
  var haslinks = false;
  var linkGuids = getPortalLinks(guid);
  $.each(linkGuids.in.concat(linkGuids.out), function(i,lguid) {
    var l = window.links[lguid];
    var ld = l.options.data;
    body += 'Link GUID: '+l.options.guid+'

'+JSON.stringify(ld,null,2)+'
';
    haslinks = true;
  });

  if (!haslinks) body += '
No links to/from this portal
';

  body += '
Fields referencing this portal
';
  var hasfields = false;
  var fieldGuids = getPortalFields(guid);
  $.each(fieldGuids, function(i,fguid) {
    var f = window.fields[fguid];
    var fd = f.options.data;
    body += 'Field guid: '+f.options.guid+'

'+JSON.stringify(fd,null,2)+'
';
    hasfields = true;
  });
  if (!hasfields) body += '
No fields linked to this portal
';

  dialog({
    title: title,
    html: body,
    id: 'dialog-rawdata',
    dialogClass: 'ui-dialog-rawdata',
  });
}

var setup = function () {
  window.plugin.rawdata.setupCallback();
  $('head').append('');
}

// PLUGIN END //////////////////////////////////////////////////////////

@@PLUGINEND@@
<|endoftext|>


<commit_before><commit_msg>site-search: fix bug with variable shadowing<commit_after><|endoftext|>


<commit_before><commit_msg>Small fix: Removed unnecessary export from Zebra Puzzle exercise (#1652)<commit_after><|endoftext|>


<commit_before><commit_msg>bf: ZENKO-343 adapt lifecycle qp extension for mongo<commit_after><|endoftext|>


<commit_before><commit_msg>Lint fix<commit_after><|endoftext|>


<commit_before>var Dijkstra = (function () {

     /**
     * A class for calculations on graphs using Dijkstra's algorithm.
     * @constructor
     */
    function Dijkstra(graph) {
        this.graph = graph;
    }

    // Private sort delegate for ordering key value pairs arranged
    // as an array of two items like [key, value].
    var keyValueSorter = function(kv1, kv2) {
        return parseFloat(kv1[1]) - parseFloat(kv2[1]);
    }

     /**
     * Calculate the shortest path between two nodes in a graph using
     * Dijkstra's Algorithm.
     * @param {String} source
     * @param {String} target
     * @return {Array} An array of node names corresponding to the path
     */
    Dijkstra.prototype.shortestPath = function (source, target, weight) {
        if (source === target) {
            return [source];
        }

        var touchedNodes = {};
        var previous = {};
        var distances = {};
        var visited = {};

        touchedNodes[source] = 0;
        previous[source] = undefined;
        distances[source] = 0;

        while (true) {
            var touched = [];
            for (var key in touchedNodes) {
                if (Object.prototype.hasOwnProperty.call(touchedNodes, key)) {
                    touched.push([key, touchedNodes[key]])
                }
            }

            // Stop if none of the unvisited nodes can be reached.
            if (!touched.length) {
                break;
            }

            // Select the unvisited node with smallest distance and mark it as current node.
            touched.sort(keyValueSorter);
            var currentNode = touched[0][0];

            visited[currentNode] = true;
            delete touchedNodes[currentNode];

            // Return if we have reached the target.
            if (currentNode === target) {
                break;
            }

            var currentEdges = this.graph.edges[currentNode] || {};

            for (var node in currentEdges) {
                if (Object.prototype.hasOwnProperty.call(currentEdges, node)) {

                    // Do not process already visited nodes.
                    if (Object.prototype.hasOwnProperty.call(visited, node)) {
                        continue;
                    }

                    // Calculate the total distance from the source to the node of
                    // the current edge.
                    var distance = currentEdges[node][weight];
                    var totalDistance = distances[currentNode] + distance;

                    if (!distances[node] || totalDistance < distances[node])
                    {
                        distances[node] = totalDistance;
                        touchedNodes[node] = totalDistance;
                        previous[node] = currentNode;
                    }
                }
            }
        }

        // No path to the target was found.
        if (previous[target] === undefined) {
            return null;
        }

        // Retrieve a path from the dictionary of previous nodes and reverse it.
        var reversePath = [];
        var element = target;
        while (element !== undefined) {
            reversePath.push(element);
            element = previous[element];
        }

        return reversePath.reverse();
    }

    return Dijkstra;
})();

var Journey = (function () {

    /**
     * A journey.
     * @constructor
     * @param {String} graphs A list of graphs.
     * @param {String} intervalTime The maximum time between navigation.
     * @param {String} navigationAction The action to execute on navigation.
     * @param {String} startAction The action to run when starting a journey.
     * @param {String} stopAction The action to run when stopping a journey.
     * @param {String} usePenalty Boolean indicating if a penalty should be used.
     */
    function Journey(graphs, intervalTime, navigationAction, startAction, stopAction, usePenalty) {
        this.graphs = graphs;
        this.intervalTime = intervalTime;
        this.navigationAction = navigationAction;
        this.startAction = startAction;
        this.stopAction = stopAction;
        this.usePenalty = usePenalty;
        this.timeoutToken = undefined;
        this.path = undefined;
        this.currentIndex = 0;
        this.started = false;
    }

    // Private callback function for setInterval.
    var onMove = function(self) {
        var pathLength = self.path.length;
        self.currentIndex++;

        if (self.started !== true || self.currentIndex >= pathLength) {
            self.stop();
            return;
        }

        self.navigationAction(self.path[self.currentIndex]);

        if (self.currentIndex === pathLength - 1) {
            self.stop();
            return;
        }

        self.timeoutToken = window.setTimeout(function () { onMove(self); }, self.intervalTime);
    }

    // Private function for creating a graph with a penalty for a certain property with
    // a certain value.
    var getPenaltyGraph = function(graph, edgesKey, weightKey, originalWeightKey, penaltyKey, penaltyValue, penalty) {

        var penaltyGraph = {};
        penaltyGraph[edgesKey] = {};

        for (var k in graph[edgesKey]) {
            if (Object.prototype.hasOwnProperty.call(graph[edgesKey], k)) {

                penaltyGraph[edgesKey][k] = {};
                var edges = graph[edgesKey][k];

                for (var m in edges) {
                    if (Object.prototype.hasOwnProperty.call(edges, m)) {
                        penaltyGraph[edgesKey][k][m] = {};

                        // Add penalty to weight if the value of the penalty key corresponds
                        // to the specified penalty value.
                        if (edges[m][penaltyKey] === penaltyValue) {
                            penaltyGraph[edgesKey][k][m][weightKey] = edges[m][weightKey] + penalty;
                        }
                        else {
                            penaltyGraph[edgesKey][k][m][weightKey] = edges[m][weightKey];
                        }

                        penaltyGraph[edgesKey][k][m][originalWeightKey] = edges[m][weightKey];
                    }
                }
            }
        }

        return penaltyGraph;
    }

    /**
     * Sets the interval time.
     * @param {Integer} intervalTime
     */
    Journey.prototype.updateInterval = function (intervalTime) {
        this.intervalTime = intervalTime;
    }

     /**
     * Gets a value indicating whether a journey is ongoing.
     * @return {Boolean} A value indicating whether a journey is ongoing.
     */
    Journey.prototype.isStarted = function() {
        return this.started;
    }

    /**
     * Calculate the shortest path between two nodes in a graph.
     * @param {String} from
     * @param {String} to
     * @return {Array} An array of node names corresponding to the path
     */
    Journey.prototype.shortestPath = function (from, to) {
        var journeyGraph = undefined;
        for (var k in this.graphs) {
            if (Object.prototype.hasOwnProperty.call(this.graphs, k)) {
                // Ensure that both nodes exist in the graph.
                if (this.graphs[k].nodes.indexOf(from) > -1 &&
                    this.graphs[k].nodes.indexOf(to) > -1) {
                    journeyGraph = this.graphs[k];
                    break;
                }
            }
        }

        if (journeyGraph === undefined) {
            return undefined;
        }

        if (this.usePenalty === true) {
            journeyGraph = getPenaltyGraph(journeyGraph, 'edges', 'weight', 'distance', 'direction', 'step_backward', 20);
        }

        var dijkstra = new Dijkstra(journeyGraph);
        var path = dijkstra.shortestPath(from, to, 'weight');

        return path;
    }

    /**
     * Starts a journey between two nodes in a graph.
     * @param {Number} from
     * @param {Number} to
     */
    Journey.prototype.start = function (from, to) {
        if (this.started === true) {
            return;
        }

        this.path = this.shortestPath(from, to);
        if (this.path === null) {
            return;
        }

        this.started = true;
        this.currentIndex = 0;
        this.startAction();
        this.navigationAction(this.path[this.currentIndex])

        var _this = this;
        this.timeoutToken = window.setTimeout(function () { onMove(_this); }, this.intervalTime);
    }

    /**
     * Stops an ongoing journey between two nodes in a graph.
     */
    Journey.prototype.stop = function () {
        if (this.timeoutToken === undefined) {
            return;
        }

        window.clearTimeout(this.timeoutToken);
        this.timeoutToken = undefined;
        this.currentIndex = 0;
        this.path = undefined;

        this.stopAction();

        this.started = false;
    }

    return Journey;
})();

var JourneyWrapper = (function ($) {

    /**
     * A journey wrapper.
     * @constructor
     */
    function JourneyWrapper() {
        this.initialized = false;
        this.journey = undefined;
        this.destination = undefined;
    }

    var getInterval = function () {
        var interval = undefined;
        if (controls.animationSpeed === 0) {
            interval = 3 * 1000;
        }
        else {
            interval = (3 - 10 * (controls.animationSpeed)) * 1000;
        }

        return interval;
    }

    var navigation = function (shot_id) {
        var camera = undefined;
        for (var i = 0; i < camera_lines.length; ++i) {
            if (camera_lines[i].shot_id === shot_id) {
                camera = camera_lines[i];
            }
        }

        if (camera === undefined) {
            return;
        }

        setImagePlaneCamera(camera);
        navigateToShot(camera);
    }

    var start = function () {
        setMovingMode('walk');
        $('#journeyButton').html('X');
    }

    var stop = function () {
        $('#journeyButton').html('Go');
    }

    /**
     * Initializes a journey wrapper.
     */
    JourneyWrapper.prototype.initialize = function () {
        if ('graph' in urlParams && 'dest' in urlParams) {

            this.destination = urlParams.dest;
            var _this = this;

            jQuery.getJSON(urlParams.graph, function(data) {

                _this.journey =
                    new Journey(
                        data,
                        getInterval(),
                        navigation,
                        start,
                        stop,
                        true);

                _this.initialized = true;
                $('#journeyButton').show();

                if ('img' in urlParams && selectedCamera !== undefined) {
                    _this.toggleJourney();
                }
            });
        }
    }

    /**
     * Updates the interval.
     */
    JourneyWrapper.prototype.updateInterval = function () {
        if (this.initialized !== true){
            return;
        }

        this.journey.updateInterval(getInterval());
    }

    /**
     * Toggles the journey state between started and stopped.
     */
    JourneyWrapper.prototype.toggleJourney = function () {
        if (this.initialized !== true){
            return;
        }

        if (this.journey.isStarted() === true) {
            this.journey.stop();
            return;
        }

        if (selectedCamera === undefined) {
            return;
        }

        this.journey.updateInterval(getInterval());
        this.journey.start(selectedCamera.shot_id, this.destination);
    }

    return JourneyWrapper;
})(jQuery);

var journeyWrapper = new JourneyWrapper();

<commit_msg>Adding stop function in journey wrapper.<commit_after>var Dijkstra = (function () {

     /**
     * A class for calculations on graphs using Dijkstra's algorithm.
     * @constructor
     */
    function Dijkstra(graph) {
        this.graph = graph;
    }

    // Private sort delegate for ordering key value pairs arranged
    // as an array of two items like [key, value].
    var keyValueSorter = function(kv1, kv2) {
        return parseFloat(kv1[1]) - parseFloat(kv2[1]);
    }

     /**
     * Calculate the shortest path between two nodes in a graph using
     * Dijkstra's Algorithm.
     * @param {String} source
     * @param {String} target
     * @return {Array} An array of node names corresponding to the path
     */
    Dijkstra.prototype.shortestPath = function (source, target, weight) {
        if (source === target) {
            return [source];
        }

        var touchedNodes = {};
        var previous = {};
        var distances = {};
        var visited = {};

        touchedNodes[source] = 0;
        previous[source] = undefined;
        distances[source] = 0;

        while (true) {
            var touched = [];
            for (var key in touchedNodes) {
                if (Object.prototype.hasOwnProperty.call(touchedNodes, key)) {
                    touched.push([key, touchedNodes[key]])
                }
            }

            // Stop if none of the unvisited nodes can be reached.
            if (!touched.length) {
                break;
            }

            // Select the unvisited node with smallest distance and mark it as current node.
            touched.sort(keyValueSorter);
            var currentNode = touched[0][0];

            visited[currentNode] = true;
            delete touchedNodes[currentNode];

            // Return if we have reached the target.
            if (currentNode === target) {
                break;
            }

            var currentEdges = this.graph.edges[currentNode] || {};

            for (var node in currentEdges) {
                if (Object.prototype.hasOwnProperty.call(currentEdges, node)) {

                    // Do not process already visited nodes.
                    if (Object.prototype.hasOwnProperty.call(visited, node)) {
                        continue;
                    }

                    // Calculate the total distance from the source to the node of
                    // the current edge.
                    var distance = currentEdges[node][weight];
                    var totalDistance = distances[currentNode] + distance;

                    if (!distances[node] || totalDistance < distances[node])
                    {
                        distances[node] = totalDistance;
                        touchedNodes[node] = totalDistance;
                        previous[node] = currentNode;
                    }
                }
            }
        }

        // No path to the target was found.
        if (previous[target] === undefined) {
            return null;
        }

        // Retrieve a path from the dictionary of previous nodes and reverse it.
        var reversePath = [];
        var element = target;
        while (element !== undefined) {
            reversePath.push(element);
            element = previous[element];
        }

        return reversePath.reverse();
    }

    return Dijkstra;
})();

var Journey = (function () {

    /**
     * A journey.
     * @constructor
     * @param {String} graphs A list of graphs.
     * @param {String} intervalTime The maximum time between navigation.
     * @param {String} navigationAction The action to execute on navigation.
     * @param {String} startAction The action to run when starting a journey.
     * @param {String} stopAction The action to run when stopping a journey.
     * @param {String} usePenalty Boolean indicating if a penalty should be used.
     */
    function Journey(graphs, intervalTime, navigationAction, startAction, stopAction, usePenalty) {
        this.graphs = graphs;
        this.intervalTime = intervalTime;
        this.navigationAction = navigationAction;
        this.startAction = startAction;
        this.stopAction = stopAction;
        this.usePenalty = usePenalty;
        this.timeoutToken = undefined;
        this.path = undefined;
        this.currentIndex = 0;
        this.started = false;
    }

    // Private callback function for setInterval.
    var onMove = function(self) {
        var pathLength = self.path.length;
        self.currentIndex++;

        if (self.started !== true || self.currentIndex >= pathLength) {
            self.stop();
            return;
        }

        self.navigationAction(self.path[self.currentIndex]);

        if (self.currentIndex === pathLength - 1) {
            self.stop();
            return;
        }

        self.timeoutToken = window.setTimeout(function () { onMove(self); }, self.intervalTime);
    }

    // Private function for creating a graph with a penalty for a certain property with
    // a certain value.
    var getPenaltyGraph = function(graph, edgesKey, weightKey, originalWeightKey, penaltyKey, penaltyValue, penalty) {

        var penaltyGraph = {};
        penaltyGraph[edgesKey] = {};

        for (var k in graph[edgesKey]) {
            if (Object.prototype.hasOwnProperty.call(graph[edgesKey], k)) {

                penaltyGraph[edgesKey][k] = {};
                var edges = graph[edgesKey][k];

                for (var m in edges) {
                    if (Object.prototype.hasOwnProperty.call(edges, m)) {
                        penaltyGraph[edgesKey][k][m] = {};

                        // Add penalty to weight if the value of the penalty key corresponds
                        // to the specified penalty value.
                        if (edges[m][penaltyKey] === penaltyValue) {
                            penaltyGraph[edgesKey][k][m][weightKey] = edges[m][weightKey] + penalty;
                        }
                        else {
                            penaltyGraph[edgesKey][k][m][weightKey] = edges[m][weightKey];
                        }

                        penaltyGraph[edgesKey][k][m][originalWeightKey] = edges[m][weightKey];
                    }
                }
            }
        }

        return penaltyGraph;
    }

    /**
     * Sets the interval time.
     * @param {Integer} intervalTime
     */
    Journey.prototype.updateInterval = function (intervalTime) {
        this.intervalTime = intervalTime;
    }

     /**
     * Gets a value indicating whether a journey is ongoing.
     * @return {Boolean} A value indicating whether a journey is ongoing.
     */
    Journey.prototype.isStarted = function() {
        return this.started;
    }

    /**
     * Calculate the shortest path between two nodes in a graph.
     * @param {String} from
     * @param {String} to
     * @return {Array} An array of node names corresponding to the path
     */
    Journey.prototype.shortestPath = function (from, to) {
        var journeyGraph = undefined;
        for (var k in this.graphs) {
            if (Object.prototype.hasOwnProperty.call(this.graphs, k)) {
                // Ensure that both nodes exist in the graph.
                if (this.graphs[k].nodes.indexOf(from) > -1 &&
                    this.graphs[k].nodes.indexOf(to) > -1) {
                    journeyGraph = this.graphs[k];
                    break;
                }
            }
        }

        if (journeyGraph === undefined) {
            return undefined;
        }

        if (this.usePenalty === true) {
            journeyGraph = getPenaltyGraph(journeyGraph, 'edges', 'weight', 'distance', 'direction', 'step_backward', 20);
        }

        var dijkstra = new Dijkstra(journeyGraph);
        var path = dijkstra.shortestPath(from, to, 'weight');

        return path;
    }

    /**
     * Starts a journey between two nodes in a graph.
     * @param {Number} from
     * @param {Number} to
     */
    Journey.prototype.start = function (from, to) {
        if (this.started === true) {
            return;
        }

        this.path = this.shortestPath(from, to);
        if (this.path === null) {
            return;
        }

        this.started = true;
        this.currentIndex = 0;
        this.startAction();
        this.navigationAction(this.path[this.currentIndex])

        var _this = this;
        this.timeoutToken = window.setTimeout(function () { onMove(_this); }, this.intervalTime);
    }

    /**
     * Stops an ongoing journey between two nodes in a graph.
     */
    Journey.prototype.stop = function () {
        if (this.timeoutToken === undefined) {
            return;
        }

        window.clearTimeout(this.timeoutToken);
        this.timeoutToken = undefined;
        this.currentIndex = 0;
        this.path = undefined;

        this.stopAction();

        this.started = false;
    }

    return Journey;
})();

var JourneyWrapper = (function ($) {

    /**
     * A journey wrapper.
     * @constructor
     */
    function JourneyWrapper() {
        this.initialized = false;
        this.journey = undefined;
        this.destination = undefined;
    }

    var getInterval = function () {
        var interval = undefined;
        if (controls.animationSpeed === 0) {
            interval = 3 * 1000;
        }
        else {
            interval = (3 - 10 * (controls.animationSpeed)) * 1000;
        }

        return interval;
    }

    var navigation = function (shot_id) {
        var camera = undefined;
        for (var i = 0; i < camera_lines.length; ++i) {
            if (camera_lines[i].shot_id === shot_id) {
                camera = camera_lines[i];
            }
        }

        if (camera === undefined) {
            return;
        }

        setImagePlaneCamera(camera);
        navigateToShot(camera);
    }

    var start = function () {
        setMovingMode('walk');
        $('#journeyButton').html('X');
    }

    var stop = function () {
        $('#journeyButton').html('Go');
    }

    /**
     * Initializes a journey wrapper.
     */
    JourneyWrapper.prototype.initialize = function () {
        if ('graph' in urlParams && 'dest' in urlParams) {

            this.destination = urlParams.dest;
            var _this = this;

            jQuery.getJSON(urlParams.graph, function(data) {

                _this.journey =
                    new Journey(
                        data,
                        getInterval(),
                        navigation,
                        start,
                        stop,
                        true);

                _this.initialized = true;
                $('#journeyButton').show();

                if ('img' in urlParams && selectedCamera !== undefined) {
                    _this.toggleJourney();
                }
            });
        }
    }

    /**
     * Updates the interval.
     */
    JourneyWrapper.prototype.updateInterval = function () {
        if (this.initialized !== true){
            return;
        }

        this.journey.updateInterval(getInterval());
    }

    /**
     * Stops a journey.
     */
    JourneyWrapper.prototype.stop = function () {
        if (this.initialized !== true){
            return;
        }

        if (this.journey.isStarted() === true) {
            this.journey.stop();
        }
    }

    /**
     * Toggles the journey state between started and stopped.
     */
    JourneyWrapper.prototype.toggleJourney = function () {
        if (this.initialized !== true){
            return;
        }

        if (this.journey.isStarted() === true) {
            this.journey.stop();
            return;
        }

        if (selectedCamera === undefined) {
            return;
        }

        this.journey.updateInterval(getInterval());
        this.journey.start(selectedCamera.shot_id, this.destination);
    }

    return JourneyWrapper;
})(jQuery);

var journeyWrapper = new JourneyWrapper();

<|endoftext|>


<commit_before>/* global ares */
/**
 * This kind provide a widget to tune global properties
 */

enyo.kind({
	name: "AresProperties",
	classes: "enyo-unselectable ares-classic-popup",
	kind:"onyx.Popup",
	fit: true,
	modal: true, centered: true, floating: true, autoDismiss: false,
	events: {
		onModifiedConfig: "",
		onSaveGeneratedXml: "",
		onDone: ""
	},

	components: [
		{classes:"title left-align", components:[
			{kind: "onyx.RadioGroup", onActivate: "switchDrawers", name: "thumbnail", classes:"ares-radio-group", components: []}
		]},
		{kind: "onyx.Toolbar", name: "toolbarId", classes:"bottom-toolbar", components: [
			{name: "ok", classes:"right", kind: "onyx.Button", content: "OK", ontap: "confirmTap"}
		]},
		{kind: "Signals", onPluginRegist: "handlePluginRegist"}
	],

	debug: false,

	/**
	 * @protected
	 */
	create: function() {
		ares.setupTraceLogger(this);
		this.inherited(arguments);
		this.createAresAboutDrawer();
	},

	/**
	 * @private
	 */
	createAresAboutDrawer: function() {
		var aresAboutTabEntry = {
			id: "aresAbout",
			name: "Ares",
			kind: "AboutAresPanel",
			components:[{content:"Ares", classes:"large-fixed"},{tag:"span", classes:"ares-bottom-check"}]
		};
		this.createComponentTab(aresAboutTabEntry);
	},

	/**
	 * Create a tab to display basic informations about Ares or embeeded plugins
	 *
	 * @param  {Object} inTabEntry object that define the name of the tab thumbnail & drawer
	 *                             and the kind of the tab panel.
	 * @private
	 */
	createComponentTab: function(inTabEntry) {
		var drawer = this.createComponent({
			name: inTabEntry.id + 'Drawer',
			kind: "onyx.Drawer",
			open: false
		},{addBefore: this.$.toolbarId});

		inTabEntry.panel = drawer.createComponent({
			name: inTabEntry.id,
			kind: inTabEntry.kind
		});

		inTabEntry.tab = this.$.thumbnail.createComponent({
			name: inTabEntry.id + 'Tab',
			content: inTabEntry.name,
			componentId: inTabEntry.id,
			showing: true,
			active: true,
			components:inTabEntry.components
		});
	},

	/**
	 * Receive the {onPluginRegist} broadcast notification
	 * @param {Object} inEvent.pluginService
	 */
	handlePluginRegist: function(inSender, inEvent) {
		this.trace("");

		if (typeof inEvent.pluginService.getAresPropertiesKind !== 'function') {
			return true;
		}

		var pluginService = {
			id: inEvent.pluginService.id,
			name: inEvent.pluginService.getName() || inEvent.pluginService.id,
			kind: inEvent.pluginService.getAresPropertiesKind()
		};
		this.createComponentTab(pluginService);
	},

	// /**
	//  * close one drawer and open the other depending on which radio button was tapped
	//  */
	switchDrawers: function(inSender, inEvent) {
		if (inEvent.originator.active === true ) {
			enyo.forEach(inEvent.originator.parent.children, function(tab) {
				var activate = (tab.componentId === inEvent.originator.componentId);
				this.$[tab.componentId + 'Drawer'].setOpen(activate);
			}, this);
		}
	},

	confirmTap: function(inSender, inEvent) {
		this.hide();
	}

});

enyo.kind({
	name: "AboutAresPanel",
	kind: "enyo.Scroller",
	fit: "true",
	classes: "ares-about-drawer",
	published: {
		config: {},
		aboutAresData: undefined
	},
	events: {
		onError: ""
	},
	components: [
		{name: "errorMessage", content: "Error: Unable to load Ares About data from Ares IDE Server", showing: false},
		{
			kind: "FittableRows",
			name: "aboutDescription",
				components: [
					{
						kind:"FittableColumns",
						components: [
							{content: "Ares version: ", classes: "ares-about-description"},
							{name: "versionValue"}
						]
					},
					{
						kind:"FittableColumns",
						components: [
							{content: "In case of issue, please consider ", classes: "ares-about-description"},
							{name: "brValue", kind: "enyo.Control", tag: "a", content: "Reporting a bug", attributes: {"target": "_blank"}}
						]
					},
					{
						kind:"FittableColumns",
						components: [
							{content: "See ", classes: "ares-about-description"},
							{name: "homeValue", kind: "enyo.Control", tag: "a", content: "Project Homepage", attributes: {"target": "_blank"}}
						]
					},
					{
						kind:"FittableColumns",
						components: [
							{content: "License: ", classes: "ares-about-description"},
							{name: "license", classes: "ares-about-description"}
						]
					}
				]
		}
	],

	/**
	 * private
	 */
	create: function(){
		this.inherited(arguments);
		this.reqAboutAresData();

	},

	/**
	 * Send an AJAX request to the  Backend in order to get the needed data for the Ares description.
	 * @rprivate
	 */
	reqAboutAresData: function(){
		var origin = window.location.origin || window.location.protocol + "//" + window.location.host; // Webkit/FF vs IE

		var req = new enyo.Ajax({
			url: origin + '/res/aboutares'
		});

		req.response(this, function(inSender, inData) {
			this.setAboutAresData(inData.aboutAres);
		});

		//Show the error in a Pop-up.
		req.error(this, function(inSender, inError){

			this.doError({msg: "("+inError +") Unable to load Ares About data", err: inError});
			this.$.errorMessage.show();
			this.$.aboutDescription.hide();
		});

		req.go();
	},

	/**
	 * @private
	 */
	aboutAresDataChanged: function(){
		this.$.versionValue.content = this.aboutAresData.version;
		this.$.brValue.setAttribute("href", this.aboutAresData.bugReportURL);
		this.$.homeValue.setAttribute("href", this.aboutAresData.projectHomePage);
		this.$.license.content = this.aboutAresData.license;
	}
});
<commit_msg>ENYO-2795: fix jsdoc & do not inline the detailed error message twice<commit_after>/* global ares */
/**
 * This kind provide a widget to tune global properties
 */

enyo.kind({
	name: "AresProperties",
	classes: "enyo-unselectable ares-classic-popup",
	kind:"onyx.Popup",
	fit: true,
	modal: true, centered: true, floating: true, autoDismiss: false,
	events: {
		onModifiedConfig: "",
		onSaveGeneratedXml: "",
		onDone: ""
	},

	components: [
		{classes:"title left-align", components:[
			{kind: "onyx.RadioGroup", onActivate: "switchDrawers", name: "thumbnail", classes:"ares-radio-group", components: []}
		]},
		{kind: "onyx.Toolbar", name: "toolbarId", classes:"bottom-toolbar", components: [
			{name: "ok", classes:"right", kind: "onyx.Button", content: "OK", ontap: "confirmTap"}
		]},
		{kind: "Signals", onPluginRegist: "handlePluginRegist"}
	],

	debug: false,

	/**
	 * @protected
	 */
	create: function() {
		ares.setupTraceLogger(this);
		this.inherited(arguments);
		this.createAresAboutDrawer();
	},

	/**
	 * @private
	 */
	createAresAboutDrawer: function() {
		var aresAboutTabEntry = {
			id: "aresAbout",
			name: "Ares",
			kind: "AboutAresPanel",
			components:[{content:"Ares", classes:"large-fixed"},{tag:"span", classes:"ares-bottom-check"}]
		};
		this.createComponentTab(aresAboutTabEntry);
	},

	/**
	 * Create a tab to display basic informations about Ares or embeeded plugins
	 *
	 * @param  {Object} inTabEntry object that define the name of the tab thumbnail & drawer
	 *                             and the kind of the tab panel.
	 * @private
	 */
	createComponentTab: function(inTabEntry) {
		var drawer = this.createComponent({
			name: inTabEntry.id + 'Drawer',
			kind: "onyx.Drawer",
			open: false
		},{addBefore: this.$.toolbarId});

		inTabEntry.panel = drawer.createComponent({
			name: inTabEntry.id,
			kind: inTabEntry.kind
		});

		inTabEntry.tab = this.$.thumbnail.createComponent({
			name: inTabEntry.id + 'Tab',
			content: inTabEntry.name,
			componentId: inTabEntry.id,
			showing: true,
			active: true,
			components:inTabEntry.components
		});
	},

	/**
	 * Receive the {onPluginRegist} broadcast notification
	 * @param {Object} inEvent.pluginService
	 */
	handlePluginRegist: function(inSender, inEvent) {
		this.trace("");

		if (typeof inEvent.pluginService.getAresPropertiesKind !== 'function') {
			return true;
		}

		var pluginService = {
			id: inEvent.pluginService.id,
			name: inEvent.pluginService.getName() || inEvent.pluginService.id,
			kind: inEvent.pluginService.getAresPropertiesKind()
		};
		this.createComponentTab(pluginService);
	},

	// /**
	//  * close one drawer and open the other depending on which radio button was tapped
	//  */
	switchDrawers: function(inSender, inEvent) {
		if (inEvent.originator.active === true ) {
			enyo.forEach(inEvent.originator.parent.children, function(tab) {
				var activate = (tab.componentId === inEvent.originator.componentId);
				this.$[tab.componentId + 'Drawer'].setOpen(activate);
			}, this);
		}
	},

	confirmTap: function(inSender, inEvent) {
		this.hide();
	}

});

enyo.kind({
	name: "AboutAresPanel",
	kind: "enyo.Scroller",
	fit: "true",
	classes: "ares-about-drawer",
	published: {
		config: {},
		aboutAresData: undefined
	},
	events: {
		onError: ""
	},
	components: [
		{name: "errorMessage", content: "Error: Unable to load Ares About data from Ares IDE Server", showing: false},
		{
			kind: "FittableRows",
			name: "aboutDescription",
				components: [
					{
						kind:"FittableColumns",
						components: [
							{content: "Ares version: ", classes: "ares-about-description"},
							{name: "versionValue"}
						]
					},
					{
						kind:"FittableColumns",
						components: [
							{content: "In case of issue, please consider ", classes: "ares-about-description"},
							{name: "brValue", kind: "enyo.Control", tag: "a", content: "Reporting a bug", attributes: {"target": "_blank"}}
						]
					},
					{
						kind:"FittableColumns",
						components: [
							{content: "See ", classes: "ares-about-description"},
							{name: "homeValue", kind: "enyo.Control", tag: "a", content: "Project Homepage", attributes: {"target": "_blank"}}
						]
					},
					{
						kind:"FittableColumns",
						components: [
							{content: "License: ", classes: "ares-about-description"},
							{name: "license", classes: "ares-about-description"}
						]
					}
				]
		}
	],

	/**
	 * @protected
	 */
	create: function(){
		this.inherited(arguments);
		this.reqAboutAresData();

	},

	/**
	 * Send an AJAX request to the  Backend in order to get the needed data for the Ares description.
	 * @private
	 */
	reqAboutAresData: function(){
		var origin = window.location.origin || window.location.protocol + "//" + window.location.host; // Webkit/FF vs IE

		var req = new enyo.Ajax({
			url: origin + '/res/aboutares'
		});

		req.response(this, function(inSender, inData) {
			this.setAboutAresData(inData.aboutAres);
		});

		//Show the error in a Pop-up.
		req.error(this, function(inSender, inError){

			this.doError({msg: "Unable to load data about Ares", err: inError});
			this.$.errorMessage.show();
			this.$.aboutDescription.hide();
		});

		req.go();
	},

	/**
	 * @private
	 */
	aboutAresDataChanged: function(){
		this.$.versionValue.content = this.aboutAresData.version;
		this.$.brValue.setAttribute("href", this.aboutAresData.bugReportURL);
		this.$.homeValue.setAttribute("href", this.aboutAresData.projectHomePage);
		this.$.license.content = this.aboutAresData.license;
	}
});
<|endoftext|>


<commit_before><commit_msg>Fixed bug in which undefined check was missing and causing json parsing errors.<commit_after><|endoftext|>


<commit_before>require('dotenv').config();

const express = require('express');
//const cors = require('cors');
const { MongoClient } = require("mongodb");
const share = express();

// parse incoming POST requests body to JSON
share.use(express.json());
//// handle CORS
//share.use(cors())
share.set('view engine', 'pug')

// handle GET requests
share.get('/', context => {
  if (context.query.request) {
    switch (context.query.request.toLowerCase()) {

      case 'load':
        getCompositionRecord(context.query.id, context);
        break;

      case 'socialshare':
        getSocialShareRecord(context.query.id, context);
        break;

      default:
        formatResponseJson({ success: false, error: "Request not specified" }, context);
        break;
    }
  }
  else {
    context.res.send('HSLayers map share service');
  }
});

// handle POST requests
share.post('/', context => {
  if (context.body && context.body.request) {
    switch (context.body.request.toLowerCase()) {
      case 'save':
        insertRecord("composition", {
          id: context.body.id,
          data: context.body.data
        }, context);
        break;

      case 'socialshare':
        insertRecord("socialShare", {
          id: context.body.id,
          url: context.body.url,
          title: context.body.title,
          description: context.body.description,
          image: context.body.image
        }, context);
        break;

      default:
        formatResponseJson({ success: false, error: "Request not specified" }, context);
    }
  }
  else {

  }
});

// start the service on the port xxxx
share.listen(3000, () => console.log('HSLayers map share service listening on port 3000...'));

/**
 * Find composition by its ID and return it as JSON
 * @param {any} id ID of the composition to look for
 * @param {any} context HTTP context of the request
 */
async function getCompositionRecord(id, context) {
  await queryCollection("composition", { id: id }, function (result, success) {
    if (success)
      formatResponseJson({ success: true, id: result.id, data: result.data }, context);
    else
      formatResponseJson(result, context);
  });
}

/**
 * Find composition social share record by its ID and render it as HTML
 * @param {any} id ID of the composition to look for
 * @param {any} context HTTP context of the request
 */
async function getSocialShareRecord(id, context) {
  await queryCollection("socialShare", { id: id }, function (result, success) {
    if (success)
      context.res.render('socialShare', { record: result });
    else
      formatResponseJson(result, context);
  });
}

/**
 * Generic method to find an item in the DB collection
 * @param {any} collName Name of the collection
 * @param {any} query MongoDB query expression
 * @param {any} callback Callback function
 */
async function queryCollection(collName, query, callback) {
  const client = new MongoClient(process.env.DB_HOST, { useNewUrlParser: true, useUnifiedTopology: true });

  try {
    await client.connect();
    const db = client.db(process.env.DB_NAME);
    const collection = db.collection(collName);
    const result = await collection.findOne(query);

    if (result) {
      callback(result, true);
    }
    else {
      callback({ success: false, id: query.id, error: `${collName} record not found` }, false);
    }
  }
  catch (err) {
    callback({ success: false, id: query.id, error: err }, false);
  }
  finally {
    client.close();
  }
}

/**
 * Generic method to insert an item in the DB collection
 * @param {any} collName Name of the collection
 * @param {any} record Item to be inserted
 * @param {any} context HTTP context of the request
 */
async function insertRecord(collName, record, context) {
  const client = new MongoClient(process.env.DB_HOST, { useNewUrlParser: true, useUnifiedTopology: true });

  try {
    await client.connect();
    const db = client.db(process.env.DB_NAME);
    const collection = db.collection(collName);

    var result = await collection.insertOne(record);
    if (result.insertedCount > 0)
      formatResponseJson({ success: true, id: record.id }, context);
    else
      formatResponseJson({ success: false, id: record.id, error: err }, context);
  }
  catch (err2) {
    formatResponseJson({ success: false, id: record.id, error: err2 }, context);
  }
  finally {
    client.close();
  }
}

/**
 * Format and send object as a JSON HTTP response
 * @param {any} obj Object to be sended in the response
 * @param {any} context HTTP context of the request
 */
function formatResponseJson(obj, context) {
  context.res.header("Content-Type", 'application/json');

  if (context.query && context.query.f && context.query.f == 'pjson')
    context.res.send(JSON.stringify(obj, null, 4));
  else
    context.res.send(obj);
}
<commit_msg>Process POST without content-type and views inside src directory<commit_after>require('dotenv').config();

const express = require('express');
//const cors = require('cors');
const { MongoClient } = require("mongodb");
const share = express();

// parse incoming POST requests body to JSON
share.use(express.json());
//// handle CORS
//share.use(cors())
share.set('view engine', 'pug')
share.set('views', __dirname+'/views/');

// handle GET requests
share.get('/', context => {
  if (context.query.request) {
    switch (context.query.request.toLowerCase()) {

      case 'load':
        getCompositionRecord(context.query.id, context);
        break;

      case 'socialshare':
        getSocialShareRecord(context.query.id, context);
        break;

      default:
        formatResponseJson({ success: false, error: "Request not specified" }, context);
        break;
    }
  }
  else {
    context.res.send('HSLayers map share service');
  }
});

// handle POST requests
share.post('/', express.json({strict: false, type: '*/*'}), context => {
  if (context.body && context.body.request) {
    switch (context.body.request.toLowerCase()) {
      case 'save':
        insertRecord("composition", {
          id: context.body.id,
          data: context.body.data
        }, context);
        break;

      case 'socialshare':
        insertRecord("socialShare", {
          id: context.body.id,
          url: context.body.url,
          title: context.body.title,
          description: context.body.description,
          image: context.body.image
        }, context);
        break;

      default:
        formatResponseJson({ success: false, error: "Request not specified" }, context);
    }
  }
  else {

  }
});

// start the service on the port xxxx
share.listen(3000, () => console.log('HSLayers map share service listening on port 3000...'));

/**
 * Find composition by its ID and return it as JSON
 * @param {any} id ID of the composition to look for
 * @param {any} context HTTP context of the request
 */
async function getCompositionRecord(id, context) {
  await queryCollection("composition", { id: id }, function (result, success) {
    if (success)
      formatResponseJson({ success: true, id: result.id, data: result.data }, context);
    else
      formatResponseJson(result, context);
  });
}

/**
 * Find composition social share record by its ID and render it as HTML
 * @param {any} id ID of the composition to look for
 * @param {any} context HTTP context of the request
 */
async function getSocialShareRecord(id, context) {
  await queryCollection("socialShare", { id: id }, function (result, success) {
    if (success)
      context.res.render('socialShare', { record: result });
    else
      formatResponseJson(result, context);
  });
}

/**
 * Generic method to find an item in the DB collection
 * @param {any} collName Name of the collection
 * @param {any} query MongoDB query expression
 * @param {any} callback Callback function
 */
async function queryCollection(collName, query, callback) {
  const client = new MongoClient(process.env.DB_HOST, { useNewUrlParser: true, useUnifiedTopology: true });

  try {
    await client.connect();
    const db = client.db(process.env.DB_NAME);
    const collection = db.collection(collName);
    const result = await collection.findOne(query);

    if (result) {
      callback(result, true);
    }
    else {
      callback({ success: false, id: query.id, error: `${collName} record not found` }, false);
    }
  }
  catch (err) {
    callback({ success: false, id: query.id, error: err }, false);
  }
  finally {
    client.close();
  }
}

/**
 * Generic method to insert an item in the DB collection
 * @param {any} collName Name of the collection
 * @param {any} record Item to be inserted
 * @param {any} context HTTP context of the request
 */
async function insertRecord(collName, record, context) {
  const client = new MongoClient(process.env.DB_HOST, { useNewUrlParser: true, useUnifiedTopology: true });

  try {
    await client.connect();
    const db = client.db(process.env.DB_NAME);
    const collection = db.collection(collName);

    var result = await collection.insertOne(record);
    if (result.insertedCount > 0)
      formatResponseJson({ success: true, id: record.id }, context);
    else
      formatResponseJson({ success: false, id: record.id, error: err }, context);
  }
  catch (err2) {
    formatResponseJson({ success: false, id: record.id, error: err2 }, context);
  }
  finally {
    client.close();
  }
}

/**
 * Format and send object as a JSON HTTP response
 * @param {any} obj Object to be sended in the response
 * @param {any} context HTTP context of the request
 */
function formatResponseJson(obj, context) {
  context.res.header("Content-Type", 'application/json');

  if (context.query && context.query.f && context.query.f == 'pjson')
    context.res.send(JSON.stringify(obj, null, 4));
  else
    context.res.send(obj);
}
<|endoftext|>


<commit_before>'use strict';

var React = require('react-native');
const STORAGE_KEY = 'restaurantsKey';
import clamp from 'clamp';
var RestaurantInfo = require('./restaurantInfo');
var ImageModal = require('./imageModal');

var {
View,
Text,
Component,
AsyncStorage,
StyleSheet,
Image,
PanResponder,
Animated,
TouchableOpacity
} = React;

var SWIPE_THRESHOLD = 120;

class Restaurant extends Component {

  constructor(props) {
    super(props)
    this.state = {
      latitude: null,
      longitude: null,
      pan: new Animated.ValueXY(),
      enter: new Animated.Value(0.5)
    }
  }

  _goToNextRestaurant() {
    var restaurant = this.props.restaurant;
    this.props.navigator.replace({
      title: restaurant.name,
      component: Restaurant,
      index: this.props.index + 1
    });
  }

  openModal(url) {
    this.props.navigator.push({
      component: ImageModal,
      url: url
    })
  }

  render() {
    let { pan, enter, } = this.state;

    let [translateX, translateY] = [pan.x, pan.y];

    let rotate = pan.x.interpolate({inputRange: [-200, 0, 200], outputRange: ["-30deg", "0deg", "30deg"]});
    let opacity = pan.x.interpolate({inputRange: [-200, 0 , 200], outputRange: [0.5, 1, 0.5]});
    let scale = enter;

    let animatedCardStyles = {transform: [{translateX}, {translateY}, {rotate}, {scale}], opacity};

    let yupOpacity = pan.x.interpolate({inputRange: [0, 150], outputRange: [0, 1]});
    let yupScale = pan.x.interpolate({inputRange: [0, 150], outputRange: [0.5, 1], extrapolate: 'clamp'});
    let animatedYupStyles = {transform: [{scale: yupScale}], opacity: yupOpacity}

    let nopeOpacity = pan.x.interpolate({inputRange: [-150, 0], outputRange: [1, 0]});
    let nopeScale = pan.x.interpolate({inputRange: [-150, 0], outputRange: [1, 0.5], extrapolate: 'clamp'});
    let animatedNopeStyles = {transform: [{scale: nopeScale}], opacity: nopeOpacity}

    var currentRestaurant = this.props.restaurant;
    if (currentRestaurant) {
      console.log(currentRestaurant);
      // console.log(this.state.restaurants); // DEBUGGING
      var url1 = currentRestaurant.photos[0];
      var url2 = currentRestaurant.photos[1];
      var url3 = currentRestaurant.photos[2];
      var url4 = currentRestaurant.photos[3];
      var url5 = currentRestaurant.photos[4];
    } else {
      SWIPE_THRESHOLD=1000;
    }

    return (
      <View style={styles.container} >
            <View style={styles.logoContainer}>
              <Image
                    style={styles.logo}
                    source={require('../thumbnails/logohighreswhite_720.png')}
              />
            </View>
            <View style={styles.blah}>
        <Animated.View style={styles.card, animatedCardStyles} {...this._panResponder.panHandlers}>
            {url1 ?
              <TouchableOpacity onPress={this.openModal.bind(this, url1)}>
                <Image style={styles.iconhor} source={{uri: url1}} />
              </TouchableOpacity>
            : null}
          <Animated.View style={styles.card, animatedCardStyles, styles.squareView} {...this._panResponder.panHandlers}>
            {currentRestaurant.photos.length > 2 ?
              <TouchableOpacity onPress={this.openModal.bind(this, url2)}>
                <Image style={styles.iconver} source={{uri: url2}} />
              </TouchableOpacity> : <TouchableOpacity onPress={this.openModal.bind(this, url2)}>
                <Image style={styles.iconhor} source={{uri: url2}} />
              </TouchableOpacity>
            }
            {url3 ?
              <TouchableOpacity onPress={this.openModal.bind(this, url3)}>
                <Image style={styles.iconver} source={{uri: url3}} />
              </TouchableOpacity>
            : null}
          </Animated.View>
            {url4 ?
              <TouchableOpacity onPress={this.openModal.bind(this, url4)}>
              <Image style={styles.iconhor} source={{uri: url4}} />
              </TouchableOpacity>
              : null}
        </Animated.View>
        <Animated.View style={[styles.nope, animatedNopeStyles]} >
          <Text style={styles.nopeText}>No No</Text>
        </Animated.View>
        <Animated.View style={[styles.yup, animatedYupStyles]}>
          <Text style={styles.yupText}>Nom Nom</Text>
        </Animated.View>
        </View>
      </View>
    )
  }

  componentDidMount(){
    this._animateEntrance();
  }

  componentWillMount() {
    this._panResponder = PanResponder.create({
      onMoveShouldSetResponderCapture: () => true,
      onMoveShouldSetPanResponderCapture: () => true,

      onPanResponderGrant: (e, gestureState) => {
        this.state.pan.setOffset({x: this.state.pan.x._value, y: this.state.pan.y._value});
        this.state.pan.setValue({x: 0, y: 0});
      },

      onPanResponderMove: Animated.event([
        null, {dx: this.state.pan.x, dy: this.state.pan.y},
      ]),

      onPanResponderRelease: (e, {vx, vy}) => {
        this.state.pan.flattenOffset();
        var velocity;

        if (vx >= 0) {
          velocity = clamp(vx, 3, 5);
        } else if (vx < 0) {
          velocity = clamp(vx * -1, 3, 5) * -1;
        }

        if (Math.abs(this.state.pan.x._value) > SWIPE_THRESHOLD) {
          var swipeFunction = this.state.pan.x._value > SWIPE_THRESHOLD ?
            this._swipeRight.bind(this) :
            this._resetState.bind(this);

          Animated.decay(this.state.pan, {
            velocity: {x: velocity, y: vy},
            deceleration: 0.98
          }).start(swipeFunction)
        } else {
          Animated.spring(this.state.pan, {
            toValue: {x: 0, y: 0},
            friction: 4
          }).start()
        }
      }
    })
  }

  _resetState() {
    this.state.pan.setValue({x: 0, y: 0});
    this.state.enter.setValue(0);
    this._goToNextRestaurant();
    this._animateEntrance();

  }

  _swipeRight() {
    var restaurant = this.props.restaurant;
    this.state.pan.setValue({x: 0, y: 0});
    this.state.enter.setValue(1);
    this._goToInfo(restaurant);
  }

  _goToInfo(restaurant) {
    this.props.navigator.push({
      title: restaurant.name,
      component: RestaurantInfo,
      passProps: {restaurant: restaurant}
    });
  }

  _animateEntrance() {
    Animated.spring(
      this.state.enter,
      { toValue: 1, friction: 8 }
    ).start();
  }
}

const styles = StyleSheet.create({
  container: {
    marginTop:20,
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#300030',
  },
  content: {
    flex: 1,
    color: 'white',
    fontSize: 25,
    marginTop: 20,
    fontFamily: 'Hiragino Kaku Gothic ProN'
  },
  iconhor: {
    width: 400,
    height: 150,
    margin: 2,
    justifyContent: 'center',
  },
  iconver: {
    width: 200,
    height: 150,
    margin: 2,
    justifyContent: 'center',
  },
  squareView:{
    flexDirection: 'row'
  },
  card: {
    flex: 1,
    width: 200,
    height: 200,
    backgroundColor: 'red'
  },
  yup: {
    borderColor: 'white',
    borderWidth: 2,
    position: 'absolute',
    padding: 20,
    bottom: 20,
    borderRadius: 5,
    right: 20,
  },
  yupText: {
    fontSize: 20,
    color: 'white',
    fontFamily: 'Hiragino Kaku Gothic ProN',
    backgroundColor: 'transparent'
  },
  nope: {
    borderColor: 'white',
    borderWidth: 2,
    position: 'absolute',
    bottom: 20,
    padding: 20,
    borderRadius: 5,
    left: 20
  },
  nopeText: {
    fontSize: 20,
    color: 'white',
    fontFamily: 'Hiragino Kaku Gothic ProN',
    backgroundColor: 'transparent'
  },
  logo: {
    marginLeft: 130,
    marginTop: 20,
    height: 80,
    width: 120,
  },
  logoContainer: {
    flex: 1,
    flexDirection: 'column',
    position: 'absolute',
    top: 0,
    left: 0,
    justifyContent: 'center',
    alignItems: 'center',
  },
  blah: {
    marginTop: 50,
  }
})

module.exports = Restaurant;
<commit_msg>Update restaurants.js<commit_after>'use strict';

var React = require('react-native');
const STORAGE_KEY = 'restaurantsKey';
import clamp from 'clamp';
var RestaurantInfo = require('./restaurantInfo');
var ImageModal = require('./imageModal');

var {
View,
Text,
Component,
AsyncStorage,
StyleSheet,
Image,
PanResponder,
Animated,
TouchableOpacity
} = React;

var SWIPE_THRESHOLD = 120;

class Restaurant extends Component {

  constructor(props) {
    super(props)
    this.state = {
      latitude: null,
      longitude: null,
      pan: new Animated.ValueXY(),
      enter: new Animated.Value(0.5)
    }
  }

  _goToNextRestaurant() {
    var restaurant = this.props.restaurant;
    this.props.navigator.replace({
      title: restaurant.name,
      component: Restaurant,
      index: this.props.index + 1
    });
  }

  openModal(url) {
    this.props.navigator.push({
      component: ImageModal,
      url: url
    })
  }

  render() {
    let { pan, enter, } = this.state;

    let [translateX, translateY] = [pan.x, pan.y];

    let rotate = pan.x.interpolate({inputRange: [-200, 0, 200], outputRange: ["-30deg", "0deg", "30deg"]});
    let opacity = pan.x.interpolate({inputRange: [-200, 0 , 200], outputRange: [0.5, 1, 0.5]});
    let scale = enter;

    let animatedCardStyles = {transform: [{translateX}, {translateY}, {rotate}, {scale}], opacity};

    let yupOpacity = pan.x.interpolate({inputRange: [0, 150], outputRange: [0, 1]});
    let yupScale = pan.x.interpolate({inputRange: [0, 150], outputRange: [0.5, 1], extrapolate: 'clamp'});
    let animatedYupStyles = {transform: [{scale: yupScale}], opacity: yupOpacity}

    let nopeOpacity = pan.x.interpolate({inputRange: [-150, 0], outputRange: [1, 0]});
    let nopeScale = pan.x.interpolate({inputRange: [-150, 0], outputRange: [1, 0.5], extrapolate: 'clamp'});
    let animatedNopeStyles = {transform: [{scale: nopeScale}], opacity: nopeOpacity}

    var currentRestaurant = this.props.restaurant;
    if (currentRestaurant) {
      console.log(currentRestaurant);
      // console.log(this.state.restaurants); // DEBUGGING
      var url1 = currentRestaurant.photos[0];
      var url2 = currentRestaurant.photos[1];
      var url3 = currentRestaurant.photos[2];
      var url4 = currentRestaurant.photos[3];
      var url5 = currentRestaurant.photos[4];
    } else {
      SWIPE_THRESHOLD=1000;
    }

    return (
      <View style={styles.container} >
            <View style={styles.logoContainer}>
              <Image
                    style={styles.logo}
                    source={require('../thumbnails/logohighreswhite_720.png')}
              />
            </View>
            <View style={styles.headerMargins}>
        <Animated.View style={styles.card, animatedCardStyles} {...this._panResponder.panHandlers}>
            {url1 ?
              <TouchableOpacity onPress={this.openModal.bind(this, url1)}>
                <Image style={styles.iconhor} source={{uri: url1}} />
              </TouchableOpacity>
            : null}
          <Animated.View style={styles.card, animatedCardStyles, styles.squareView} {...this._panResponder.panHandlers}>
            {currentRestaurant.photos.length > 2 ?
              <TouchableOpacity onPress={this.openModal.bind(this, url2)}>
                <Image style={styles.iconver} source={{uri: url2}} />
              </TouchableOpacity> : <TouchableOpacity onPress={this.openModal.bind(this, url2)}>
                <Image style={styles.iconhor} source={{uri: url2}} />
              </TouchableOpacity>
            }
            {url3 ?
              <TouchableOpacity onPress={this.openModal.bind(this, url3)}>
                <Image style={styles.iconver} source={{uri: url3}} />
              </TouchableOpacity>
            : null}
          </Animated.View>
            {url4 ?
              <TouchableOpacity onPress={this.openModal.bind(this, url4)}>
              <Image style={styles.iconhor} source={{uri: url4}} />
              </TouchableOpacity>
              : null}
        </Animated.View>
        <Animated.View style={[styles.nope, animatedNopeStyles]} >
          <Text style={styles.nopeText}>No No</Text>
        </Animated.View>
        <Animated.View style={[styles.yup, animatedYupStyles]}>
          <Text style={styles.yupText}>Nom Nom</Text>
        </Animated.View>
        </View>
      </View>
    )
  }

  componentDidMount(){
    this._animateEntrance();
  }

  componentWillMount() {
    this._panResponder = PanResponder.create({
      onMoveShouldSetResponderCapture: () => true,
      onMoveShouldSetPanResponderCapture: () => true,

      onPanResponderGrant: (e, gestureState) => {
        this.state.pan.setOffset({x: this.state.pan.x._value, y: this.state.pan.y._value});
        this.state.pan.setValue({x: 0, y: 0});
      },

      onPanResponderMove: Animated.event([
        null, {dx: this.state.pan.x, dy: this.state.pan.y},
      ]),

      onPanResponderRelease: (e, {vx, vy}) => {
        this.state.pan.flattenOffset();
        var velocity;

        if (vx >= 0) {
          velocity = clamp(vx, 3, 5);
        } else if (vx < 0) {
          velocity = clamp(vx * -1, 3, 5) * -1;
        }

        if (Math.abs(this.state.pan.x._value) > SWIPE_THRESHOLD) {
          var swipeFunction = this.state.pan.x._value > SWIPE_THRESHOLD ?
            this._swipeRight.bind(this) :
            this._resetState.bind(this);

          Animated.decay(this.state.pan, {
            velocity: {x: velocity, y: vy},
            deceleration: 0.98
          }).start(swipeFunction)
        } else {
          Animated.spring(this.state.pan, {
            toValue: {x: 0, y: 0},
            friction: 4
          }).start()
        }
      }
    })
  }

  _resetState() {
    this.state.pan.setValue({x: 0, y: 0});
    this.state.enter.setValue(0);
    this._goToNextRestaurant();
    this._animateEntrance();

  }

  _swipeRight() {
    var restaurant = this.props.restaurant;
    this.state.pan.setValue({x: 0, y: 0});
    this.state.enter.setValue(1);
    this._goToInfo(restaurant);
  }

  _goToInfo(restaurant) {
    this.props.navigator.push({
      title: restaurant.name,
      component: RestaurantInfo,
      passProps: {restaurant: restaurant}
    });
  }

  _animateEntrance() {
    Animated.spring(
      this.state.enter,
      { toValue: 1, friction: 8 }
    ).start();
  }
}

const styles = StyleSheet.create({
  container: {
    marginTop:20,
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#300030',
  },
  content: {
    flex: 1,
    color: 'white',
    fontSize: 25,
    marginTop: 20,
    fontFamily: 'Hiragino Kaku Gothic ProN'
  },
  iconhor: {
    width: 400,
    height: 150,
    margin: 2,
    justifyContent: 'center',
  },
  iconver: {
    width: 200,
    height: 150,
    margin: 2,
    justifyContent: 'center',
  },
  squareView:{
    flexDirection: 'row'
  },
  card: {
    flex: 1,
    width: 200,
    height: 200,
    backgroundColor: 'red'
  },
  yup: {
    borderColor: 'white',
    borderWidth: 2,
    position: 'absolute',
    padding: 20,
    bottom: 20,
    borderRadius: 5,
    right: 20,
  },
  yupText: {
    fontSize: 20,
    color: 'white',
    fontFamily: 'Hiragino Kaku Gothic ProN',
    backgroundColor: 'transparent'
  },
  nope: {
    borderColor: 'white',
    borderWidth: 2,
    position: 'absolute',
    bottom: 20,
    padding: 20,
    borderRadius: 5,
    left: 20
  },
  nopeText: {
    fontSize: 20,
    color: 'white',
    fontFamily: 'Hiragino Kaku Gothic ProN',
    backgroundColor: 'transparent'
  },
  logo: {
    marginLeft: 130,
    marginTop: 20,
    height: 80,
    width: 120,
  },
  logoContainer: {
    flex: 1,
    flexDirection: 'column',
    position: 'absolute',
    top: 0,
    left: 0,
    justifyContent: 'center',
    alignItems: 'center',
  },
  headerMargins: {
    marginTop: 50,
  }
})

module.exports = Restaurant;
<|endoftext|>