<commit_before>/*
	----------------------------------------------------
	Event.js : 1.1.2 : 2013/05/06 : MIT License
	----------------------------------------------------
	https://github.com/mudcube/Event.js
	----------------------------------------------------
	1  : click, dblclick, dbltap
	1+ : tap, longpress, drag, swipe
	2+ : pinch, rotate
	   : mousewheel, devicemotion, shake
	----------------------------------------------------
	Ideas for the future
	----------------------------------------------------
	* GamePad, and other input abstractions.
	* Event batching - i.e. for every x fingers down a new gesture is created.
	----------------------------------------------------
	http://www.w3.org/TR/2011/WD-touch-events-20110505/
	----------------------------------------------------

*/

if (typeof(Event) === "undefined") var Event = {};
if (typeof(eventjs) === "undefined") var eventjs = Event;

Event = (function(root) { "use strict";

// Add custom *EventListener commands to HTMLElements.
root.modifyEventListener = true;

// Add bulk *EventListener commands on NodeLists from querySelectorAll and others.
root.modifySelectors = true;

// Event maintenance.
root.add = function(target, type, listener, configure) {
	return eventManager(target, type, listener, configure, "add");
};

root.remove = function(target, type, listener, configure) {
	return eventManager(target, type, listener, configure, "remove");
};

root.stop = function(event) {
	if (event.stopPropagation) event.stopPropagation();
	event.cancelBubble = true; // <= IE8
	event.bubble = 0;
};

root.prevent = function(event) {
	if (event.preventDefault) event.preventDefault();
	event.returnValue = false; // <= IE8
};

root.cancel = function(event) {
	root.stop(event);
	root.prevent(event);
};

// Check whether event is natively supported (via @kangax)
root.supports = function (target, type) {
	if (typeof(target) === "string") {
		type = target;
		target = window;
	}
	type = "on" + type;
	if (type in target) return true;
	if (!target.setAttribute) target = document.createElement("div");
	if (target.setAttribute && target.removeAttribute) {
		target.setAttribute(type, "");
		var isSupported = typeof target[type] === "function";
		if (typeof target[type] !== "undefined") target[type] = null;
		target.removeAttribute(type);
		return isSupported;
	}
};

var clone = function (obj) {
	if (!obj || typeof (obj) !== 'object') return obj;
	var temp = new obj.constructor();
	for (var key in obj) {
		if (!obj[key] || typeof (obj[key]) !== 'object') {
			temp[key] = obj[key];
		} else { // clone sub-object
			temp[key] = clone(obj[key]);
		}
	}
	return temp;
};

/// Handle custom *EventListener commands.
var eventManager = function(target, type, listener, configure, trigger, fromOverwrite) {
	configure = configure || {};
	// Check whether target is a configuration variable;
	if (String(target) === "[object Object]") {
		var data = target;
		target = data.target;
		type = data.type;
		listener = data.listener;
		delete data.target;
		delete data.type;
		delete data.listener;
		for (var key in data) {
			configure[key] = data[key];
		}
	}
	///
	if (!target || !type || !listener) return;
	// Check for element to load on interval (before onload).
	if (typeof(target) === "string" && type === "ready") {
		var time = (new Date()).getTime();
		var timeout = configure.timeout;
		var ms = configure.interval || 1000 / 60;
		var interval = window.setInterval(function() {
			if ((new Date()).getTime() - time > timeout) {
				window.clearInterval(interval);
			}
			if (document.querySelector(target)) {
				window.clearInterval(interval);
				setTimeout(listener, 1);
			}
		}, ms);
		return;
	}
	// Get DOM element from Query Selector.
	if (typeof(target) === "string") {
		target = document.querySelectorAll(target);
		if (target.length === 0) return createError("Missing target on listener!", arguments); // No results.
		if (target.length === 1) { // Single target.
			target = target[0];
		}
	}

	/// Handle multiple targets.
	var event;
	var events = {};
	if (target.length > 0 && target !== window) {
		for (var n0 = 0, length0 = target.length; n0 < length0; n0 ++) {
			event = eventManager(target[n0], type, listener, clone(configure), trigger);
			if (event) events[n0] = event;
		}
		return createBatchCommands(events);
	}
	// Check for multiple events in one string.
	if (type.indexOf && type.indexOf(" ") !== -1) type = type.split(" ");
	if (type.indexOf && type.indexOf(",") !== -1) type = type.split(",");
	// Attach or remove multiple events associated with a target.
	if (typeof(type) !== "string") { // Has multiple events.
		if (typeof(type.length) === "number") { // Handle multiple listeners glued together.
			for (var n1 = 0, length1 = type.length; n1 < length1; n1 ++) { // Array [type]
				event = eventManager(target, type[n1], listener, clone(configure), trigger);
				if (event) events[type[n1]] = event;
			}
		} else { // Handle multiple listeners.
			for (var key in type) { // Object {type}
				if (typeof(type[key]) === "function") { // without configuration.
					event = eventManager(target, key, type[key], clone(configure), trigger);
				} else { // with configuration.
					event = eventManager(target, key, type[key].listener, clone(type[key]), trigger);
				}
				if (event) events[key] = event;
			}
		}
		return createBatchCommands(events);
	}
	// Ensure listener is a function.
	if (typeof(target) !== "object") return createError("Target is not defined!", arguments);
	if (typeof(listener) !== "function") return createError("Listener is not a function!", arguments);
	// Generate a unique wrapper identifier.
	var useCapture = configure.useCapture || false;
	var id = normalize(type) + "." + getID(target) + "." + getID(listener) + "." + (useCapture ? 1 : 0);
	// Handle the event.
	if (root.Gesture && root.Gesture._gestureHandlers[type]) { // Fire custom event.
		if (trigger === "remove") { // Remove event listener.
			if (!wrappers[id]) return; // Already removed.
			wrappers[id].remove();
			delete wrappers[id];
		} else if (trigger === "add") { // Attach event listener.
			if (wrappers[id]) {
				wrappers[id].add();
				return wrappers[id]; // Already attached.
			}
			// Retains "this" orientation.
			if (configure.useCall && !root.modifyEventListener) {
				var tmp = listener;
				listener = function(event, self) {
					for (var key in self) event[key] = self[key];
					return tmp.call(target, event);
				};
			}
			// Create listener proxy.
			configure.gesture = type;
			configure.target = target;
			configure.listener = listener;
			configure.fromOverwrite = fromOverwrite;
			// Record wrapper.
			wrappers[id] = root.proxy[type](configure);
		}
	} else { // Fire native event.
		type = normalize(type);
		if (trigger === "remove") { // Remove event listener.
			if (!wrappers[id]) return; // Already removed.
			target[remove](type, listener, useCapture);
			delete wrappers[id];
		} else if (trigger === "add") { // Attach event listener.
			if (wrappers[id]) return wrappers[id]; // Already attached.
			target[add](type, listener, useCapture);
			// Record wrapper.
			wrappers[id] = {
				id: id,
				type: type,
				target: target,
				listener: listener,
				remove: function() {
					root.remove(target, type, listener, configure);
				}
			};
		}
	}
	return wrappers[id];
};

/// Perform batch actions on multiple events.
var createBatchCommands = function(events) {
	return {
		remove: function() { // Remove multiple events.
			for (var key in events) {
				events[key].remove();
			}
		},
		add: function() { // Add multiple events.
			for (var key in events) {
				events[key].add();
			}
		}
	};
};

/// Display error message in console.
var createError = function(message, data) {
	if (typeof(console) === "undefined") return;
	if (typeof(console.error) === "undefined") return;
	console.error(message, data);
};

/// Handle naming discrepancies between platforms.
var normalize = (function() {
	var translate = {};
	return function(type) {
		if (!root.pointerType) {
			if (window.navigator.msPointerEnabled) {
				root.pointerType = "mspointer";
				translate = {
					"mousedown": "MSPointerDown",
					"mousemove": "MSPointerMove",
					"mouseup": "MSPointerUp"
				};
			} else if (root.supports("touchstart")) {
				root.pointerType = "touch";
				translate = {
					"mousedown": "touchstart",
					"mouseup": "touchend",
					"mousemove": "touchmove"
				};
			} else {
				root.pointerType = "mouse";
			}
		}
		if (translate[type]) type = translate[type];
		if (!document.addEventListener) { // IE
			return "on" + type;
		} else {
			return type;
		}
	};
})();

/// Event wrappers to keep track of all events placed in the window.
var wrappers = {};
var counter = 0;
var getID = function(object) {
	if (object === window) return "#window";
	if (object === document) return "#document";
	if (!object.uniqueID) object.uniqueID = "e" + counter ++;
	return object.uniqueID;
};

/// Detect platforms native *EventListener command.
var add = document.addEventListener ? "addEventListener" : "attachEvent";
var remove = document.removeEventListener ? "removeEventListener" : "detachEvent";

/*
	Pointer.js
	------------------------
	Modified from; https://github.com/borismus/pointer.js
*/

root.createPointerEvent = function (event, self, preventRecord) {
	var eventName = self.gesture;
	var target = self.target;
	var pts = event.changedTouches || root.proxy.getCoords(event);
	if (pts.length) {
		var pt = pts[0];
		self.pointers = preventRecord ? [] : pts;
		self.pageX = pt.pageX;
		self.pageY = pt.pageY;
		self.x = self.pageX;
		self.y = self.pageY;
	}
	///
	var newEvent = document.createEvent("Event");
	newEvent.initEvent(eventName, true, true);
	newEvent.originalEvent = event;
	for (var k in self) {
		if (k === "target") continue;
		newEvent[k] = self[k];
	}
	///
	var type = newEvent.type;
	if (root.Gesture && root.Gesture._gestureHandlers[type]) { // capture custom events.
		self.oldListener.call(target, newEvent, self);
	}
};

/// Allows *EventListener to use custom event proxies.
if (root.modifyEventListener && window.HTMLElement) (function() {
	var augmentEventListener = function(proto) {
		var recall = function(trigger) { // overwrite native *EventListener's
			var handle = trigger + "EventListener";
			var handler = proto[handle];
			proto[handle] = function (type, listener, useCapture) {
				if (root.Gesture && root.Gesture._gestureHandlers[type]) { // capture custom events.
					var configure = useCapture;
					if (typeof(useCapture) === "object") {
						configure.useCall = true;
					} else { // convert to configuration object.
						configure = {
							useCall: true,
							useCapture: useCapture
						};
					}
					eventManager(this, type, listener, configure, trigger, true);
//					handler.call(this, type, listener, useCapture);
				} else { // use native function.
					handler.call(this, normalize(type), listener, useCapture);
				}
			};
		};
		recall("add");
		recall("remove");
	};
	// NOTE: overwriting HTMLElement doesn't do anything in Firefox.
	if (navigator.userAgent.match(/Firefox/)) {
		// TODO: fix Firefox for the general case.
		augmentEventListener(HTMLDivElement.prototype);
		augmentEventListener(HTMLCanvasElement.prototype);
	} else {
		augmentEventListener(HTMLElement.prototype);
	}
	augmentEventListener(document);
	augmentEventListener(window);
})();

/// Allows querySelectorAll and other NodeLists to perform *EventListener commands in bulk.
if (root.modifySelectors) (function() {
	var proto = NodeList.prototype;
	proto.removeEventListener = function(type, listener, useCapture) {
		for (var n = 0, length = this.length; n < length; n ++) {
			this[n].removeEventListener(type, listener, useCapture);
		}
	};
	proto.addEventListener = function(type, listener, useCapture) {
		for (var n = 0, length = this.length; n < length; n ++) {
			this[n].addEventListener(type, listener, useCapture);
		}
	};
})();

return root;

})(Event);<commit_msg>adding support for devices with multiple pointer inputs (like chrome pixel with touch screen and mouse input), add event.preventManipulation for MSPointer prevent default<commit_after>/*
	----------------------------------------------------
	Event.js : 1.1.2 : 2013/05/06 : MIT License
	----------------------------------------------------
	https://github.com/mudcube/Event.js
	----------------------------------------------------
	1  : click, dblclick, dbltap
	1+ : tap, longpress, drag, swipe
	2+ : pinch, rotate
	   : mousewheel, devicemotion, shake
	----------------------------------------------------
	Ideas for the future
	----------------------------------------------------
	* GamePad, and other input abstractions.
	* Event batching - i.e. for every x fingers down a new gesture is created.
	----------------------------------------------------
	http://www.w3.org/TR/2011/WD-touch-events-20110505/
	----------------------------------------------------

*/

if (typeof(Event) === "undefined") var Event = {};
if (typeof(eventjs) === "undefined") var eventjs = Event;

(function(root) { "use strict";

// Add custom *EventListener commands to HTMLElements (set false to prevent funkiness).
root.modifyEventListener = true;

// Add bulk *EventListener commands on NodeLists from querySelectorAll and others  (set false to prevent funkiness).
root.modifySelectors = true;

// Event maintenance.
root.add = function(target, type, listener, configure) {
	return eventManager(target, type, listener, configure, "add");
};

root.remove = function(target, type, listener, configure) {
	return eventManager(target, type, listener, configure, "remove");
};

root.stop = function(event) {
	if (!event) return;
	if (event.stopPropagation) event.stopPropagation();
	event.cancelBubble = true; // <= IE8
	event.bubble = 0;
};

root.prevent = function(event) {
	if (!event) return;
	if (event.preventDefault) event.preventDefault();
	if (event.preventManipulation) event.preventManipulation(); // MS
	event.returnValue = false; // <= IE8
};

root.cancel = function(event) {
	root.stop(event);
	root.prevent(event);
};

// Check whether event is natively supported (via @kangax)
root.getEventSupport = function (target, type) {
	if (typeof(target) === "string") {
		type = target;
		target = window;
	}
	type = "on" + type;
	if (type in target) return true;
	if (!target.setAttribute) target = document.createElement("div");
	if (target.setAttribute && target.removeAttribute) {
		target.setAttribute(type, "");
		var isSupported = typeof target[type] === "function";
		if (typeof target[type] !== "undefined") target[type] = null;
		target.removeAttribute(type);
		return isSupported;
	}
};

var clone = function (obj) {
	if (!obj || typeof (obj) !== 'object') return obj;
	var temp = new obj.constructor();
	for (var key in obj) {
		if (!obj[key] || typeof (obj[key]) !== 'object') {
			temp[key] = obj[key];
		} else { // clone sub-object
			temp[key] = clone(obj[key]);
		}
	}
	return temp;
};

/// Handle custom *EventListener commands.
var eventManager = function(target, type, listener, configure, trigger, fromOverwrite) {
	configure = configure || {};
	// Check whether target is a configuration variable;
	if (String(target) === "[object Object]") {
		var data = target;
		target = data.target;
		type = data.type;
		listener = data.listener;
		delete data.target;
		delete data.type;
		delete data.listener;
		for (var key in data) {
			configure[key] = data[key];
		}
	}
	///
	if (!target || !type || !listener) return;
	// Check for element to load on interval (before onload).
	if (typeof(target) === "string" && type === "ready") {
		var time = (new Date()).getTime();
		var timeout = configure.timeout;
		var ms = configure.interval || 1000 / 60;
		var interval = window.setInterval(function() {
			if ((new Date()).getTime() - time > timeout) {
				window.clearInterval(interval);
			}
			if (document.querySelector(target)) {
				window.clearInterval(interval);
				setTimeout(listener, 1);
			}
		}, ms);
		return;
	}
	// Get DOM element from Query Selector.
	if (typeof(target) === "string") {
		target = document.querySelectorAll(target);
		if (target.length === 0) return createError("Missing target on listener!", arguments); // No results.
		if (target.length === 1) { // Single target.
			target = target[0];
		}
	}

	/// Handle multiple targets.
	var event;
	var events = {};
	if (target.length > 0 && target !== window) {
		for (var n0 = 0, length0 = target.length; n0 < length0; n0 ++) {
			event = eventManager(target[n0], type, listener, clone(configure), trigger);
			if (event) events[n0] = event;
		}
		return createBatchCommands(events);
	}
	// Check for multiple events in one string.
	if (type.indexOf && type.indexOf(" ") !== -1) type = type.split(" ");
	if (type.indexOf && type.indexOf(",") !== -1) type = type.split(",");
	// Attach or remove multiple events associated with a target.
	if (typeof(type) !== "string") { // Has multiple events.
		if (typeof(type.length) === "number") { // Handle multiple listeners glued together.
			for (var n1 = 0, length1 = type.length; n1 < length1; n1 ++) { // Array [type]
				event = eventManager(target, type[n1], listener, clone(configure), trigger);
				if (event) events[type[n1]] = event;
			}
		} else { // Handle multiple listeners.
			for (var key in type) { // Object {type}
				if (typeof(type[key]) === "function") { // without configuration.
					event = eventManager(target, key, type[key], clone(configure), trigger);
				} else { // with configuration.
					event = eventManager(target, key, type[key].listener, clone(type[key]), trigger);
				}
				if (event) events[key] = event;
			}
		}
		return createBatchCommands(events);
	}
	// Ensure listener is a function.
	if (typeof(target) !== "object") return createError("Target is not defined!", arguments);
	if (typeof(listener) !== "function") return createError("Listener is not a function!", arguments);
	// Generate a unique wrapper identifier.
	var useCapture = configure.useCapture || false;
	var id = getID(target) + "." + getID(listener) + "." + (useCapture ? 1 : 0);
	// Handle the event.
	if (root.Gesture && root.Gesture._gestureHandlers[type]) { // Fire custom event.
		id = type + id;
		if (trigger === "remove") { // Remove event listener.
			if (!wrappers[id]) return; // Already removed.
			wrappers[id].remove();
			delete wrappers[id];
		} else if (trigger === "add") { // Attach event listener.
			if (wrappers[id]) {
				wrappers[id].add();
				return wrappers[id]; // Already attached.
			}
			// Retains "this" orientation.
			if (configure.useCall && !root.modifyEventListener) {
				var tmp = listener;
				listener = function(event, self) {
					for (var key in self) event[key] = self[key];
					return tmp.call(target, event);
				};
			}
			// Create listener proxy.
			configure.gesture = type;
			configure.target = target;
			configure.listener = listener;
			configure.fromOverwrite = fromOverwrite;
			// Record wrapper.
			wrappers[id] = root.proxy[type](configure);
		}
		return wrappers[id];
	} else { // Fire native event.
		var eventList = getEventList(type);
		for (var n = 0, eventId; n < eventList.length; n ++) {
			type = eventList[n];
			eventId = type + "." + id;
			if (trigger === "remove") { // Remove event listener.
				if (!wrappers[eventId]) continue; // Already removed.
				target[remove](type, listener, useCapture);
				delete wrappers[eventId];
			} else if (trigger === "add") { // Attach event listener.
				if (wrappers[eventId]) return wrappers[eventId]; // Already attached.
				target[add](type, listener, useCapture);
				// Record wrapper.
				wrappers[eventId] = {
					id: eventId,
					type: type,
					target: target,
					listener: listener,
					remove: function() {
						for (var n = 0; n < eventList.length; n ++) {
							root.remove(target, eventList[n], listener, configure);
						}
					}
				};
			}
		}
		return wrappers[eventId];
	}
};

/// Perform batch actions on multiple events.
var createBatchCommands = function(events) {
	return {
		remove: function() { // Remove multiple events.
			for (var key in events) {
				events[key].remove();
			}
		},
		add: function() { // Add multiple events.
			for (var key in events) {
				events[key].add();
			}
		}
	};
};

/// Display error message in console.
var createError = function(message, data) {
	if (typeof(console) === "undefined") return;
	if (typeof(console.error) === "undefined") return;
	console.error(message, data);
};

/// Handle naming discrepancies between platforms.
var pointerDefs = {
	"msPointer": [ "MSPointerDown", "MSPointerMove", "MSPointerUp" ],
	"touch": [ "touchstart", "touchmove", "touchend" ],
	"mouse": [ "mousedown", "mousemove", "mouseup" ]
};

var pointerDetect = {
	// MSPointer
	"MSPointerDown": 0,
	"MSPointerMove": 1,
	"MSPointerUp": 2,
	// Touch
	"touchstart": 0,
	"touchmove": 1,
	"touchend": 2,
	// Mouse
	"mousedown": 0,
	"mousemove": 1,
	"mouseup": 2
};

var getEventSupport = (function() {
	root.supports = {};
	if (window.navigator.msPointerEnabled) {
		root.supports.msPointer = true;
	}
	if (root.getEventSupport("touchstart")) {
		root.supports.touch = true;
	}
	if (root.getEventSupport("mousedown")) {
		root.supports.mouse = true;
	}
})();

var getEventList = (function() {
	return function(type) {
		var prefix = document.addEventListener ? "" : "on"; // IE
		var idx = pointerDetect[type];
		if (isFinite(idx)) {
			var types = [];
			for (var key in root.supports) {
				types.push(prefix + pointerDefs[key][idx]);
			}
			return types;
		} else {
			return [ prefix + type ];
		}
	};
})();

/// Event wrappers to keep track of all events placed in the window.
var wrappers = {};
var counter = 0;
var getID = function(object) {
	if (object === window) return "#window";
	if (object === document) return "#document";
	if (!object.uniqueID) object.uniqueID = "e" + counter ++;
	return object.uniqueID;
};

/// Detect platforms native *EventListener command.
var add = document.addEventListener ? "addEventListener" : "attachEvent";
var remove = document.removeEventListener ? "removeEventListener" : "detachEvent";

/*
	Pointer.js
	------------------------
	Modified from; https://github.com/borismus/pointer.js
*/

root.createPointerEvent = function (event, self, preventRecord) {
	var eventName = self.gesture;
	var target = self.target;
	var pts = event.changedTouches || root.proxy.getCoords(event);
	if (pts.length) {
		var pt = pts[0];
		self.pointers = preventRecord ? [] : pts;
		self.pageX = pt.pageX;
		self.pageY = pt.pageY;
		self.x = self.pageX;
		self.y = self.pageY;
	}
	///
	var newEvent = document.createEvent("Event");
	newEvent.initEvent(eventName, true, true);
	newEvent.originalEvent = event;
	for (var k in self) {
		if (k === "target") continue;
		newEvent[k] = self[k];
	}
	///
	var type = newEvent.type;
	if (root.Gesture && root.Gesture._gestureHandlers[type]) { // capture custom events.
//		target.dispatchEvent(newEvent);
		self.oldListener.call(target, newEvent, self, false);
	}
};

/// Allows *EventListener to use custom event proxies.
if (root.modifyEventListener && window.HTMLElement) (function() {
	var augmentEventListener = function(proto) {
		var recall = function(trigger) { // overwrite native *EventListener's
			var handle = trigger + "EventListener";
			var handler = proto[handle];
			proto[handle] = function (type, listener, useCapture) {
				if (root.Gesture && root.Gesture._gestureHandlers[type]) { // capture custom events.
					var configure = useCapture;
					if (typeof(useCapture) === "object") {
						configure.useCall = true;
					} else { // convert to configuration object.
						configure = {
							useCall: true,
							useCapture: useCapture
						};
					}
					eventManager(this, type, listener, configure, trigger, true);
//					handler.call(this, type, listener, useCapture);
				} else { // use native function.
					var types = getEventList(type);
					for (var n = 0; n < types.length; n ++) {
						handler.call(this, types[n], listener, useCapture);
					}
				}
			};
		};
		recall("add");
		recall("remove");
	};
	// NOTE: overwriting HTMLElement doesn't do anything in Firefox.
	if (navigator.userAgent.match(/Firefox/)) {
		// TODO: fix Firefox for the general case.
		augmentEventListener(HTMLDivElement.prototype);
		augmentEventListener(HTMLCanvasElement.prototype);
	} else {
		augmentEventListener(HTMLElement.prototype);
	}
	augmentEventListener(document);
	augmentEventListener(window);
})();

/// Allows querySelectorAll and other NodeLists to perform *EventListener commands in bulk.
if (root.modifySelectors) (function() {
	var proto = NodeList.prototype;
	proto.removeEventListener = function(type, listener, useCapture) {
		for (var n = 0, length = this.length; n < length; n ++) {
			this[n].removeEventListener(type, listener, useCapture);
		}
	};
	proto.addEventListener = function(type, listener, useCapture) {
		for (var n = 0, length = this.length; n < length; n ++) {
			this[n].addEventListener(type, listener, useCapture);
		}
	};
})();

return root;

})(Event);<|endoftext|>


<commit_before>// Copyright 2018, University of Colorado Boulder

/**
 * A dialog that the client displays when the user gets a specific number of stars.
 * See specification in https://github.com/phetsims/vegas/issues/59.
 *
 * @author Andrea Lin
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var vegas = require( 'VEGAS/vegas' );
  var HBox = require( 'SCENERY/nodes/HBox' );
  var VBox = require( 'SCENERY/nodes/VBox' );
  var Image = require( 'SCENERY/nodes/Image' );
  var RectangularPushButton = require( 'SUN/buttons/RectangularPushButton' );
  var VStrut = require( 'SCENERY/nodes/VStrut' );
  var Dialog = require( 'JOIST/Dialog' );
  var NumberProperty = require( 'AXON/NumberProperty' );
  var ScoreDisplayNumberAndStar = require( 'VEGAS/ScoreDisplayNumberAndStar' );
  var Text = require( 'SCENERY/nodes/Text' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var PhetColorScheme = require( 'SCENERY_PHET/PhetColorScheme' );

  // images
  var phetGirlJugglingStarsImage = require( 'image!VEGAS/phet-girl-juggling-stars.png' );

  // strings
  var keepGoingString = require( 'string!VEGAS/keepGoing' );
  var newLevelString = require( 'string!VEGAS/newLevel' );

  // constants
  var SCORE_FONT = new PhetFont( { size: 40, weight: 'bold' } );
  var BUTTON_FONT = new PhetFont( 24 );

  /**
   * @param {number} score
   * @param {Object} [options]
   * @constructor
   */
  function RewardDialog( score, options ) {

    options = _.extend( {
      modal: true,
      hasCloseButton: false,
      xMargin: 40,
      keepGoingButtonListener: function() {}, // called when 'Keep Going' button is pressed
      newLevelButtonListener: function() {} // called when 'New Level' button is pressed
    }, options );

    var phetGirlNode = new Image( phetGirlJugglingStarsImage );

    var scoreDisplay = new ScoreDisplayNumberAndStar( new NumberProperty( score ), {
      font: SCORE_FONT,
      spacing: 6,
      starNodeOptions: {
        outerRadius: 25,
        innerRadius: 12.5,
        filledLineWidth: 3,
        emptyLineWidth: 3
      }
    } );

    var buttonOptions = {
      minWidth: 145, // determined empirically
      maxWidth: 145
    };

    var keepGoingButton = new RectangularPushButton( _.extend( {}, buttonOptions, {
      content: new Text( keepGoingString, { font: BUTTON_FONT } ),
      listener: options.keepGoingButtonListener,
      baseColor: 'white'
    } ) );

    var newLevelButton = new RectangularPushButton( _.extend( {}, buttonOptions, {
      content: new Text( newLevelString, { font: BUTTON_FONT } ),
      listener: options.newLevelButtonListener,
      baseColor: PhetColorScheme.PHET_LOGO_YELLOW
    } ) );

    var rightSideNode = new VBox( {
      children: [ scoreDisplay, new VStrut( 20 ), keepGoingButton, newLevelButton ],
      spacing: 25
    } );

    var content = new HBox( {
      children: [ phetGirlNode, rightSideNode ],
      spacing: 40
    } );

    Dialog.call( this, content, options );
  }

  vegas.register( 'RewardDialog', RewardDialog );

  return inherit( Dialog, RewardDialog );
} );<commit_msg>move Dialog and DialogIO to sun, https://github.com/phetsims/joist/issues/315<commit_after>// Copyright 2018, University of Colorado Boulder

/**
 * A dialog that the client displays when the user gets a specific number of stars.
 * See specification in https://github.com/phetsims/vegas/issues/59.
 *
 * @author Andrea Lin
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var vegas = require( 'VEGAS/vegas' );
  var HBox = require( 'SCENERY/nodes/HBox' );
  var VBox = require( 'SCENERY/nodes/VBox' );
  var Image = require( 'SCENERY/nodes/Image' );
  var RectangularPushButton = require( 'SUN/buttons/RectangularPushButton' );
  var VStrut = require( 'SCENERY/nodes/VStrut' );
  var Dialog = require( 'SUN/Dialog' );
  var NumberProperty = require( 'AXON/NumberProperty' );
  var ScoreDisplayNumberAndStar = require( 'VEGAS/ScoreDisplayNumberAndStar' );
  var Text = require( 'SCENERY/nodes/Text' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var PhetColorScheme = require( 'SCENERY_PHET/PhetColorScheme' );

  // images
  var phetGirlJugglingStarsImage = require( 'image!VEGAS/phet-girl-juggling-stars.png' );

  // strings
  var keepGoingString = require( 'string!VEGAS/keepGoing' );
  var newLevelString = require( 'string!VEGAS/newLevel' );

  // constants
  var SCORE_FONT = new PhetFont( { size: 40, weight: 'bold' } );
  var BUTTON_FONT = new PhetFont( 24 );

  /**
   * @param {number} score
   * @param {Object} [options]
   * @constructor
   */
  function RewardDialog( score, options ) {

    options = _.extend( {
      modal: true,
      hasCloseButton: false,
      xMargin: 40,
      keepGoingButtonListener: function() {}, // called when 'Keep Going' button is pressed
      newLevelButtonListener: function() {} // called when 'New Level' button is pressed
    }, options );

    var phetGirlNode = new Image( phetGirlJugglingStarsImage );

    var scoreDisplay = new ScoreDisplayNumberAndStar( new NumberProperty( score ), {
      font: SCORE_FONT,
      spacing: 6,
      starNodeOptions: {
        outerRadius: 25,
        innerRadius: 12.5,
        filledLineWidth: 3,
        emptyLineWidth: 3
      }
    } );

    var buttonOptions = {
      minWidth: 145, // determined empirically
      maxWidth: 145
    };

    var keepGoingButton = new RectangularPushButton( _.extend( {}, buttonOptions, {
      content: new Text( keepGoingString, { font: BUTTON_FONT } ),
      listener: options.keepGoingButtonListener,
      baseColor: 'white'
    } ) );

    var newLevelButton = new RectangularPushButton( _.extend( {}, buttonOptions, {
      content: new Text( newLevelString, { font: BUTTON_FONT } ),
      listener: options.newLevelButtonListener,
      baseColor: PhetColorScheme.PHET_LOGO_YELLOW
    } ) );

    var rightSideNode = new VBox( {
      children: [ scoreDisplay, new VStrut( 20 ), keepGoingButton, newLevelButton ],
      spacing: 25
    } );

    var content = new HBox( {
      children: [ phetGirlNode, rightSideNode ],
      spacing: 40
    } );

    Dialog.call( this, content, options );
  }

  vegas.register( 'RewardDialog', RewardDialog );

  return inherit( Dialog, RewardDialog );
} );<|endoftext|>


<commit_before>/*
 * Multiselect
 * https://github.com/crlcu/multiselect
 *
 * Copyright (c) 2013 Adrian Crisan
 * Licensed under the MIT license.
 */

;(function( $ ) {
    /*
     * public methods
     */
    var privateMethods = {
        init: function( obj, data ){
            console.log(obj);
            console.log(data);
        }
    };

    /*
     * public methods
     */
    var methods = {
        open: function(name, callback) {
            privateMethods.execute('open', name, callback);
        },
        close: function(name, callback) {
            privateMethods.execute('close', name, callback);
        },
        toogle: function(name, callback) {
            privateMethods.execute('toogle', name, callback);
        }
    };

    $.multiselect = function( method ) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'function' ||  typeof method === 'string'  || ! method ) {
            return methods.toogle.apply( this, arguments );
        } else {
            return $.error( 'Method ' +  method + ' does not exist on multiselect.' );
        }
    };

    $.fn.multiselect = function( options ) {
        var settings = $.extend({}, {
            /*
             * will be executed once
             * @method startUp
            **/
            startUp: function( $left, $right ) {},
            /*
             *  will be executed each time before moving one option to right
             *  IMPORTANT : this method must return boolean value
             *      true    : continue to moveOneToRight method
             *      false   : stop
             *
             *  @method beforeMoveOneToRight
             *  @attribute $left jQuery object
             *  @attribute $right jQuery object
             *  @attribute option HTML object (the option which was selected to be moved)
             *
             *  @default true
             *  @return {boolean}
            **/
			beforeMoveOneToRight: function($left, $right, option) { return true; },
			afterMoveOneToRight: function($left, $right, option){},
			beforeMoveAllToRight: function($left, $right, options){ return true; },
			afterMoveAllToRight: function($left, $right, options){},
			beforeMoveOneToLeft: function($left, $right, option){ return true; },
			afterMoveOneToLeft: function($left, $right, option){},
			beforeMoveAllToLeft: function($left, $right, options){ return true; },
			afterMoveAllToLeft: function($left, $right, options){},
            sort: function(a, b) {
                if (a.innerHTML == 'NA') {
					return 1;
				} else if (b.innerHTML == 'NA') {
					return -1;
				}

				return (a.innerHTML > b.innerHTML) ? 1 : -1;
            }
        }, options);

        return this.each(function() {
            var $this = $(this),
            data = $this.data();

            privateMethods.init($this, data);
        });
    };

})( jQuery );<commit_msg>Start of new plugin definition<commit_after>/*
 * Multiselect
 * https://github.com/crlcu/multiselect
 *
 * Copyright (c) 2013 Adrian Crisan
 * Licensed under the MIT license.
 */

;(function( $ ) {
    /*
     * private methods
     */
    var __private = {
        settings: undefined,

        init: function( obj, data, settings ) {
            __private.settings = settings;

            var $left = __private.$left = obj;
            var $leftAll = __private.$leftAll = $( data.leftAll );
            var $leftSelected = __private.$leftSelected = $( data.leftSelected );

            var $right = __private.$right = $( data.right );
            var $rightAll = __private.$rightAll = $( data.rightAll );
            var $rightSelected = __private.$rightSelected = $( data.rightSelected );

            if ( typeof settings.startUp == 'function' ) {
                settings.startUp( $left, $right );
            }

            if ( typeof settings.sort == 'function' ) {
                $left.find('option').sort(settings.sort).appendTo($left);
                $right.find('option').sort(settings.sort).appendTo($right);
            }

            __private.events();

            __private.beforeSubmit( $left );

            return this;
        },

        events: function() {
            __private.$left.on('dblclick', 'option', function(e) {
                e.preventDefault();
                __private.moveOneToRight(this);
            });

            __private.$right.on('dblclick', 'option', function(e) {
                e.preventDefault();
                __private.moveOneToLeft(this);
            });

            __private.$rightSelected.on('click', function(e) {
                e.preventDefault();
                var option = __private.$left.find('option:selected');

                if ( option )
                    __private.moveOneToRight(option);
            });

            __private.$leftSelected.on('click', function(e) {
                e.preventDefault();
                var option = __private.$right.find('option:selected');

                if ( option )
                    __private.moveOneToLeft(option);
            });

            __private.$rightAll.on('click', function(e){
                e.preventDefault();

                var options = __private.$left.find('option');

                if ( options )
                    __private.moveAllToRight(options);
            });

            __private.$leftAll.on('click', function(e){
                e.preventDefault();

                var options = __private.$right.find('option');

                if ( options )
                    __private.moveAllToLeft(options);
            });
        },

        moveOneToRight: function( option, silent ) {
            if ( typeof __private.settings.beforeMoveOneToRight == 'function' && !silent ){
                if ( !__private.settings.beforeMoveOneToRight( __private.$left, __private.$right, option ) )
                    return false;
            }

            __private.$right.append(option);

            if ( typeof __private.settings.sort == 'function' && !silent ){
                __private.$right.find('option').sort(__private.settings.sort).appendTo(__private.$right);
            }

            if ( typeof __private.settings.afterMoveOneToRight == 'function' && !silent ){
                __private.settings.afterMoveOneToRight( __private.$left, __private.$right, option );
            }
        },

        moveOneToLeft: function( option, silent ){
            if ( typeof __private.settings.beforeMoveOneToLeft == 'function' && !silent ) {
                if ( !__private.settings.beforeMoveOneToLeft( __private.$left, __private.$right, option ) )
                    return false;
            }

            __private.$left.append(option);

            if ( typeof __private.settings.sort == 'function' && !silent ) {
                __private.$left.find('option').sort(__private.settings.sort).appendTo(__private.$left);
            }

            if ( typeof __private.settings.afterMoveOneToLeft == 'function' && !silent ) {
                __private.settings.afterMoveOneToLeft( __private.$left, __private.$right, option );
            }
        },

        moveAllToRight: function( options ) {
            if ( typeof __private.settings.beforeMoveAllToRight == 'function' ) {
                if ( !__private.settings.beforeMoveAllToRight( __private.$left, __private.$right, options ) )
                    return false;
            }

            for ( var i = 0; options[i]; i++ ) {
                __private.moveOneToRight(options[i], true);
            }

            if ( typeof __private.settings.sort == 'function' ) {
                __private.$right.find('option').sort(__private.settings.sort).appendTo(__private.$right);
            }

            if ( typeof __private.settings.afterMoveAllToRight == 'function' ){
                __private.settings.afterMoveAllToRight( __private.$left, __private.$right, options );
            }
        },

        moveAllToLeft: function( options ){
            if ( typeof __private.settings.beforeMoveAllToLeft == 'function' ) {
                if ( !__private.settings.beforeMoveAllToLeft( __private.$left, __private.$right, options ) )
                    return false;
            }

            for ( var i = 0; options[i]; i++ ) {
                __private.moveOneToLeft(options[i], true);
            }

            if ( typeof __private.settings.sort == 'function' ){
                __private.$left.find('option').sort(__private.settings.sort).appendTo(__private.$left);
            }

            if ( typeof __private.settings.afterMoveAllToLeft == 'function' ){
                __private.settings.afterMoveAllToLeft( __private.$left, __private.$right, options );
            }
        },

        beforeSubmit: function( $left ) {
            var $form = $left.closest('form');

            $form.off('submit').on('submit', function() {
                $('select[multiple]', $form).find('option').attr('selected', true);
            });
        }
    };

    /*
     * public methods
     */
    var methods = {
        open: function(name, callback) {
            privateMethods.execute('open', name, callback);
        },
        close: function(name, callback) {
            privateMethods.execute('close', name, callback);
        },
        toogle: function(name, callback) {
            privateMethods.execute('toogle', name, callback);
        }
    };

    $.multiselect = function( method ) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'function' ||  typeof method === 'string'  || ! method ) {
            return methods.toogle.apply( this, arguments );
        } else {
            return $.error( 'Method ' +  method + ' does not exist on multiselect.' );
        }
    };

    $.fn.multiselect = function( options ) {
        var settings = $.extend({}, {
            /*
             * will be executed once
             * @method startUp
            **/
            startUp: function( $left, $right ) {},
            /*
             *  will be executed each time before moving one option to right
             *  IMPORTANT : this method must return boolean value
             *      true    : continue to moveOneToRight method
             *      false   : stop
             *
             *  @method beforeMoveOneToRight
             *  @attribute $left jQuery object
             *  @attribute $right jQuery object
             *  @attribute option HTML object (the option which was selected to be moved)
             *
             *  @default true
             *  @return {boolean}
            **/
			beforeMoveOneToRight: function($left, $right, option) { return true; },
			afterMoveOneToRight: function($left, $right, option){},
			beforeMoveAllToRight: function($left, $right, options){ return true; },
			afterMoveAllToRight: function($left, $right, options){},
			beforeMoveOneToLeft: function($left, $right, option){ return true; },
			afterMoveOneToLeft: function($left, $right, option){},
			beforeMoveAllToLeft: function($left, $right, options){ return true; },
			afterMoveAllToLeft: function($left, $right, options){},
            sort: function(a, b) {
                if (a.innerHTML == 'NA') {
					return 1;
				} else if (b.innerHTML == 'NA') {
					return -1;
				}

				return (a.innerHTML > b.innerHTML) ? 1 : -1;
            }
        }, options);

        return this.each(function() {
            var $this = $(this),
            data = $this.data();

            return __private.init($this, data, settings);
        });
    };

})( jQuery );<|endoftext|>


<commit_before>/*jslint browser: true, white: true, plusplus: true */
/*global angular, console, alert*/

(function () {
  'use strict';

  var app = angular.module('keira2');

  app.controller("CreatureController", function ($scope, $http, $stateParams, $modal) {

    if ($stateParams.id) {
      $http.get( app.api + "creature/template/" + $stateParams.id)
        .success(function (data, status, header, config) {
        $scope.current_creature_template = data[0];
        $scope.new_creature_template = angular.copy($scope.current_creature_template);
        console.log($scope.current_creature_template);
      })
        .error(function (data, status, header, config) {
        console.log("Error in CREATURE DATA $http.get request");
      });
      $scope.isCreatureSelected = true;
    }

    $scope.search = function (CreatureEntry, CreatureName, CreatureSubname) {

      $http.get( app.api + "/search/creature/", {
        params: {
          id: CreatureEntry,
          name: CreatureName,
          subname: CreatureSubname
        }
      }).success(function (data, status, header, config) {
        $scope.creatures = data;
      })
        .error(function (data, status, header, config) {
        console.log("Error in CREATURE SEARCH $http.get request");
      });

    };

    /* Generate SQL Script for Creature */
    $scope.generateCreatureScript = function() {

      var whereCondition = "entry = " + $scope.current_creature_template.entry;

      $scope.creatureScript = app.getUpdateQuery("creature_template", whereCondition, $scope.current_creature_template, $scope.new_creature_template);

    };

    $scope.open = function (size) {

      var modalInstance = $modal.open({
        animation: $scope.animationsEnabled,
        templateUrl: 'partials/creature/modals/mechanic.html',
        controller: "ModalInstanceCtrl",
        size: size,
        resolve: {
          mechanicVal: function () {
            return $scope.new_creature_template.mechanic_immune_mask;
          }
        }
      });

      modalInstance.result.then(function (mechanicRes) {
        $scope.new_creature_template.mechanic_immune_mask = mechanicRes;
      });

    };

  });

  app.controller('ModalInstanceCtrl', function ($scope, $modalInstance, mechanicVal) {

    mechanicVal = String(parseInt(mechanicVal, 10).toString(2));
    mechanicVal = mechanicVal.split("").reverse().join("");

    $scope.mechanic = new Array(31);

    var i = 0;
    for (i = 0; i < $scope.mechanic.length; i++)
    {
      if(parseInt(mechanicVal[i], 10) !== 1) {
        $scope.mechanic[i] = false;
      } else {
        $scope.mechanic[i] = true;
      }
    }

    $scope.ok = function () {
      var i = 0, mechanicRes = 0;
      for (i = 0; i < $scope.mechanic.length; i++)
      {
        if($scope.mechanic[i] === true)
        {
          mechanicRes += Math.pow(2, i);
        }
      }
      $modalInstance.close(mechanicRes);
    };

    $scope.cancel = function () {
      $modalInstance.dismiss('cancel');
    };

  });

}());
<commit_msg>Do not generate creature script if there is no creature selected<commit_after>/*jslint browser: true, white: true, plusplus: true */
/*global angular, console, alert*/

(function () {
  'use strict';

  var app = angular.module('keira2');

  app.controller("CreatureController", function ($scope, $http, $stateParams, $modal) {

    if ($stateParams.id) {
      $http.get( app.api + "creature/template/" + $stateParams.id)
        .success(function (data, status, header, config) {
        $scope.current_creature_template = data[0];
        $scope.new_creature_template = angular.copy($scope.current_creature_template);
        console.log($scope.current_creature_template);
      })
        .error(function (data, status, header, config) {
        console.log("Error in CREATURE DATA $http.get request");
      });
      $scope.isCreatureSelected = true;
    }

    $scope.search = function (CreatureEntry, CreatureName, CreatureSubname) {

      $http.get( app.api + "/search/creature/", {
        params: {
          id: CreatureEntry,
          name: CreatureName,
          subname: CreatureSubname
        }
      }).success(function (data, status, header, config) {
        $scope.creatures = data;
      })
        .error(function (data, status, header, config) {
        console.log("Error in CREATURE SEARCH $http.get request");
      });

    };

    /* Generate SQL Script for Creature */
    $scope.generateCreatureScript = function() {

      if (!$scope.isCreatureSelected) { return; }

      var whereCondition = "entry = " + $scope.current_creature_template.entry;

      $scope.creatureScript = app.getUpdateQuery("creature_template", whereCondition, $scope.current_creature_template, $scope.new_creature_template);

    };

    $scope.open = function (size) {

      var modalInstance = $modal.open({
        animation: $scope.animationsEnabled,
        templateUrl: 'partials/creature/modals/mechanic.html',
        controller: "ModalInstanceCtrl",
        size: size,
        resolve: {
          mechanicVal: function () {
            return $scope.new_creature_template.mechanic_immune_mask;
          }
        }
      });

      modalInstance.result.then(function (mechanicRes) {
        $scope.new_creature_template.mechanic_immune_mask = mechanicRes;
      });

    };

  });

  app.controller('ModalInstanceCtrl', function ($scope, $modalInstance, mechanicVal) {

    mechanicVal = String(parseInt(mechanicVal, 10).toString(2));
    mechanicVal = mechanicVal.split("").reverse().join("");

    $scope.mechanic = new Array(31);

    var i = 0;
    for (i = 0; i < $scope.mechanic.length; i++)
    {
      if(parseInt(mechanicVal[i], 10) !== 1) {
        $scope.mechanic[i] = false;
      } else {
        $scope.mechanic[i] = true;
      }
    }

    $scope.ok = function () {
      var i = 0, mechanicRes = 0;
      for (i = 0; i < $scope.mechanic.length; i++)
      {
        if($scope.mechanic[i] === true)
        {
          mechanicRes += Math.pow(2, i);
        }
      }
      $modalInstance.close(mechanicRes);
    };

    $scope.cancel = function () {
      $modalInstance.dismiss('cancel');
    };

  });

}());
<|endoftext|>


<commit_before>define([
    '../utility/retina.js',
], (isRetina) => {
    var Renderer = function($canvas, canvasContext) {
        var myself = self;
        var resolution = isRetina ? 2 : 1;
        var backgroundRatio = {
            width: 1,
            height: 1,
        };
        var offset = {
            x: 0,
            y: 0,
        }
        var backgroundDimensions = {
            cornerX: undefined,
            cornerY: undefined,
            width: undefined,
            height: undefined,
        };

        this.getBackgroundRatio = () => {
            return backgroundRatio;
        }

        this.setBackgroundRatio = (width, height) => {
            backgroundRatio.width = width;
            backgroundRatio.height = height;
        }

        this.setBackgroundDimensions = (cornerX, cornerY, width, height) => {
            backgroundDimensions = {
                cornerX: cornerX,
                cornerY: cornerY,
                width: width,
                height: height,
            };
        }

        this.getBackgroundDimensions = () => {
            return backgroundDimensions;
        }

        this.get$Canvas = () => {
            return $canvas;
        }

        this.getCanvas = () => {
            return canvas;
        }

        this.getContext = () => {
            return canvasContext;
        }

        this.convertCoordonateToBackground = (point, forDisplay) => {
            var r = forDisplay ? resolution : 1;
            return {
                x: point.x * backgroundRatio.width * r + offset.x,
                y: point.y * backgroundRatio.height * r + offset.y,
            };
        }

        this.convertBackgroundToCoordinate = (point, forDisplay) => {
            var r = forDisplay ? resolution : 1;
            return {
                x: (point.x - offset.x) / backgroundRatio.width / r,
                y: (point.y - offset.y) / backgroundRatio.height/ r,
            };
        }

        this.convertValueToBackground = (value, forDisplay) => {
            var r = forDisplay ? resolution : 1;
            return value * backgroundRatio.width* r;
        }

        this.convertBackgroundToValue = (value, forDisplay) => {
            var r = forDisplay ? resolution : 1;
            return value / backgroundRatio.width/ r;
        }

        this.setOffset = (offsetX, offsetY) => {
            offset.x = offsetX;
            offset.y = offsetY;
        }

        this.getOffset = () => {
            return offset;
        }
    }

    return Renderer;
});
<commit_msg>Fix renderer coordinates conversion<commit_after>define([
    '../utility/retina.js',
], (isRetina) => {
    var Renderer = function($canvas, canvasContext) {
        var myself = self;
        var resolution = isRetina ? 2 : 1;
        var backgroundRatio = {
            width: 1,
            height: 1,
        };
        var offset = {
            x: 0,
            y: 0,
        }
        var backgroundDimensions = {
            cornerX: undefined,
            cornerY: undefined,
            width: undefined,
            height: undefined,
        };

        this.getBackgroundRatio = () => {
            return backgroundRatio;
        }

        this.setBackgroundRatio = (width, height) => {
            backgroundRatio.width = width;
            backgroundRatio.height = height;
        }

        this.setBackgroundDimensions = (cornerX, cornerY, width, height) => {
            backgroundDimensions = {
                cornerX: cornerX,
                cornerY: cornerY,
                width: width,
                height: height,
            };
        }

        this.getBackgroundDimensions = () => {
            return backgroundDimensions;
        }

        this.get$Canvas = () => {
            return $canvas;
        }

        this.getCanvas = () => {
            return canvas;
        }

        this.getContext = () => {
            return canvasContext;
        }

        this.convertCoordonateToBackground = (point, forDisplay) => {
            var r = forDisplay ? resolution : 1;
            return {
                x: (point.x * backgroundRatio.width + offset.x / resolution)* r,
                y: (point.y * backgroundRatio.height + offset.y / resolution)* r,
            };
        }

        this.convertBackgroundToCoordinate = (point, forDisplay) => {
            var r = forDisplay ? resolution : 1;
            return {
                x: (point.x / r - offset.x / resolution) / backgroundRatio.width,
                y: (point.y / r - offset.y / resolution) / backgroundRatio.height,
            };
        }

        this.convertValueToBackground = (value, forDisplay) => {
            var r = forDisplay ? resolution : 1;
            return value * backgroundRatio.width* r;
        }

        this.convertBackgroundToValue = (value, forDisplay) => {
            var r = forDisplay ? resolution : 1;
            return value / backgroundRatio.width/ r;
        }

        this.setOffset = (offsetX, offsetY) => {
            offset.x = offsetX;
            offset.y = offsetY;
        }

        this.getOffset = () => {
            return offset;
        }
    }

    return Renderer;
});
<|endoftext|>


<commit_before>class MCWorkflowFiltersComponentController {
    /*@ngInject*/
    constructor(experimentsAPI, mcStateStore, $stateParams) {
        this.experimentsAPI = experimentsAPI;
        this.mcStateStore = mcStateStore;
        this.projectId = $stateParams.project_id;
        this.experimentId = $stateParams.experiment_id;
        this.showSamplesFilter = false;
        this.showProcessesFilter = true;
    }

    $onInit() {
        this.activateProcessesFilter();
    }

    activateProcessesFilter() {
        let e = this.mcStateStore.getState('experiment');
        this.processes = _.values(e.processes);
        this.showProcessesFilter = true;
        this.showSamplesFilter = false;
        // this.experimentsAPI.getProcessesForExperiment(this.projectId, this.experimentId).then(
        //     (processes) => {
        //         this.showProcessesFilter = true;
        //         this.showSamplesFilter = false;
        //         this.processes = processes;
        //     }
        // );
    }

    activateSamplesFilter() {
        this.experimentsAPI.getSamplesForExperiment(this.projectId, this.experimentId).then(
            (samples) => {
                this.showProcessesFilter = false;
                this.showSamplesFilter = true;
                this.samples = samples;
            }
        );
    }
}

angular.module('materialscommons').component('mcWorkflowFilters', {
    template: require('./mc-workflow-filters.html'),
    controller: MCWorkflowFiltersComponentController
});
<commit_msg>Make samples filter the default filter<commit_after>class MCWorkflowFiltersComponentController {
    /*@ngInject*/
    constructor(experimentsAPI, mcStateStore, $stateParams) {
        this.experimentsAPI = experimentsAPI;
        this.mcStateStore = mcStateStore;
        this.projectId = $stateParams.project_id;
        this.experimentId = $stateParams.experiment_id;
        this.showSamplesFilter = true;
        this.showProcessesFilter = false;
    }

    $onInit() {
        this.activateSamplesFilter();
    }

    activateProcessesFilter() {
        let e = this.mcStateStore.getState('experiment');
        this.processes = _.values(e.processes);
        this.showProcessesFilter = true;
        this.showSamplesFilter = false;
    }

    activateSamplesFilter() {
        this.experimentsAPI.getSamplesForExperiment(this.projectId, this.experimentId).then(
            (samples) => {
                this.showProcessesFilter = false;
                this.showSamplesFilter = true;
                this.samples = samples;
            }
        );
    }
}

angular.module('materialscommons').component('mcWorkflowFilters', {
    template: require('./mc-workflow-filters.html'),
    controller: MCWorkflowFiltersComponentController
});
<|endoftext|>


<commit_before>window.serverUrl = 'http://lamk.net/api/';
changewidth();
var width = $(window).width()/3;
var windowWidth = $(window).width();
var position = 2;															// indicates selected category
var catCount = 0;

function layout(){															// adjusts the height of div "content"
	var height = $(window).height();
	$("#content").css("height",height-60+"px");
}

function changewidth(){														// adjust width of category divs
	var width = $(window).width()/3;
	$("#container").css("margin-left",+-((position-2)*width)+"px");			// adjusts the category positions
	var i;
	for(i = 1; i <= catCount; i++){											// loops through categorise and adjusts them
		$("#"+i).css("width",+width+"px");
		$("#"+i).css("margin-left",+((i-1)*width)+"px");
	}
}

function transitionleft(){													// swipe left
	$("#instruction"+position).hide();
	var width = $(window).width()/3;
	$("#container").animate({"margin-left":"-="+width+"px"}, "slow");		// category movement by animating margin change
	position++;																// updates the indicator of selected category
	if(position>catCount){													// checks if categories are going too far
		$("#container").animate({"margin-left":"+="+width+"px"}, "slow");	// if categories are going too far move them back
		position--;															// update position indicator
	}
	$("#instruction"+position).show();
}

function transitionright(){													// swipe right
	$("#instruction"+position).hide();
	var width = $(window).width()/3;
	$("#container").animate({"margin-left":"+="+width+"px"}, "slow");
	position--;
	if(position<1){
		$("#container").animate({"margin-left":"-="+width+"px"}, "slow");
		position++;
	}
	$("#instruction"+position).show();
}

$(document).ready(function(){
	layout();
	$(window).resize(function(){
		layout();
	});

	$.ajax({
		url: window.serverUrl,
		data: {act:'getcategories'},
		type: "GET",
		dataType: 'jsonp',
		crossDomain: true,
		cache : "false",
		success: function(data){
			if(data.status != 0){
				$(data.categories).each(function(i,item){
					$('#container').append('

'+item.name+'

');
					$('#instructions').append('

'+item.instructiontext+'

');
					$("#"+item.id).css("margin-left",+(i*width)+"px");
					$("#instruction"+item.id).hide();
					catCount = i+1;
				});
				changewidth();
			}
		}
	});
	$("#categories").swipe({												// waits for swipe at categories div
		swipe:function(event, direction, distance, duration, fingerCount){
			if(direction == "left"){
				transitionleft();
			}
			else if(direction == "right"){
				transitionright();
			}
		}
	});
});<commit_msg>kategoria valikon skaalautuvuus<commit_after>window.serverUrl = 'http://lamk.net/api/';
changewidth();
var width = $(window).width()/3;
var windowWidth = $(window).width();
var position = 2;															// indicates selected category
var catCount = 0;
var lastCategory;

function layout(){															// adjusts the height of div "content"
	var height = $(window).height();
	$("#content").css("height",height-60+"px");
}

function changewidth(){														// adjust width of category divs
	width = $(window).width()/3;
	$("#container").css("margin-left",+-((position-2)*width)+"px");			// adjusts the category positions
	var i;
	var textwidth = 0;
	var compare;
	for(i = 1; i <= lastCategory; i++){										// loops through categories and adjusts them
		$("#header"+i).css("width",+width+"px");
		$("#header"+i).css("margin-left",+(-(catCount-i)*width)+"px");
		compare = $("#header"+i+" > div").innerWidth();
		if(compare > textwidth){
			textwidth = compare;
		}
	}
	if(textwidth >= width){
		for(i = 1; i <= lastCategory; i++){
			$("#header"+i).css("width",+textwidth+"px");
			$("#header"+i).css("margin-left",+(-(catCount-i)*textwidth)+"px");
			windowWidth = $(window).width();
			$("#container").css("margin-left",+-(((position-2)*textwidth)+(textwidth*3-windowWidth)/2)+"px");
		}
	}
}

function transitionleft(){													// swipe left
	$("#instruction"+(catCount-1+position)).hide();
	width = $(window).width()/3;
	$("#container").animate({"margin-left":"-="+width+"px"}, "slow");		// category movement by animating margin change
	position++;																// updates the indicator of selected category
	if(position>catCount){													// checks if categories are going too far
		$("#container").animate({"margin-left":"+="+width+"px"}, "slow");	// if categories are going too far move them back
		position--;															// update position indicator
	}
	$("#instruction"+(catCount-1+position)).show();
}

function transitionright(){													// swipe right
	$("#instruction"+(catCount-1+position)).hide();
	width = $(window).width()/3;
	$("#container").animate({"margin-left":"+="+width+"px"}, "slow");
	position--;
	if(position<1){
		$("#container").animate({"margin-left":"-="+width+"px"}, "slow");
		position++;
	}
	$("#instruction"+(catCount-1+position)).show();
}

$(document).ready(function(){
	layout();
	$(window).resize(function(){
		layout();
	});

	$.ajax({
		url: window.serverUrl,
		data: {act:'getcategories'},
		type: "GET",
		dataType: 'jsonp',
		crossDomain: true,
		cache : "false",
		success: function(data){
			if(data.status != 0){
				$(data.categories).each(function(i,item){
					$('#container').append('

'+item.name+'

');
					$('#instructions').append('

'+item.instructiontext+'

');
					$("#header"+item.id).css("margin-left",+((i-1)*width)+"px");
					$("#instruction"+item.id).hide();
					catCount = i+1;
					lastCategory = item.id;
				});
				$("#instruction"+(catCount-1+position)).show();
				changewidth();
			}
		}
	});
	$("#categories").swipe({												// waits for swipe at categories div
		swipe:function(event, direction, distance, duration, fingerCount){
			if(direction == "left"){
				transitionleft();
			}
			else if(direction == "right"){
				transitionright();
			}
		}
	});
});<|endoftext|>


<commit_before>/***** BEGIN LICENSE BLOCK ***** {{{
Version: MPL 1.1/GPL 2.0/LGPL 2.1

The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.

Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>

Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
}}} ***** END LICENSE BLOCK *****/

// TODO:
//   - fix Sanitize autocommand
//   - add warning for TIMESPAN_EVERYTHING?
//   - respect privacy.clearOnShutdown et al or recommend VimperatorLeave autocommand?
//   - add support for :set sanitizeitems=all like 'eventignore'?
//   - integrate with the Clear Private Data dialog?

// FIXME:
//   - finish 1.9.0 support if we're going to support sanitizing in Xulmus

function Sanitizer() //{{{
{
    ////////////////////////////////////////////////////////////////////////////////
    ////////////////////// PRIVATE SECTION /////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    const local = {}; // XXX: is there some reason liberator.loadModule doesn't create modules with new?
    services.get("subscriptLoader").loadSubScript("chrome://browser/content/sanitize.js", local);
    const Sanitizer = local.Sanitizer;

    var prefArgList = [["commandLine",  "commandline"],
                       ["offlineApps",  "offlineapps"],
                       ["siteSettings", "sitesettings"]];

    function prefToArg(pref)
    {
        let pref = pref.replace(/.*\./, "");
        return util.Array.toObject(prefArgList)[pref] || pref;
    }

    function argToPref(arg) [k for ([, [k, v]] in Iterator(prefArgList)) if (v == arg)][0] || arg

    /////////////////////////////////////////////////////////////////////////////}}}
    ////////////////////// OPTIONS /////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    options.add(["sanitizeitems", "si"],
        "The default list of private items to sanitize",
        "stringlist", "cache,commandline,cookies,formdata,history,marks,sessions",
        {
            setter: function (values)
            {
                for (let [, pref] in Iterator(sanitizer.prefNames))
                {
                    options.setPref(pref, false);

                    for (let [, value] in Iterator(values.split(",")))
                    {
                        if (prefToArg(pref) == value)
                        {
                            options.setPref(pref, true);
                            break;
                        }
                    }
                }

                return values;
            },
            getter: function () sanitizer.prefNames.filter(function (pref) options.getPref(pref)).map(prefToArg).join(","),
            completer: function (value) [
                ["cache", "Cache"],
                ["commandline", "Command-line history"],
                ["cookies", "Cookies"],
                ["downloads", "Download history"],
                ["formdata", "Saved form and search history"],
                ["history", "Browsing history"],
                ["macros", "Saved macros"],
                ["marks", "Local and URL marks"],
                ["offlineapps", "Offline website data"],
                ["passwords", "Saved passwords"],
                ["sessions", "Authenticated sessions"],
                ["sitesettings", "Site preferences"],
            ],
            validator: Option.validateCompleter
        });

    options.add(["sanitizetimespan", "sts"],
        "The default sanitizer time span",
        "number", 1,
        {
            setter: function (value)
            {
                options.setPref("privacy.sanitize.timeSpan", value);
                return value;
            },
            getter: function () options.getPref("privacy.sanitize.timeSpan", this.defaultValue),
            completer: function (value) [
                ["0", "Everything"],
                ["1", "Last hour"],
                ["2", "Last two hours"],
                ["3", "Last four hours"],
                ["4", "Today"]
            ],
            validator: Option.validateCompleter
        });

    /////////////////////////////////////////////////////////////////////////////}}}
    ////////////////////// COMMANDS ////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    commands.add(["sa[nitize]"],
        "Clear private data",
        function (args)
        {
            if (options['private'])
                return void liberator.echomsg("Cannot sanitize items in private mode");

            let timespan = args["-timespan"] || options["sanitizetimespan"];

            sanitizer.range = Sanitizer.getClearRange(timespan);
            sanitizer.ignoreTimespan = !sanitizer.range;

            if (args.bang)
            {
                if (args.length > 0)
                    return void liberator.echoerr("E488: Trailing characters");

                liberator.log("Sanitizing all items in 'sanitizeitems'...");

                let errors = sanitizer.sanitize();

                if (errors)
                {
                    for (let item in errors)
                        liberator.echoerr("Error sanitizing " + item + ": " + errors[item]);
                }
            }
            else
            {
                if (args.length == 0)
                    return void liberator.echoerr("E471: Argument required");

                for (let [, item] in Iterator(args.map(argToPref)))
                {
                    liberator.log("Sanitizing " + item + " items...");

                    if (sanitizer.canClearItem(item))
                    {
                        try
                        {
                            sanitizer.clearItem(item);
                        }
                        catch (e)
                        {
                            liberator.echoerr("Error sanitizing " + item + ": " + e);
                        }
                    }
                    else
                        liberator.echomsg("Cannot sanitize " + item);
                }
            }
        },
        {
            argCount: "*", // FIXME: should be + and 0
            bang: true,
            completer: function (context) {
                context.title = ["Privacy Item", "Description"];
                context.completions = options.get("sanitizeitems").completer();
            },
            options: [
                [["-timespan", "-t"],
                 commands.OPTION_INT,
                 function (arg) /^[0-4]$/.test(arg),
                 function () options.get("sanitizetimespan").completer()]
             ]
        });

    /////////////////////////////////////////////////////////////////////////////}}}
    ////////////////////// PUBLIC SECTION //////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    var self = new Sanitizer();

    // TODO: remove this version test
    if (/^1.9.1/.test(services.get("xulAppInfo").platformVersion))
        self.prefDomain = "privacy.cpd.";
    else
        self.prefDomain = "privacy.item.";

    self.prefDomain2 = "extensions.liberator.privacy.cpd.";

    // add liberator-specific private items
    [
        {
            name: "commandLine",
            action: function ()
            {
                let stores = ["command", "search"];

                if (self.range)
                {
                    stores.forEach(function (store) {
                        storage["history-" + store].mutate("filter", function (item) {
                            let timestamp = item.timestamp * 1000;
                            return timestamp < self.range[0] || timestamp > self.range[1];
                        });
                    });
                }
                else
                    stores.forEach(function (store) { storage["history-" + store].truncate(0); });
            }
        },
        {
            name: "macros",
            action: function () { storage["macros"].clear(); }
        },
        {
            name: "marks",
            action: function ()
            {
                storage["local-marks"].clear();
                storage["url-marks"].clear();
            }
        }
    ].forEach(function (item) {
        let pref = self.prefDomain2 + item.name;

        if (options.getPref(pref) == null)
            options.setPref(pref, false);

        self.items[item.name] = {
            canClear: true,
            clear: item.action
        }
    });

    self.getClearRange = Sanitizer.getClearRange;

    // Largely ripped from from browser/base/content/sanitize.js so we can override
    // the pref strategy without stepping on the global prefs namespace.
    self.sanitize = function () {
        const prefService = services.get("pref");
        let branch = prefService.getBranch(this.prefDomain);
        let branch2 = prefService.getBranch(this.prefDomain2);
        let errors = null;

        function prefSet(name)
        {
            try
            {
                return branch.getBoolPref(name);
            }
            catch (e)
            {
                return branch2.getBoolPref(name);
            }
        }

        // Cache the range of times to clear
        if (this.ignoreTimespan)
            var range = null;  // If we ignore timespan, clear everything
        else
            range = this.range || Sanitizer.getClearRange();

        for (let itemName in this.items)
        {
            let item = this.items[itemName];
            item.range = range;

            if ("clear" in item && item.canClear && prefSet(itemName))
            {
                liberator.log("Sanitizing " + itemName + " items...");
                // Some of these clear() may raise exceptions (see bug #265028)
                // to sanitize as much as possible, we catch and store them,
                // rather than fail fast.
                // Callers should check returned errors and give user feedback
                // about items that could not be sanitized
                try
                {
                    item.clear();
                }
                catch (e)
                {
                    if (!errors)
                        errors = {};
                    errors[itemName] = e;
                    dump("Error sanitizing " + itemName + ": " + e + "\n");
                }
            }
        }

        return errors;
    };

    self.__defineGetter__("prefNames", function () {
        let ret = [];

        [self.prefDomain, self.prefDomain2].forEach(function (branch) {
            ret = ret.concat(services.get("pref").getBranch(branch).getChildList("", {}).map(function (pref) branch + pref));
        });

        return ret;
    });
    //}}}

    return self;

} //}}}

// vim: set fdm=marker sw=4 ts=4 et:
<commit_msg>Fix sanitizing range for non-liberator items.<commit_after>/***** BEGIN LICENSE BLOCK ***** {{{
Version: MPL 1.1/GPL 2.0/LGPL 2.1

The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.

Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>

Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
}}} ***** END LICENSE BLOCK *****/

// TODO:
//   - fix Sanitize autocommand
//   - add warning for TIMESPAN_EVERYTHING?
//   - respect privacy.clearOnShutdown et al or recommend VimperatorLeave autocommand?
//   - add support for :set sanitizeitems=all like 'eventignore'?
//   - integrate with the Clear Private Data dialog?

// FIXME:
//   - finish 1.9.0 support if we're going to support sanitizing in Xulmus

function Sanitizer() //{{{
{
    ////////////////////////////////////////////////////////////////////////////////
    ////////////////////// PRIVATE SECTION /////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    const local = {}; // XXX: is there some reason liberator.loadModule doesn't create modules with new?
    services.get("subscriptLoader").loadSubScript("chrome://browser/content/sanitize.js", local);
    const Sanitizer = local.Sanitizer;

    var prefArgList = [["commandLine",  "commandline"],
                       ["offlineApps",  "offlineapps"],
                       ["siteSettings", "sitesettings"]];

    function prefToArg(pref)
    {
        let pref = pref.replace(/.*\./, "");
        return util.Array.toObject(prefArgList)[pref] || pref;
    }

    function argToPref(arg) [k for ([, [k, v]] in Iterator(prefArgList)) if (v == arg)][0] || arg

    /////////////////////////////////////////////////////////////////////////////}}}
    ////////////////////// OPTIONS /////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    options.add(["sanitizeitems", "si"],
        "The default list of private items to sanitize",
        "stringlist", "cache,commandline,cookies,formdata,history,marks,sessions",
        {
            setter: function (values)
            {
                for (let [, pref] in Iterator(sanitizer.prefNames))
                {
                    options.setPref(pref, false);

                    for (let [, value] in Iterator(values.split(",")))
                    {
                        if (prefToArg(pref) == value)
                        {
                            options.setPref(pref, true);
                            break;
                        }
                    }
                }

                return values;
            },
            getter: function () sanitizer.prefNames.filter(function (pref) options.getPref(pref)).map(prefToArg).join(","),
            completer: function (value) [
                ["cache", "Cache"],
                ["commandline", "Command-line history"],
                ["cookies", "Cookies"],
                ["downloads", "Download history"],
                ["formdata", "Saved form and search history"],
                ["history", "Browsing history"],
                ["macros", "Saved macros"],
                ["marks", "Local and URL marks"],
                ["offlineapps", "Offline website data"],
                ["passwords", "Saved passwords"],
                ["sessions", "Authenticated sessions"],
                ["sitesettings", "Site preferences"],
            ],
            validator: Option.validateCompleter
        });

    options.add(["sanitizetimespan", "sts"],
        "The default sanitizer time span",
        "number", 1,
        {
            setter: function (value)
            {
                options.setPref("privacy.sanitize.timeSpan", value);
                return value;
            },
            getter: function () options.getPref("privacy.sanitize.timeSpan", this.defaultValue),
            completer: function (value) [
                ["0", "Everything"],
                ["1", "Last hour"],
                ["2", "Last two hours"],
                ["3", "Last four hours"],
                ["4", "Today"]
            ],
            validator: Option.validateCompleter
        });

    /////////////////////////////////////////////////////////////////////////////}}}
    ////////////////////// COMMANDS ////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    commands.add(["sa[nitize]"],
        "Clear private data",
        function (args)
        {
            if (options['private'])
                return void liberator.echomsg("Cannot sanitize items in private mode");

            let timespan = args["-timespan"] || options["sanitizetimespan"];

            sanitizer.range = Sanitizer.getClearRange(timespan);
            sanitizer.ignoreTimespan = !sanitizer.range;

            if (args.bang)
            {
                if (args.length > 0)
                    return void liberator.echoerr("E488: Trailing characters");

                liberator.log("Sanitizing all items in 'sanitizeitems'...");

                let errors = sanitizer.sanitize();

                if (errors)
                {
                    for (let item in errors)
                        liberator.echoerr("Error sanitizing " + item + ": " + errors[item]);
                }
            }
            else
            {
                if (args.length == 0)
                    return void liberator.echoerr("E471: Argument required");

                for (let [, item] in Iterator(args.map(argToPref)))
                {
                    liberator.log("Sanitizing " + item + " items...");

                    if (sanitizer.canClearItem(item))
                    {
                        try
                        {
                            sanitizer.items[item].range = sanitizer.range;
                            sanitizer.clearItem(item);
                        }
                        catch (e)
                        {
                            liberator.echoerr("Error sanitizing " + item + ": " + e);
                        }
                    }
                    else
                        liberator.echomsg("Cannot sanitize " + item);
                }
            }
        },
        {
            argCount: "*", // FIXME: should be + and 0
            bang: true,
            completer: function (context) {
                context.title = ["Privacy Item", "Description"];
                context.completions = options.get("sanitizeitems").completer();
            },
            options: [
                [["-timespan", "-t"],
                 commands.OPTION_INT,
                 function (arg) /^[0-4]$/.test(arg),
                 function () options.get("sanitizetimespan").completer()]
             ]
        });

    /////////////////////////////////////////////////////////////////////////////}}}
    ////////////////////// PUBLIC SECTION //////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////{{{

    var self = new Sanitizer();

    // TODO: remove this version test
    if (/^1.9.1/.test(services.get("xulAppInfo").platformVersion))
        self.prefDomain = "privacy.cpd.";
    else
        self.prefDomain = "privacy.item.";

    self.prefDomain2 = "extensions.liberator.privacy.cpd.";

    // add liberator-specific private items
    [
        {
            name: "commandLine",
            action: function ()
            {
                let stores = ["command", "search"];

                if (self.range)
                {
                    stores.forEach(function (store) {
                        storage["history-" + store].mutate("filter", function (item) {
                            let timestamp = item.timestamp * 1000;
                            return timestamp < self.range[0] || timestamp > self.range[1];
                        });
                    });
                }
                else
                    stores.forEach(function (store) { storage["history-" + store].truncate(0); });
            }
        },
        {
            name: "macros",
            action: function () { storage["macros"].clear(); }
        },
        {
            name: "marks",
            action: function ()
            {
                storage["local-marks"].clear();
                storage["url-marks"].clear();
            }
        }
    ].forEach(function (item) {
        let pref = self.prefDomain2 + item.name;

        if (options.getPref(pref) == null)
            options.setPref(pref, false);

        self.items[item.name] = {
            canClear: true,
            clear: item.action
        }
    });

    self.getClearRange = Sanitizer.getClearRange;

    // Largely ripped from from browser/base/content/sanitize.js so we can override
    // the pref strategy without stepping on the global prefs namespace.
    self.sanitize = function () {
        const prefService = services.get("pref");
        let branch = prefService.getBranch(this.prefDomain);
        let branch2 = prefService.getBranch(this.prefDomain2);
        let errors = null;

        function prefSet(name)
        {
            try
            {
                return branch.getBoolPref(name);
            }
            catch (e)
            {
                return branch2.getBoolPref(name);
            }
        }

        // Cache the range of times to clear
        if (this.ignoreTimespan)
            var range = null;  // If we ignore timespan, clear everything
        else
            range = this.range || Sanitizer.getClearRange();

        for (let itemName in this.items)
        {
            let item = this.items[itemName];
            item.range = range;

            if ("clear" in item && item.canClear && prefSet(itemName))
            {
                liberator.log("Sanitizing " + itemName + " items...");
                // Some of these clear() may raise exceptions (see bug #265028)
                // to sanitize as much as possible, we catch and store them,
                // rather than fail fast.
                // Callers should check returned errors and give user feedback
                // about items that could not be sanitized
                try
                {
                    item.clear();
                }
                catch (e)
                {
                    if (!errors)
                        errors = {};
                    errors[itemName] = e;
                    dump("Error sanitizing " + itemName + ": " + e + "\n");
                }
            }
        }

        return errors;
    };

    self.__defineGetter__("prefNames", function () {
        let ret = [];

        [self.prefDomain, self.prefDomain2].forEach(function (branch) {
            ret = ret.concat(services.get("pref").getBranch(branch).getChildList("", {}).map(function (pref) branch + pref));
        });

        return ret;
    });
    //}}}

    return self;

} //}}}

// vim: set fdm=marker sw=4 ts=4 et:
<|endoftext|>