<commit_before>//WARNING: no log() function usage before init.js

exports.core.device = 0
exports.core.vendor = ""

exports.core.trace = { key: false, focus: false, listeners: false }

/* ${init.js} */

if (log === null)
	log = console.log.bind(console)

/** @const */
/** @param {string} text @param {...} args */
_globals.qsTr = function(text, args) { return _globals._context.qsTr.apply(qml._context, arguments) }

var colorTable = {
	'maroon':	'800000',
	'red':		'ff0000',
	'orange':	'ffA500',
	'yellow':	'ffff00',
	'olive':	'808000',
	'purple':	'800080',
	'fuchsia':	'ff00ff',
	'white':	'ffffff',
	'lime':		'00ff00',
	'green':	'008000',
	'navy':		'000080',
	'blue':		'0000ff',
	'aqua':		'00ffff',
	'teal':		'008080',
	'black':	'000000',
	'silver':	'c0c0c0',
	'gray':		'080808',
	'transparent': '0000'
}

var safeCallImpl = function(callback, self, args, onError) {
	try { return callback.apply(self, args) } catch(ex) { onError(ex) }
}

exports.core.safeCall = function(self, args, onError) {
	return function(callback) { return safeCallImpl(callback, self, args, onError) }
}

/**
 * @constructor
 */
var CoreObjectComponent = exports.core.CoreObject = function() { }
var CoreObjectComponentPrototype = CoreObjectComponent.prototype
CoreObjectComponentPrototype.componentName = 'core.CoreObject'
CoreObjectComponentPrototype.constructor = CoreObjectComponent
CoreObjectComponentPrototype.__create = function() { }
CoreObjectComponentPrototype.__setup = function() { }

/** @constructor */
var Color = exports.core.Color = function(value) {
	if (Array.isArray(value)) {
		this.r = value[0]
		this.g = value[1]
		this.b = value[2]
		this.a = value[3] !== undefined? value[3]: 255
		return
	}
	if (typeof value !== 'string')
	{
		this.r = this.b = this.a = 255
		this.g = 0
		log("invalid color specification: " + value)
		return
	}
	var triplet
	if (value.substring(0, 4) == "rgba") {
		var b = value.indexOf('('), e = value.lastIndexOf(')')
		value = value.substring(b + 1, e).split(',')
		this.r = parseInt(value[0], 10)
		this.g = parseInt(value[1], 10)
		this.b = parseInt(value[2], 10)
		this.a = Math.floor(parseFloat(value[3]) * 255)
		return
	}
	else {
		var h = value[0]
		if (h != '#')
			triplet = colorTable[value]
		else
			triplet = value.substring(1)
	}
	if (!triplet) {
		this.r = 255
		this.g = 0
		this.b = 255
		log("invalid color specification: " + value)
		return
	}

	var len = triplet.length;
	if (len == 3 || len == 4) {
		var r = parseInt(triplet[0], 16)
		var g = parseInt(triplet[1], 16)
		var b = parseInt(triplet[2], 16)
		var a = (len == 4)? parseInt(triplet[3], 16): 15
		this.r = (r << 4) | r;
		this.g = (g << 4) | g;
		this.b = (b << 4) | b;
		this.a = (a << 4) | a;
	} else if (len == 6 || len == 8) {
		this.r = parseInt(triplet.substring(0, 2), 16)
		this.g = parseInt(triplet.substring(2, 4), 16)
		this.b = parseInt(triplet.substring(4, 6), 16)
		this.a = (len == 8)? parseInt(triplet.substring(6, 8), 16): 255
	} else
		throw new Error("invalid color specification: " + value)
}
var ColorPrototype = Color.prototype
ColorPrototype.constructor = exports.core.Color
/** @const */

ColorPrototype.rgba = function() {
	return "rgba(" + this.r + "," + this.g + "," + this.b + "," + (this.a / 255) + ")";
}

var hexByte = function(v) {
	return ('0' + (Number(v).toString(16))).slice(-2)
}

ColorPrototype.hex = function() {
	return '#' + hexByte(this.r) + hexByte(this.g) + hexByte(this.b) + hexByte(this.a)
}

exports.core.normalizeColor = function(spec) {
	return (new Color(spec)).rgba()
}

exports.core.mixColor = function(specA, specB, r) {
	var a = new Color(specA)
	var b = new Color(specB)
	var mix = function(a, b, r) { return Math.floor((b - a) * r + a) }
	return [mix(a.r, b.r, r), mix(a.g, b.g, r), mix(a.b, b.b, r), mix(a.a, b.a, r)]
}

/** @constructor */
exports.core.DelayedAction = function(context, action) {
	this.context = context
	this.action = function() {
		this._scheduled = false
		action()
	}.bind(this)
}

exports.core.DelayedAction.prototype.schedule = function() {
	if (!this._scheduled) {
		this._scheduled = true
		this.context.scheduleAction(this.action)
	}
}

exports.addLazyProperty = function(proto, name, creator) {
	var storageName = '__lazy_property_' + name
	var forwardName = '__forward_' + name

	var get = function(object) {
		var value = object[storageName]
		if (value !== undefined)
			return value
		else
			return (object[storageName] = creator(object))
	}

	Object.defineProperty(proto, name, {
		get: function() {
			return get(this)
		},

		set: function(newValue) {
			var forwardedTarget = this[forwardName]
			if (forwardedTarget !== undefined) {
				var target = get(this)
				if (target !== null && (target instanceof Object)) {
					//forward property update for mixins
					var forwardedValue = target[forwardedTarget]
					if (newValue !== forwardedValue) {
						target[forwardedTarget] = newValue
						this._update(name, newValue, forwardedValue)
					}
					return
				}
			}

			throw new Error('setting attempt on readonly lazy property ' + name + ' in ' + proto.componentName)
		},
		enumerable: true
	})
}

exports.addProperty = function(proto, type, name, defaultValue) {
	var convert
	switch(type) {
		case 'enum':
		case 'int':		convert = function(value) { return ~~value }; break
		case 'bool':	convert = function(value) { return value? true: false }; break
		case 'real':	convert = function(value) { return +value }; break
		case 'string':	convert = function(value) { return String(value) }; break
		default:		convert = function(value) { return value }; break
	}

	if (defaultValue !== undefined) {
		defaultValue = convert(defaultValue)
	} else {
		switch(type) {
			case 'enum': //fixme: add default value here
			case 'int':		defaultValue = 0; break
			case 'bool':	defaultValue = false; break
			case 'real':	defaultValue = 0.0; break
			case 'string':	defaultValue = ""; break
			case 'array':	defaultValue = []; break
			case 'Color':	defaultValue = '#0000'; break
			default:
				defaultValue = (type[0].toUpperCase() == type[0])? null: undefined
		}
	}

	var storageName = '__property_' + name
	var forwardName = '__forward_' + name

	Object.defineProperty(proto, name, {
		get: function() {
			var p = this[storageName]
			return p !== undefined?
				p.interpolatedValue !== undefined? p.interpolatedValue: p.value:
				defaultValue
		},

		set: function(newValue) {
			newValue = convert(newValue)
			var p = this[storageName]
			if (p === undefined) { //no storage
				if (newValue === defaultValue) //value == defaultValue, no storage allocation
					return

				p = this[storageName] = { value : defaultValue }
			}

			var animation = this.getAnimation(name)
			if (animation && p.value !== newValue) {
				var backend = this._context.backend
				if (p.frameRequest)
					backend.cancelAnimationFrame(p.frameRequest)

				p.started = Date.now()

				var src = p.interpolatedValue !== undefined? p.interpolatedValue: p.value
				var dst = newValue

				var self = this

				var complete = function() {
					backend.cancelAnimationFrame(p.frameRequest)
					p.frameRequest = undefined
					animation.complete = function() { }
					animation.running = false
					p.interpolatedValue = undefined
					p.started = undefined
					self._update(name, dst, src)
				}

				var duration = animation.duration

				var nextFrame = function() {
					var now = Date.now()
					var t = 1.0 * (now - p.started) / duration
					if (t >= 1) {
						complete()
					} else {
						p.interpolatedValue = convert(animation.interpolate(dst, src, t))
						self._update(name, p.interpolatedValue, src)
						p.frameRequest = backend.requestAnimationFrame(nextFrame)
					}
				}

				p.frameRequest = backend.requestAnimationFrame(nextFrame)

				animation.running = true
				animation.complete = complete
			}
			var oldValue = p.value
			if (oldValue !== newValue) {
				var forwardTarget = this[forwardName]
				if (forwardTarget !== undefined) {
					if (oldValue !== null && (oldValue instanceof Object)) {
						//forward property update for mixins
						var forwardedOldValue = oldValue[forwardTarget]
						if (newValue !== forwardedOldValue) {
							oldValue[forwardTarget] = newValue
							this._update(name, newValue, forwardedOldValue)
						}
						return
					} else if (newValue instanceof Object) {
						//first assignment of mixin
						this.connectOnChanged(newValue, forwardTarget, function(v, ov) { this._update(name, v, ov) }.bind(this))
					}
				}
				p.value = newValue
				if ((!animation || !animation.running) && newValue == defaultValue)
					delete this[storageName]
				if (!animation)
					this._update(name, newValue, oldValue)
			}
		},
		enumerable: true
	})
}

exports.addAliasProperty = function(self, name, getObject, srcProperty) {
	var target = getObject()
	self.connectOnChanged(target, srcProperty, function(value) { self._update(name, value) })

	Object.defineProperty(self, name, {
		get: function() { return target[srcProperty] },
		set: function(value) { target[srcProperty] = value },
		enumerable: true
	})
}

exports.core.createSignal = function(name) {
	return function() { COPY_ARGS(args, 0) this.emitWithArgs(name, args) }
}
exports.core.createSignalForwarder = function(object, name) {
	return (function() { COPY_ARGS(args, 0) object.emitWithArgs(name, args) })
}

/** @constructor */
exports.core.EventBinder = function(target) {
	this.target = target
	this.callbacks = {}
	this.enabled = false
}

exports.core.EventBinder.prototype.on = function(event, callback) {
	if (event in this.callbacks)
		throw new Error('double adding of event (' + event + ')')
	this.callbacks[event] = callback
	if (this.enabled)
		this.target.on(event, callback)
}

exports.core.EventBinder.prototype.constructor = exports.core.EventBinder

exports.core.EventBinder.prototype.enable = function(value) {
	if (value != this.enabled) {
		var target = this.target
		this.enabled = value
		if (value) {
			for(var event in this.callbacks)
				target.on(event, this.callbacks[event])
		} else {
			for(var event in this.callbacks)
				target.removeListener(event, this.callbacks[event])
		}
	}
}

var protoEvent = function(prefix, proto, name, callback) {
	var sname = '__' + prefix + '__' + name
	//if property was in base prototype, create shallow copy and put our handler there or we would add to base prototype's array
	var ownStorage = proto.hasOwnProperty(sname)
	var storage = proto[sname]
	if (storage != undefined) {
		if (ownStorage)
			storage.push(callback)
		else {
			var copy = storage.slice()
			copy.push(callback)
			proto[sname] = copy
		}
	} else
		proto[sname] = [callback]
}

exports.core._protoOn = function(proto, name, callback)
{ protoEvent('on', proto, name, callback) }

exports.core._protoOnChanged = function(proto, name, callback)
{ protoEvent('changed', proto, name, callback) }

exports.core._protoOnKey = function(proto, name, callback)
{ protoEvent('key', proto, name, callback) }

var ObjectEnumerator = function(callback) {
	this._callback = callback
	this._queue = []
	this.history = []
}

var ObjectEnumeratorPrototype = ObjectEnumerator.prototype
ObjectEnumeratorPrototype.constructor = ObjectEnumerator

ObjectEnumeratorPrototype.unshift = function() {
	var q = this._queue
	q.unshift.apply(q, arguments)
}

ObjectEnumeratorPrototype.push = function() {
	var q = this._queue
	q.push.apply(q, arguments)
}

ObjectEnumeratorPrototype.enumerate = function(root, arg) {
	var args = [this, arg]
	var queue = this._queue
	queue.unshift(root)
	while(queue.length) {
		var el = queue.shift()
		this.history.push(el)
		var r = this._callback.apply(el, args)
		if (r)
			break
	}
}

exports.forEach = function(root, callback, arg) {
	var oe = new ObjectEnumerator(callback)
	oe.enumerate(root, arg)
	return arg
}
<commit_msg>reformatted code a bit<commit_after>//WARNING: no log() function usage before init.js

exports.core.device = 0
exports.core.vendor = ""

exports.core.trace = { key: false, focus: false, listeners: false }

/* ${init.js} */

if (log === null)
	log = console.log.bind(console)

/** @const */
/** @param {string} text @param {...} args */
_globals.qsTr = function(text, args) { return _globals._context.qsTr.apply(qml._context, arguments) }

var colorTable = {
	'maroon':	'800000',
	'red':		'ff0000',
	'orange':	'ffA500',
	'yellow':	'ffff00',
	'olive':	'808000',
	'purple':	'800080',
	'fuchsia':	'ff00ff',
	'white':	'ffffff',
	'lime':		'00ff00',
	'green':	'008000',
	'navy':		'000080',
	'blue':		'0000ff',
	'aqua':		'00ffff',
	'teal':		'008080',
	'black':	'000000',
	'silver':	'c0c0c0',
	'gray':		'080808',
	'transparent': '0000'
}

var safeCallImpl = function(callback, self, args, onError) {
	try { return callback.apply(self, args) } catch(ex) { onError(ex) }
}

exports.core.safeCall = function(self, args, onError) {
	return function(callback) { return safeCallImpl(callback, self, args, onError) }
}

/**
 * @constructor
 */
var CoreObjectComponent = exports.core.CoreObject = function() { }
var CoreObjectComponentPrototype = CoreObjectComponent.prototype
CoreObjectComponentPrototype.componentName = 'core.CoreObject'
CoreObjectComponentPrototype.constructor = CoreObjectComponent
CoreObjectComponentPrototype.__create = function() { }
CoreObjectComponentPrototype.__setup = function() { }

/** @constructor */
var Color = exports.core.Color = function(value) {
	if (Array.isArray(value)) {
		this.r = value[0]
		this.g = value[1]
		this.b = value[2]
		this.a = value[3] !== undefined? value[3]: 255
		return
	}
	if (typeof value !== 'string')
	{
		this.r = this.b = this.a = 255
		this.g = 0
		log("invalid color specification: " + value)
		return
	}
	var triplet
	if (value.substring(0, 4) == "rgba") {
		var b = value.indexOf('('), e = value.lastIndexOf(')')
		value = value.substring(b + 1, e).split(',')
		this.r = parseInt(value[0], 10)
		this.g = parseInt(value[1], 10)
		this.b = parseInt(value[2], 10)
		this.a = Math.floor(parseFloat(value[3]) * 255)
		return
	}
	else {
		var h = value[0]
		if (h != '#')
			triplet = colorTable[value]
		else
			triplet = value.substring(1)
	}
	if (!triplet) {
		this.r = 255
		this.g = 0
		this.b = 255
		log("invalid color specification: " + value)
		return
	}

	var len = triplet.length;
	if (len == 3 || len == 4) {
		var r = parseInt(triplet[0], 16)
		var g = parseInt(triplet[1], 16)
		var b = parseInt(triplet[2], 16)
		var a = (len == 4)? parseInt(triplet[3], 16): 15
		this.r = (r << 4) | r;
		this.g = (g << 4) | g;
		this.b = (b << 4) | b;
		this.a = (a << 4) | a;
	} else if (len == 6 || len == 8) {
		this.r = parseInt(triplet.substring(0, 2), 16)
		this.g = parseInt(triplet.substring(2, 4), 16)
		this.b = parseInt(triplet.substring(4, 6), 16)
		this.a = (len == 8)? parseInt(triplet.substring(6, 8), 16): 255
	} else
		throw new Error("invalid color specification: " + value)
}
var ColorPrototype = Color.prototype
ColorPrototype.constructor = exports.core.Color
/** @const */

ColorPrototype.rgba = function() {
	return "rgba(" + this.r + "," + this.g + "," + this.b + "," + (this.a / 255) + ")";
}

var hexByte = function(v) {
	return ('0' + (Number(v).toString(16))).slice(-2)
}

ColorPrototype.hex = function() {
	return '#' + hexByte(this.r) + hexByte(this.g) + hexByte(this.b) + hexByte(this.a)
}

exports.core.normalizeColor = function(spec) {
	return (new Color(spec)).rgba()
}

exports.core.mixColor = function(specA, specB, r) {
	var a = new Color(specA)
	var b = new Color(specB)
	var mix = function(a, b, r) { return Math.floor((b - a) * r + a) }
	return [mix(a.r, b.r, r), mix(a.g, b.g, r), mix(a.b, b.b, r), mix(a.a, b.a, r)]
}

/** @constructor */
exports.core.DelayedAction = function(context, action) {
	this.context = context
	this.action = function() {
		this._scheduled = false
		action()
	}.bind(this)
}

exports.core.DelayedAction.prototype.schedule = function() {
	if (!this._scheduled) {
		this._scheduled = true
		this.context.scheduleAction(this.action)
	}
}

exports.addLazyProperty = function(proto, name, creator) {
	var storageName = '__lazy_property_' + name
	var forwardName = '__forward_' + name

	var get = function(object) {
		var value = object[storageName]
		if (value !== undefined)
			return value
		else
			return (object[storageName] = creator(object))
	}

	Object.defineProperty(proto, name, {
		get: function() {
			return get(this)
		},

		set: function(newValue) {
			var forwardedTarget = this[forwardName]
			if (forwardedTarget !== undefined) {
				var target = get(this)
				if (target !== null && (target instanceof Object)) {
					//forward property update for mixins
					var forwardedValue = target[forwardedTarget]
					if (newValue !== forwardedValue) {
						target[forwardedTarget] = newValue
						this._update(name, newValue, forwardedValue)
					}
					return
				}
			}

			throw new Error('setting attempt on readonly lazy property ' + name + ' in ' + proto.componentName)
		},
		enumerable: true
	})
}

exports.addProperty = function(proto, type, name, defaultValue) {
	var convert
	switch(type) {
		case 'enum':
		case 'int':		convert = function(value) { return ~~value }; break
		case 'bool':	convert = function(value) { return value? true: false }; break
		case 'real':	convert = function(value) { return +value }; break
		case 'string':	convert = function(value) { return String(value) }; break
		default:		convert = function(value) { return value }; break
	}

	if (defaultValue !== undefined) {
		defaultValue = convert(defaultValue)
	} else {
		switch(type) {
			case 'enum': //fixme: add default value here
			case 'int':		defaultValue = 0; break
			case 'bool':	defaultValue = false; break
			case 'real':	defaultValue = 0.0; break
			case 'string':	defaultValue = ""; break
			case 'array':	defaultValue = []; break
			case 'Color':	defaultValue = '#0000'; break
			default:
				defaultValue = (type[0].toUpperCase() == type[0])? null: undefined
		}
	}

	var storageName = '__property_' + name
	var forwardName = '__forward_' + name

	Object.defineProperty(proto, name, {
		get: function() {
			var p = this[storageName]
			return p !== undefined?
				p.interpolatedValue !== undefined? p.interpolatedValue: p.value:
				defaultValue
		},

		set: function(newValue) {
			newValue = convert(newValue)
			var p = this[storageName]
			if (p === undefined) { //no storage
				if (newValue === defaultValue) //value == defaultValue, no storage allocation
					return

				p = this[storageName] = { value : defaultValue }
			}

			var animation = this.getAnimation(name)
			if (animation && p.value !== newValue) {
				var backend = this._context.backend
				if (p.frameRequest)
					backend.cancelAnimationFrame(p.frameRequest)

				p.started = Date.now()

				var src = p.interpolatedValue !== undefined? p.interpolatedValue: p.value
				var dst = newValue

				var self = this

				var complete = function() {
					backend.cancelAnimationFrame(p.frameRequest)
					p.frameRequest = undefined
					animation.complete = function() { }
					animation.running = false
					p.interpolatedValue = undefined
					p.started = undefined
					self._update(name, dst, src)
				}

				var duration = animation.duration

				var nextFrame = function() {
					var now = Date.now()
					var t = 1.0 * (now - p.started) / duration
					if (t >= 1) {
						complete()
					} else {
						p.interpolatedValue = convert(animation.interpolate(dst, src, t))
						self._update(name, p.interpolatedValue, src)
						p.frameRequest = backend.requestAnimationFrame(nextFrame)
					}
				}

				p.frameRequest = backend.requestAnimationFrame(nextFrame)

				animation.running = true
				animation.complete = complete
			}
			var oldValue = p.value
			if (oldValue !== newValue) {
				var forwardTarget = this[forwardName]
				if (forwardTarget !== undefined) {
					if (oldValue !== null && (oldValue instanceof Object)) {
						//forward property update for mixins
						var forwardedOldValue = oldValue[forwardTarget]
						if (newValue !== forwardedOldValue) {
							oldValue[forwardTarget] = newValue
							this._update(name, newValue, forwardedOldValue)
						}
						return
					} else if (newValue instanceof Object) {
						//first assignment of mixin
						this.connectOnChanged(newValue, forwardTarget, function(v, ov) { this._update(name, v, ov) }.bind(this))
					}
				}
				p.value = newValue
				if ((!animation || !animation.running) && newValue == defaultValue)
					delete this[storageName]
				if (!animation)
					this._update(name, newValue, oldValue)
			}
		},
		enumerable: true
	})
}

exports.addAliasProperty = function(self, name, getObject, srcProperty) {
	var target = getObject()
	self.connectOnChanged(target, srcProperty, function(value) { self._update(name, value) })

	Object.defineProperty(self, name, {
		get: function() { return target[srcProperty] },
		set: function(value) { target[srcProperty] = value },
		enumerable: true
	})
}

exports.core.createSignal = function(name) {
	return function() {
		COPY_ARGS(args, 0)
		this.emitWithArgs(name, args)
	}
}
exports.core.createSignalForwarder = function(object, name) {
	return (function() {
		COPY_ARGS(args, 0)
		object.emitWithArgs(name, args)
	})
}

/** @constructor */
exports.core.EventBinder = function(target) {
	this.target = target
	this.callbacks = {}
	this.enabled = false
}

exports.core.EventBinder.prototype.on = function(event, callback) {
	if (event in this.callbacks)
		throw new Error('double adding of event (' + event + ')')
	this.callbacks[event] = callback
	if (this.enabled)
		this.target.on(event, callback)
}

exports.core.EventBinder.prototype.constructor = exports.core.EventBinder

exports.core.EventBinder.prototype.enable = function(value) {
	if (value != this.enabled) {
		var target = this.target
		this.enabled = value
		if (value) {
			for(var event in this.callbacks)
				target.on(event, this.callbacks[event])
		} else {
			for(var event in this.callbacks)
				target.removeListener(event, this.callbacks[event])
		}
	}
}

var protoEvent = function(prefix, proto, name, callback) {
	var sname = '__' + prefix + '__' + name
	//if property was in base prototype, create shallow copy and put our handler there or we would add to base prototype's array
	var ownStorage = proto.hasOwnProperty(sname)
	var storage = proto[sname]
	if (storage != undefined) {
		if (ownStorage)
			storage.push(callback)
		else {
			var copy = storage.slice()
			copy.push(callback)
			proto[sname] = copy
		}
	} else
		proto[sname] = [callback]
}

exports.core._protoOn = function(proto, name, callback)
{ protoEvent('on', proto, name, callback) }

exports.core._protoOnChanged = function(proto, name, callback)
{ protoEvent('changed', proto, name, callback) }

exports.core._protoOnKey = function(proto, name, callback)
{ protoEvent('key', proto, name, callback) }

var ObjectEnumerator = function(callback) {
	this._callback = callback
	this._queue = []
	this.history = []
}

var ObjectEnumeratorPrototype = ObjectEnumerator.prototype
ObjectEnumeratorPrototype.constructor = ObjectEnumerator

ObjectEnumeratorPrototype.unshift = function() {
	var q = this._queue
	q.unshift.apply(q, arguments)
}

ObjectEnumeratorPrototype.push = function() {
	var q = this._queue
	q.push.apply(q, arguments)
}

ObjectEnumeratorPrototype.enumerate = function(root, arg) {
	var args = [this, arg]
	var queue = this._queue
	queue.unshift(root)
	while(queue.length) {
		var el = queue.shift()
		this.history.push(el)
		var r = this._callback.apply(el, args)
		if (r)
			break
	}
}

exports.forEach = function(root, callback, arg) {
	var oe = new ObjectEnumerator(callback)
	oe.enumerate(root, arg)
	return arg
}
<|endoftext|>


<commit_before>angular.module('npact')
  .directive('npactGraphPage', function(STATIC_BASE_URL) {
    'use strict';
    return {
      restrict: 'A',
      templateUrl: STATIC_BASE_URL + 'js/graphs/page.html',
      controller: 'npactGraphPageCtrl',
      controllerAs: 'ctrl'
    };
  })

  .controller('npactGraphPageCtrl', function($scope, GraphDealer, Fetcher, npactConstants, $q, $log, StatusPoller, FETCH_URL, $window, $element, GraphConfig, Evt, TrackReader, GraphingCalculator) {
    'use strict';
    $scope.miscFiles = [];
    $scope.graphHeight = npactConstants.graphSpecDefaults.height;
    $scope.status = 'Initializing';
    $scope.ready = false;
    $scope.FETCH_URL = FETCH_URL;

    this.addMore = _.debounce(function(){
      $log.log('scrolling down via infinite scroller');
      GraphDealer.showMore();
    }, 250);

    var getWidth = function(){ return $element.width(); };
    $scope.$watch(getWidth, function(newValue, oldValue){
          if (newValue > 0){
            $log.log('width changed from', oldValue, '->', newValue);
            GraphConfig.width = newValue;
          }
    });

    var getGraphConfig = function() { return GraphConfig; };
    $scope.$watch(getGraphConfig, function(newValue, oldValue){
      var cmd = newValue.refreshCommand(oldValue);
      $log.log('graph config changed:', cmd);
      switch(cmd){
      case Evt.REBUILD:
        GraphDealer.rebuildGraphs();
        break;
      case Evt.REDRAW:
        $scope.$broadcast(cmd);
        break;
      }
    }, true); // deep-equality

    $scope.$on(Evt.PAN, function(evt, opts) {
      var offset = Math.floor(opts.newStartBase - opts.oldStartBase);
      GraphConfig.offset += offset;
      // TODO: Event originated from outside ng, but why doesn't
      // `$watch` pick up the `offset` change?
      $scope.$apply();
    });

    var addTrack = function(key, name, data) {
      return TrackReader.load(name, data)
        .then(function() { GraphConfig.loadTrack(name, key); });
    },
        addExtract = function(name, data) {
          return addTrack('extracts', name, data);
        },
        addHits = function(name, data) {
          return addTrack('hits', name, data);
        };;

    $scope.$on(Evt.ZOOM, function(evt, opts) {
      var res = GraphingCalculator.zoom(angular.extend({}, opts, GraphConfig));
      GraphConfig.offset = res.offset;
      GraphConfig.basesPerGraph = res.basesPerGraph;
      // TODO: Event originated from outside ng, but why doesn't
      // `$watch` pick up the `offset` change?
      $scope.$apply();
    });

    // check for scope changes on resize
    angular.element($window)
      .bind('resize', function () { $scope.$apply(); });

    // start it up
    Fetcher.kickstart()
      .then(function(config) {
        $log.log('Kickstart successful:', config);
        $scope.status = 'Running';
        $scope.config = config;
        // got config, request the first round of results
        $scope.title = config.first_page_title;
        var nprofile = Fetcher.nprofile(config).then(GraphDealer.setProfile);
        // Non-gbk files don't have CDSs we can extract.
        var inputFileCds = config.isgbk && Fetcher.inputFileCds(config)
              .then(function(data) { return addExtract('Input file CDS', data); });

        var extraFileList = Fetcher.acgtGammaFileList(config)
              .then(function(fileList) {
                $scope.miscFiles.push.apply($scope.miscFiles, fileList);
                Fetcher.fetchFile(config['File_of_new_CDSs'])
                  .then(function(data) {
                    return addExtract('Newly Identified ORFs', data);
                  });
                Fetcher.fetchFile(config['File_of_G+C_coding_potential_regions'])
                  .then(function(data) { addHits('Hits', data); });
              });
        $q.all([nprofile, inputFileCds, extraFileList])
          .then(function() {
            delete $scope.status;
          })
          .catch(function(err) {
            $scope.status = err;
          });

        StatusPoller.start(config['pdf_filename'])
          .then(function(pdfFilename) {
            $scope.miscFiles.push(pdfFilename);
          });
      });
  })

  .service('Fetcher', function(StatusPoller, $http, FETCH_URL, ACGT_GAMMA_FILE_LIST_URL, KICKSTART_BASE_URL, $window) {
    'use strict';
    /**
     * download contents from any url
     */
    function rawFile(url) {
      return $http.get(url).then(function(res) { return res.data; });
    }

    /**
     * download contents from a "fetch" path
     */
    function fetchFile(path){
      return rawFile(FETCH_URL + path);
    }

    this.rawFile = rawFile;
    this.fetchFile = fetchFile;
    this.kickstart = function(){
      return rawFile(KICKSTART_BASE_URL + $window.location.search);
    };
    this.nprofile = function(config) {
      return StatusPoller.start(config['nprofileData'])
        .then(fetchFile);
    };
    this.inputFileCds = function(config) {
      return StatusPoller.start(config['File_of_published_accepted_CDSs'])
        .then(fetchFile);
    };

    this.acgtGammaFileList = function(config) {
      return StatusPoller.start(config['acgt_gamma_output'])
        .then(function(path) {
          return rawFile(ACGT_GAMMA_FILE_LIST_URL + path);
        });
    };
  })

  .service('StatusPoller', function(STATUS_BASE_URL, $q, $http, $timeout, $log) {
    'use strict';
    var POLLTIME = 2500;

    function poller(tid, deferred) {
      // remember our arguments
      var pollAgain = _.partial(poller, tid, deferred);

      $http.get(STATUS_BASE_URL + tid)
        .then(function(res) {
          if(res.data.ready) { deferred.resolve(tid); }
          else { $timeout(pollAgain, POLLTIME); }
        })
        .catch(function(err) {
          $log.error('Error while fetching tid: ', tid, err);
          deferred.reject(err.data.message);
        });

      return deferred.promise;
    }

    this.start = function(tid) {
      if(!tid || tid.length === 0){
        return $q.reject(new Error('Invalid task id'));
      }

      return poller(tid, $q.defer());
    };
  });
<commit_msg>reorganize code<commit_after>angular.module('npact')
  .directive('npactGraphPage', function(STATIC_BASE_URL) {
    'use strict';
    return {
      restrict: 'A',
      templateUrl: STATIC_BASE_URL + 'js/graphs/page.html',
      controller: 'npactGraphPageCtrl',
      controllerAs: 'ctrl'
    };
  })

  .controller('npactGraphPageCtrl', function($scope, GraphDealer, Fetcher, npactConstants, $q, $log, StatusPoller, FETCH_URL, $window, $element, GraphConfig, Evt, TrackReader, GraphingCalculator) {
    'use strict';
    var self = this,
        getWidth = function(){ return $element.width(); },
        getGraphConfig = function() { return GraphConfig; },
        addTrack = function(key, name, data) {
          return TrackReader.load(name, data)
            .then(function() { GraphConfig.loadTrack(name, key); });
        },
        addExtract = function(name, data) {
          return addTrack('extracts', name, data);
        },
        addHits = function(name, data) {
          return addTrack('hits', name, data);
        }
    ;

    $scope.miscFiles = [];
    $scope.graphHeight = npactConstants.graphSpecDefaults.height;
    $scope.status = 'Initializing';
    $scope.ready = false;
    $scope.FETCH_URL = FETCH_URL;

    self.addMore = _.debounce(function(){
      $log.log('scrolling down via infinite scroller');
      GraphDealer.showMore();
    }, 250);

    $scope.$watch(getWidth, function(newValue, oldValue){
          if (newValue > 0){
            $log.log('width changed from', oldValue, '->', newValue);
            GraphConfig.width = newValue;
          }
    });

    $scope.$watch(getGraphConfig, function(newValue, oldValue){
      var cmd = newValue.refreshCommand(oldValue);
      $log.log('graph config changed:', cmd);
      switch(cmd){
      case Evt.REBUILD:
        GraphDealer.rebuildGraphs();
        break;
      case Evt.REDRAW:
        $scope.$broadcast(cmd);
        break;
      }
    }, true); // deep-equality

    $scope.$on(Evt.PAN, function(evt, opts) {
      var offset = Math.floor(opts.newStartBase - opts.oldStartBase);
      GraphConfig.offset += offset;
      // TODO: Event originated from outside ng, but why doesn't
      // `$watch` pick up the `offset` change?
      $scope.$apply();
    });

    $scope.$on(Evt.ZOOM, function(evt, opts) {
      var res = GraphingCalculator.zoom(angular.extend({}, opts, GraphConfig));
      GraphConfig.offset = res.offset;
      GraphConfig.basesPerGraph = res.basesPerGraph;
      // TODO: Event originated from outside ng, but why doesn't
      // `$watch` pick up the `offset` change?
      $scope.$apply();
    });

    // check for scope changes on resize
    angular.element($window).bind('resize', function () { $scope.$apply(); });

    // start it up
    Fetcher.kickstart()
      .then(function(config) {
        $log.log('Kickstart successful:', config);
        $scope.status = 'Running';
        $scope.config = config;
        // got config, request the first round of results
        $scope.title = config.first_page_title;
        var nprofile = Fetcher.nprofile(config).then(GraphDealer.setProfile);
        // Non-gbk files don't have CDSs we can extract.
        var inputFileCds = config.isgbk && Fetcher.inputFileCds(config)
              .then(function(data) { return addExtract('Input file CDS', data); });

        var extraFileList = Fetcher.acgtGammaFileList(config)
              .then(function(fileList) {
                $scope.miscFiles.push.apply($scope.miscFiles, fileList);
                Fetcher.fetchFile(config['File_of_new_CDSs'])
                  .then(function(data) {
                    return addExtract('Newly Identified ORFs', data);
                  });
                Fetcher.fetchFile(config['File_of_G+C_coding_potential_regions'])
                  .then(function(data) { addHits('Hits', data); });
              });
        $q.all([nprofile, inputFileCds, extraFileList])
          .then(function() {
            delete $scope.status;
          })
          .catch(function(err) {
            $scope.status = err;
          });

        StatusPoller.start(config['pdf_filename'])
          .then(function(pdfFilename) {
            $scope.miscFiles.push(pdfFilename);
          });
      });
  })

  .service('Fetcher', function(StatusPoller, $http, FETCH_URL, ACGT_GAMMA_FILE_LIST_URL, KICKSTART_BASE_URL, $window) {
    'use strict';
    /**
     * download contents from any url
     */
    function rawFile(url) {
      return $http.get(url).then(function(res) { return res.data; });
    }

    /**
     * download contents from a "fetch" path
     */
    function fetchFile(path){
      return rawFile(FETCH_URL + path);
    }

    this.rawFile = rawFile;
    this.fetchFile = fetchFile;
    this.kickstart = function(){
      return rawFile(KICKSTART_BASE_URL + $window.location.search);
    };
    this.nprofile = function(config) {
      return StatusPoller.start(config['nprofileData'])
        .then(fetchFile);
    };
    this.inputFileCds = function(config) {
      return StatusPoller.start(config['File_of_published_accepted_CDSs'])
        .then(fetchFile);
    };

    this.acgtGammaFileList = function(config) {
      return StatusPoller.start(config['acgt_gamma_output'])
        .then(function(path) {
          return rawFile(ACGT_GAMMA_FILE_LIST_URL + path);
        });
    };
  })

  .service('StatusPoller', function(STATUS_BASE_URL, $q, $http, $timeout, $log) {
    'use strict';
    var POLLTIME = 2500;

    function poller(tid, deferred) {
      // remember our arguments
      var pollAgain = _.partial(poller, tid, deferred);

      $http.get(STATUS_BASE_URL + tid)
        .then(function(res) {
          if(res.data.ready) { deferred.resolve(tid); }
          else { $timeout(pollAgain, POLLTIME); }
        })
        .catch(function(err) {
          $log.error('Error while fetching tid: ', tid, err);
          deferred.reject(err.data.message);
        });

      return deferred.promise;
    }

    this.start = function(tid) {
      if(!tid || tid.length === 0){
        return $q.reject(new Error('Invalid task id'));
      }

      return poller(tid, $q.defer());
    };
  });
<|endoftext|>


<commit_before>/**
 * @fileOverview Adds convenience properties and methods to  a
 * [JSGI 0.3 request object](http://wiki.commonjs.org/wiki/JSGI/Level0/A/Draft2#Request).
 */

var objects = require('ringo/utils/objects');
var {isUrlEncoded, parseParameters} = require('./parameters');
var {isFileUpload, parseFileUpload} = require('./fileupload');

var {Context, Scriptable} = org.mozilla.javascript;

export('Request', 'Session');

/**
 * Adds convenience properties and methods to  a
 * [JSGI 0.3 request object](http://wiki.commonjs.org/wiki/JSGI/Level0/A/Draft2#Request).
 *
 * @param request a JSGI 0.3 request object
 * @class Request
 */
function Request(request) {

    // check if request is already extended
    if (request.hasOwnProperty("path")) {
        return request;
    }

    var params, queryParams, postParams, cookies, session, headers;
    var servletRequest = request.env.servletRequest;

    /**
     * The name of the encoding used for this request
     * @name Request.instance.charset
     */
    request.charset = servletRequest.getCharacterEncoding();

    /**
     * The request's content type, or undefined if not available.
     * @name Request.instance.contentType
     */
    request.contentType = request.headers["content-type"];

    /**
     * The request's content length, or undefined if not available.
     * @name Request.instance.contentLength
     */
    request.contentLength = request.headers["content-length"];

    /**
     * The full URI path of the request.
     * @name Request.instance.path
     */
    request.path = request.scriptName + request.pathInfo;

    /**
     * The URL-decoded URI path.
     * @name Request.instance.pathDecoded
     */
    request.pathDecoded = decodeURI(request.path);

    /**
     * An object containing the parsed HTTP query string parameters sent with this request.
     * @name Request.instance.queryParams
     */
    Object.defineProperty(request, "queryParams", {
        get: function() {
            if (!queryParams) {
                queryParams = {};
                parseParameters(this.queryString, queryParams, this.charset);
            }
            return queryParams;
        }
    });

    /**
     * An object containing the parsed HTTP POST parameters sent with this request.
     * @name Request.instance.postParams
     */
    Object.defineProperty(request, "postParams", {
        get: function() {
            if (!postParams) {
                postParams = {};
                if (this.isPost || this.isPut) {
                    if (isUrlEncoded(this.contentType)) {
                        parseParameters(this.input.read(), postParams, this.charset);
                    } else if (isFileUpload(this.contentType)) {
                        parseFileUpload(this, postParams, this.charset);
                    }
                }
            }
            return postParams;
        }
    });

    /**
     * An object containing the parsed HTTP parameters sent with this request.
     * @name Request.instance.params
     */
    Object.defineProperty(request, "params", {
        get: function() {
            if (!params) {
                params = objects.merge(this.postParams, this.queryParams);
            }
            return params;
        }
    });

    /**
     * An object containing the HTTP cookie values sent with this request
     * @name Request.instance.cookies
     */
    Object.defineProperty(request, "cookies", {
        get: function() {
            if (!cookies) {
                cookies = new ScriptableMap();
                var servletCookies = servletRequest.getCookies();
                if (servletCookies) {
                    servletCookies.forEach(function(cookie) {
                        cookies[cookie.getName()] = cookie.getValue();
                    });
                }
            }
            return cookies;
        }
    });

    /**
     * A session object for the current request. If no session exists
     * a new one will be created.
     * @see Session
     * @name Request.instance.session
     */
    Object.defineProperty(request, "session", {
        get: function() {
            if (!session)
                session = new Session(this);
            return session;
        }
    });

    /**
     * Get a single request header value. If multiple headers exist for
     * the given name, only the first one is returned.
     * @name Request.instance.getHeader
     * @function
     */
    request.getHeader = function getHeader(name) {
        return request.headers[name.toLowerCase()];
    };

    /**
     * Get all header values for the given header name as an array.
     * @name Request.instance.getHeaders
     * @function
     */
    request.getHeaders = function getHeaders(name) {
        var headers = [];
        var servletHeaders = servletRequest.getHeaders(name);
        while (servletHeaders.hasMoreElements())
            headers.push(servletHeaders.nextElement());
        return headers;
    };

    /**
     * Reset the scriptName and pathInfo properties to their original values.
     * @name Request.instance.reset
     * @function
     */
    request.reset = function() {
        request.scriptName = servletRequest.getContextPath()
                           + servletRequest.getServletPath();
        request.pathInfo = servletRequest.getPathInfo();
    };

    /**
     * True if this is a HTTP GET request.
     * @name Request.instance.isGet
     */
    Object.defineProperty(request, "isGet", {
        get: function() {
            return this.method == "GET";
        }
    });

    /**
     * True if this is a HTTP POST request.
     * @name Request.instance.isPost
     */
    Object.defineProperty(request, "isPost", {
        get: function() {
            return this.method == "POST";
        }
    });

    /**
     * True if this is a HTTP PUT request.
     * @name Request.instance.isPut
     */
    Object.defineProperty(request, "isPut", {
        get: function() {
            return this.method == "PUT";
        }
    });

    /**
     * True if this is a HTTP DELETE request.
     * @name Request.instance.isDelete
     */
    Object.defineProperty(request, "isDelete", {
        get: function() {
            return this.method == "DELETE";
        }
    });

    /**
     * True if this is a HTTP HEAD request.
     * @name Request.instance.isHead
     */
    Object.defineProperty(request, "isHead", {
        get: function() {
            return this.method == "HEAD";
        }
    });

    /**
     * True if this is a XMLHttpRequest.
     * @name Request.instance.isXhr
     */
    Object.defineProperty(request, "isXhr", {
        get: function() {
            return this.headers["x-requested-with"] == "XMLHttpRequest";
        }
    });

    return request;
}

/**
 * An HTTP session object. Properties of the session's data
 * object are persisted between requests of the same client.
 * @param request a JSGI or servlet request object
 */
function Session(request) {

    var data;
    var servletRequest = request instanceof javax.servlet.ServletRequest ?
            request : request.env.servletRequest;

    function getSession() {
        return servletRequest.getSession();
    }

    /**
     * A container for things to store in this session between requests.
     */
    Object.defineProperty(this, "data", {
        get: function() {
            if (!data) {
                // session.data is a JavaAdapter that directly proxies property access
                // to the attributes in the servlet session object.
                data = new JavaAdapter(Scriptable, {
                    put: function(name, start, value) {
                        getSession().setAttribute(name, Context.jsToJava(value, java.lang.Object));
                    },
                    get: function(name, start) {
                        return Context.javaToJS(getSession().getAttribute(name), global);
                    }
                });
            }
            return data;
        }
    });

    /**
     * True if this session was created in the current request.
     * This can be useful to find out if the client has cookies disabled
     * for cookie-based sessions.
     */
    Object.defineProperty(this, "isNew", {
        get: function() {
            getSession().isNew();
        }
    })

}

<commit_msg>Add missing return statement<commit_after>/**
 * @fileOverview Adds convenience properties and methods to  a
 * [JSGI 0.3 request object](http://wiki.commonjs.org/wiki/JSGI/Level0/A/Draft2#Request).
 */

var objects = require('ringo/utils/objects');
var {isUrlEncoded, parseParameters} = require('./parameters');
var {isFileUpload, parseFileUpload} = require('./fileupload');

var {Context, Scriptable} = org.mozilla.javascript;

export('Request', 'Session');

/**
 * Adds convenience properties and methods to  a
 * [JSGI 0.3 request object](http://wiki.commonjs.org/wiki/JSGI/Level0/A/Draft2#Request).
 *
 * @param request a JSGI 0.3 request object
 * @class Request
 */
function Request(request) {

    // check if request is already extended
    if (request.hasOwnProperty("path")) {
        return request;
    }

    var params, queryParams, postParams, cookies, session, headers;
    var servletRequest = request.env.servletRequest;

    /**
     * The name of the encoding used for this request
     * @name Request.instance.charset
     */
    request.charset = servletRequest.getCharacterEncoding();

    /**
     * The request's content type, or undefined if not available.
     * @name Request.instance.contentType
     */
    request.contentType = request.headers["content-type"];

    /**
     * The request's content length, or undefined if not available.
     * @name Request.instance.contentLength
     */
    request.contentLength = request.headers["content-length"];

    /**
     * The full URI path of the request.
     * @name Request.instance.path
     */
    request.path = request.scriptName + request.pathInfo;

    /**
     * The URL-decoded URI path.
     * @name Request.instance.pathDecoded
     */
    request.pathDecoded = decodeURI(request.path);

    /**
     * An object containing the parsed HTTP query string parameters sent with this request.
     * @name Request.instance.queryParams
     */
    Object.defineProperty(request, "queryParams", {
        get: function() {
            if (!queryParams) {
                queryParams = {};
                parseParameters(this.queryString, queryParams, this.charset);
            }
            return queryParams;
        }
    });

    /**
     * An object containing the parsed HTTP POST parameters sent with this request.
     * @name Request.instance.postParams
     */
    Object.defineProperty(request, "postParams", {
        get: function() {
            if (!postParams) {
                postParams = {};
                if (this.isPost || this.isPut) {
                    if (isUrlEncoded(this.contentType)) {
                        parseParameters(this.input.read(), postParams, this.charset);
                    } else if (isFileUpload(this.contentType)) {
                        parseFileUpload(this, postParams, this.charset);
                    }
                }
            }
            return postParams;
        }
    });

    /**
     * An object containing the parsed HTTP parameters sent with this request.
     * @name Request.instance.params
     */
    Object.defineProperty(request, "params", {
        get: function() {
            if (!params) {
                params = objects.merge(this.postParams, this.queryParams);
            }
            return params;
        }
    });

    /**
     * An object containing the HTTP cookie values sent with this request
     * @name Request.instance.cookies
     */
    Object.defineProperty(request, "cookies", {
        get: function() {
            if (!cookies) {
                cookies = new ScriptableMap();
                var servletCookies = servletRequest.getCookies();
                if (servletCookies) {
                    servletCookies.forEach(function(cookie) {
                        cookies[cookie.getName()] = cookie.getValue();
                    });
                }
            }
            return cookies;
        }
    });

    /**
     * A session object for the current request. If no session exists
     * a new one will be created.
     * @see Session
     * @name Request.instance.session
     */
    Object.defineProperty(request, "session", {
        get: function() {
            if (!session)
                session = new Session(this);
            return session;
        }
    });

    /**
     * Get a single request header value. If multiple headers exist for
     * the given name, only the first one is returned.
     * @name Request.instance.getHeader
     * @function
     */
    request.getHeader = function getHeader(name) {
        return request.headers[name.toLowerCase()];
    };

    /**
     * Get all header values for the given header name as an array.
     * @name Request.instance.getHeaders
     * @function
     */
    request.getHeaders = function getHeaders(name) {
        var headers = [];
        var servletHeaders = servletRequest.getHeaders(name);
        while (servletHeaders.hasMoreElements())
            headers.push(servletHeaders.nextElement());
        return headers;
    };

    /**
     * Reset the scriptName and pathInfo properties to their original values.
     * @name Request.instance.reset
     * @function
     */
    request.reset = function() {
        request.scriptName = servletRequest.getContextPath()
                           + servletRequest.getServletPath();
        request.pathInfo = servletRequest.getPathInfo();
    };

    /**
     * True if this is a HTTP GET request.
     * @name Request.instance.isGet
     */
    Object.defineProperty(request, "isGet", {
        get: function() {
            return this.method == "GET";
        }
    });

    /**
     * True if this is a HTTP POST request.
     * @name Request.instance.isPost
     */
    Object.defineProperty(request, "isPost", {
        get: function() {
            return this.method == "POST";
        }
    });

    /**
     * True if this is a HTTP PUT request.
     * @name Request.instance.isPut
     */
    Object.defineProperty(request, "isPut", {
        get: function() {
            return this.method == "PUT";
        }
    });

    /**
     * True if this is a HTTP DELETE request.
     * @name Request.instance.isDelete
     */
    Object.defineProperty(request, "isDelete", {
        get: function() {
            return this.method == "DELETE";
        }
    });

    /**
     * True if this is a HTTP HEAD request.
     * @name Request.instance.isHead
     */
    Object.defineProperty(request, "isHead", {
        get: function() {
            return this.method == "HEAD";
        }
    });

    /**
     * True if this is a XMLHttpRequest.
     * @name Request.instance.isXhr
     */
    Object.defineProperty(request, "isXhr", {
        get: function() {
            return this.headers["x-requested-with"] == "XMLHttpRequest";
        }
    });

    return request;
}

/**
 * An HTTP session object. Properties of the session's data
 * object are persisted between requests of the same client.
 * @param request a JSGI or servlet request object
 */
function Session(request) {

    var data;
    var servletRequest = request instanceof javax.servlet.ServletRequest ?
            request : request.env.servletRequest;

    function getSession() {
        return servletRequest.getSession();
    }

    /**
     * A container for things to store in this session between requests.
     */
    Object.defineProperty(this, "data", {
        get: function() {
            if (!data) {
                // session.data is a JavaAdapter that directly proxies property access
                // to the attributes in the servlet session object.
                data = new JavaAdapter(Scriptable, {
                    put: function(name, start, value) {
                        getSession().setAttribute(name, Context.jsToJava(value, java.lang.Object));
                    },
                    get: function(name, start) {
                        return Context.javaToJS(getSession().getAttribute(name), global);
                    }
                });
            }
            return data;
        }
    });

    /**
     * True if this session was created in the current request.
     * This can be useful to find out if the client has cookies disabled
     * for cookie-based sessions.
     */
    Object.defineProperty(this, "isNew", {
        get: function() {
            return getSession().isNew();
        }
    })

}

<|endoftext|>


<commit_before>import _throttle from 'lodash-es/throttle';

import { select as d3_select } from 'd3-selection';
import { svgPath, svgPointTransform } from './helpers';
import { services } from '../services';

export function svgMapillaryImages(projection, context, dispatch) {
    var throttledRedraw = _throttle(function () { dispatch.call('change'); }, 1000);
    var minZoom = 12;
    var minMarkerZoom = 16;
    var minViewfieldZoom = 18;
    var layer = d3_select(null);
    var _mapillary;
    var viewerCompassAngle;

    function init() {
        if (svgMapillaryImages.initialized) return;  // run once
        svgMapillaryImages.enabled = false;
        svgMapillaryImages.initialized = true;
    }

    function getService() {
        if (services.mapillary && !_mapillary) {
            _mapillary = services.mapillary;
            _mapillary.event.on('loadedImages', throttledRedraw);
            _mapillary.event.on('bearingChanged', function(e) {
                viewerCompassAngle = e;

                // avoid updating if the map is currently transformed
                // e.g. during drags or easing.
                if (context.map().isTransformed()) return;

                layer.selectAll('.viewfield-group.currentView')
                    .filter(function(d) {
                        return d.pano;
                    })
                    .attr('transform', transform);
            });
        } else if (!services.mapillary && _mapillary) {
            _mapillary = null;
        }

        return _mapillary;
    }

    function showLayer() {
        var service = getService();
        if (!service) return;

        editOn();

        layer
            .style('opacity', 0)
            .transition()
            .duration(250)
            .style('opacity', 1)
            .on('end', function () { dispatch.call('change'); });
    }

    function hideLayer() {
        throttledRedraw.cancel();

        layer
            .transition()
            .duration(250)
            .style('opacity', 0)
            .on('end', editOff);
    }

    function editOn() {
        layer.style('display', 'block');
    }

    function editOff() {
        layer.selectAll('.viewfield-group').remove();
        layer.style('display', 'none');
    }

    function click(d) {
        var service = getService();
        if (!service) return;

        service
            .selectImage(context, d.key)
            .updateViewer(context, d.key)
            .showViewer(context);

        context.map().centerEase(d.loc);
    }

    function mouseover(d) {
        var service = getService();
        if (service) service.setStyles(context, d);
    }

    function mouseout() {
        var service = getService();
        if (service) service.setStyles(context, null);
    }

    function transform(d) {
        var t = svgPointTransform(projection)(d);
        if (d.pano && viewerCompassAngle !== null && isFinite(viewerCompassAngle)) {
            t += ' rotate(' + Math.floor(viewerCompassAngle) + ',0,0)';
        } else if (d.ca) {
            t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
        }
        return t;
    }

    context.photos().on('change.mapillary_images', update);

    function filterImages(images) {
        var showsPano = context.photos().showsPanoramic();
        var showsFlat = context.photos().showsFlat();
        var fromDate = context.photos().fromDate();
        var toDate = context.photos().toDate();
        var username = context.photos().username();

        if (!showsPano || !showsFlat) {
            images = images.filter(function(image) {
                if (image.pano) return showsPano;
                return showsFlat;
            });
        }
        if (fromDate) {
            var fromTimestamp = new Date(fromDate).getTime();
            images = images.filter(function(image) {
                return new Date(image.captured_at).getTime() >= fromTimestamp;
            });
        }
        if (toDate) {
            var toTimestamp = new Date(toDate).getTime();
            images = images.filter(function(image) {
                return new Date(image.captured_at).getTime() <= toTimestamp;
            });
        }
        if (username) {
            images = images.filter(function(image) {
                return image.captured_by === username;
            });
        }
        return images;
    }

    function filterSequences(sequences, service) {
        var showsPano = context.photos().showsPanoramic();
        var showsFlat = context.photos().showsFlat();
        var fromDate = context.photos().fromDate();
        var toDate = context.photos().toDate();
        var username = context.photos().username();

        if (!showsPano || !showsFlat) {
            sequences = sequences.filter(function(sequence) {
                if (sequence.properties.hasOwnProperty('pano')) {
                    if (sequence.properties.pano) return showsPano;
                    return showsFlat;
                } else {
                    // if the sequence doesn't specify pano or not, search its images
                    var cProps = sequence.properties.coordinateProperties;
                    if (cProps && cProps.image_keys && cProps.image_keys.length > 0) {
                        for (var index in cProps.image_keys) {
                            var imageKey = cProps.image_keys[index];
                            var image = service.cachedImage(imageKey);
                            if (image && image.hasOwnProperty('pano')) {
                                if (image.pano) return showsPano;
                                return showsFlat;
                            }
                        }
                    }
                }
            });
        }
        if (fromDate) {
            var fromTimestamp = new Date(fromDate).getTime();
            sequences = sequences.filter(function(sequence) {
                return new Date(sequence.captured_at).getTime() >= fromTimestamp;
            });
        }
        if (toDate) {
            var toTimestamp = new Date(toDate).getTime();
            sequences = sequences.filter(function(sequence) {
                return new Date(sequence.captured_at).getTime() <= toTimestamp;
            });
        }
        if (username) {
            sequences = sequences.filter(function(sequence) {
                return sequence.captured_by === username;
            });
        }
        return sequences;
    }

    function update() {

        var z = ~~context.map().zoom();
        var showMarkers = (z >= minMarkerZoom);
        var showViewfields = (z >= minViewfieldZoom);

        var service = getService();
        var selectedKey = service && service.getSelectedImageKey();
        var sequences = (service ? service.sequences(projection) : []);
        var images = (service && showMarkers ? service.images(projection) : []);

        images = filterImages(images);
        sequences = filterSequences(sequences, service);
        service.filterViewer(context);

        var traces = layer.selectAll('.sequences').selectAll('.sequence')
            .data(sequences, function(d) { return d.properties.key; });

        // exit
        traces.exit()
            .remove();

        // enter/update
        traces = traces.enter()
            .append('path')
            .attr('class', 'sequence')
            .merge(traces)
            .attr('d', svgPath(projection).geojson);

        var groups = layer.selectAll('.markers').selectAll('.viewfield-group')
            .data(images, function(d) { return d.key; });

        // exit
        groups.exit()
            .remove();

        // enter
        var groupsEnter = groups.enter()
            .append('g')
            .attr('class', 'viewfield-group')
            .on('mouseenter', mouseover)
            .on('mouseleave', mouseout)
            .on('click', click);

        groupsEnter
            .append('g')
            .attr('class', 'viewfield-scale');

        // update
        var markers = groups
            .merge(groupsEnter)
            .sort(function(a, b) {
                return (a.key === selectedKey) ? 1
                    : (b.key === selectedKey) ? -1
                    : b.loc[1] - a.loc[1];  // sort Y
            })
            .attr('transform', transform)
            .select('.viewfield-scale');

        markers.selectAll('circle')
            .data([0])
            .enter()
            .append('circle')
            .attr('dx', '0')
            .attr('dy', '0')
            .attr('r', '6');

        var viewfields = markers.selectAll('.viewfield')
            .data(showViewfields ? [0] : []);

        viewfields.exit()
            .remove();

        viewfields.enter()               // viewfields may or may not be drawn...
            .insert('path', 'circle')    // but if they are, draw below the circles
            .attr('class', 'viewfield')
            .classed('pano', function() { return this.parentNode.__data__.pano; })
            .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
            .attr('d', viewfieldPath);

        function viewfieldPath() {
            var d = this.parentNode.__data__;
            if (d.pano) {
                return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
            } else {
                return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
            }
        }
    }

    function drawImages(selection) {
        var enabled = svgMapillaryImages.enabled;
        var service = getService();

        layer = selection.selectAll('.layer-mapillary')
            .data(service ? [0] : []);

        layer.exit()
            .remove();

        var layerEnter = layer.enter()
            .append('g')
            .attr('class', 'layer-mapillary')
            .style('display', enabled ? 'block' : 'none');

        layerEnter
            .append('g')
            .attr('class', 'sequences');

        layerEnter
            .append('g')
            .attr('class', 'markers');

        layer = layerEnter
            .merge(layer);

        if (enabled) {
            if (service && ~~context.map().zoom() >= minZoom) {
                editOn();
                update();
                service.loadImages(projection);
            } else {
                editOff();
            }
        }
    }

    drawImages.enabled = function(_) {
        if (!arguments.length) return svgMapillaryImages.enabled;
        svgMapillaryImages.enabled = _;
        if (svgMapillaryImages.enabled) {
            showLayer();
        } else {
            hideLayer();
        }
        dispatch.call('change');
        return this;
    };

    drawImages.supported = function() {
        return !!getService();
    };

    init();
    return drawImages;
}
<commit_msg>fix: mapillary sequence filtering<commit_after>import _throttle from 'lodash-es/throttle';

import { select as d3_select } from 'd3-selection';
import { svgPath, svgPointTransform } from './helpers';
import { services } from '../services';

export function svgMapillaryImages(projection, context, dispatch) {
    var throttledRedraw = _throttle(function () { dispatch.call('change'); }, 1000);
    var minZoom = 12;
    var minMarkerZoom = 16;
    var minViewfieldZoom = 18;
    var layer = d3_select(null);
    var _mapillary;
    var viewerCompassAngle;

    function init() {
        if (svgMapillaryImages.initialized) return;  // run once
        svgMapillaryImages.enabled = false;
        svgMapillaryImages.initialized = true;
    }

    function getService() {
        if (services.mapillary && !_mapillary) {
            _mapillary = services.mapillary;
            _mapillary.event.on('loadedImages', throttledRedraw);
            _mapillary.event.on('bearingChanged', function(e) {
                viewerCompassAngle = e;

                // avoid updating if the map is currently transformed
                // e.g. during drags or easing.
                if (context.map().isTransformed()) return;

                layer.selectAll('.viewfield-group.currentView')
                    .filter(function(d) {
                        return d.pano;
                    })
                    .attr('transform', transform);
            });
        } else if (!services.mapillary && _mapillary) {
            _mapillary = null;
        }

        return _mapillary;
    }

    function showLayer() {
        var service = getService();
        if (!service) return;

        editOn();

        layer
            .style('opacity', 0)
            .transition()
            .duration(250)
            .style('opacity', 1)
            .on('end', function () { dispatch.call('change'); });
    }

    function hideLayer() {
        throttledRedraw.cancel();

        layer
            .transition()
            .duration(250)
            .style('opacity', 0)
            .on('end', editOff);
    }

    function editOn() {
        layer.style('display', 'block');
    }

    function editOff() {
        layer.selectAll('.viewfield-group').remove();
        layer.style('display', 'none');
    }

    function click(d) {
        var service = getService();
        if (!service) return;

        service
            .selectImage(context, d.key)
            .updateViewer(context, d.key)
            .showViewer(context);

        context.map().centerEase(d.loc);
    }

    function mouseover(d) {
        var service = getService();
        if (service) service.setStyles(context, d);
    }

    function mouseout() {
        var service = getService();
        if (service) service.setStyles(context, null);
    }

    function transform(d) {
        var t = svgPointTransform(projection)(d);
        if (d.pano && viewerCompassAngle !== null && isFinite(viewerCompassAngle)) {
            t += ' rotate(' + Math.floor(viewerCompassAngle) + ',0,0)';
        } else if (d.ca) {
            t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
        }
        return t;
    }

    context.photos().on('change.mapillary_images', update);

    function filterImages(images) {
        var showsPano = context.photos().showsPanoramic();
        var showsFlat = context.photos().showsFlat();
        var fromDate = context.photos().fromDate();
        var toDate = context.photos().toDate();
        var username = context.photos().username();

        if (!showsPano || !showsFlat) {
            images = images.filter(function(image) {
                if (image.pano) return showsPano;
                return showsFlat;
            });
        }
        if (fromDate) {
            var fromTimestamp = new Date(fromDate).getTime();
            images = images.filter(function(image) {
                return new Date(image.captured_at).getTime() >= fromTimestamp;
            });
        }
        if (toDate) {
            var toTimestamp = new Date(toDate).getTime();
            images = images.filter(function(image) {
                return new Date(image.captured_at).getTime() <= toTimestamp;
            });
        }
        if (username) {
            images = images.filter(function(image) {
                return image.captured_by === username;
            });
        }
        return images;
    }

    function filterSequences(sequences, service) {
        var showsPano = context.photos().showsPanoramic();
        var showsFlat = context.photos().showsFlat();
        var fromDate = context.photos().fromDate();
        var toDate = context.photos().toDate();
        var username = context.photos().username();

        if (!showsPano || !showsFlat) {
            sequences = sequences.filter(function(sequence) {
                if (sequence.properties.hasOwnProperty('pano')) {
                    if (sequence.properties.pano) return showsPano;
                    return showsFlat;
                } else {
                    // if the sequence doesn't specify pano or not, search its images
                    var cProps = sequence.properties.coordinateProperties;
                    if (cProps && cProps.image_keys && cProps.image_keys.length > 0) {
                        for (var index in cProps.image_keys) {
                            var imageKey = cProps.image_keys[index];
                            var image = service.cachedImage(imageKey);
                            if (image && image.hasOwnProperty('pano')) {
                                if (image.pano) return showsPano;
                                return showsFlat;
                            }
                        }
                    }
                }
            });
        }
        if (fromDate) {
            var fromTimestamp = new Date(fromDate).getTime();
            sequences = sequences.filter(function(sequence) {
                return new Date(sequence.properties.captured_at).getTime() >= fromTimestamp;
            });
        }
        if (toDate) {
            var toTimestamp = new Date(toDate).getTime();
            sequences = sequences.filter(function(sequence) {
                return new Date(sequence.properties.captured_at).getTime() <= toTimestamp;
            });
        }
        if (username) {
            sequences = sequences.filter(function(sequence) {
                return sequence.properties.username === username;
            });
        }

        return sequences;
    }

    function update() {

        var z = ~~context.map().zoom();
        var showMarkers = (z >= minMarkerZoom);
        var showViewfields = (z >= minViewfieldZoom);

        var service = getService();
        var selectedKey = service && service.getSelectedImageKey();
        var sequences = (service ? service.sequences(projection) : []);
        var images = (service && showMarkers ? service.images(projection) : []);

        images = filterImages(images);
        sequences = filterSequences(sequences, service);
        service.filterViewer(context);

        var traces = layer.selectAll('.sequences').selectAll('.sequence')
            .data(sequences, function(d) { return d.properties.key; });

        // exit
        traces.exit()
            .remove();

        // enter/update
        traces = traces.enter()
            .append('path')
            .attr('class', 'sequence')
            .merge(traces)
            .attr('d', svgPath(projection).geojson);

        var groups = layer.selectAll('.markers').selectAll('.viewfield-group')
            .data(images, function(d) { return d.key; });

        // exit
        groups.exit()
            .remove();

        // enter
        var groupsEnter = groups.enter()
            .append('g')
            .attr('class', 'viewfield-group')
            .on('mouseenter', mouseover)
            .on('mouseleave', mouseout)
            .on('click', click);

        groupsEnter
            .append('g')
            .attr('class', 'viewfield-scale');

        // update
        var markers = groups
            .merge(groupsEnter)
            .sort(function(a, b) {
                return (a.key === selectedKey) ? 1
                    : (b.key === selectedKey) ? -1
                    : b.loc[1] - a.loc[1];  // sort Y
            })
            .attr('transform', transform)
            .select('.viewfield-scale');

        markers.selectAll('circle')
            .data([0])
            .enter()
            .append('circle')
            .attr('dx', '0')
            .attr('dy', '0')
            .attr('r', '6');

        var viewfields = markers.selectAll('.viewfield')
            .data(showViewfields ? [0] : []);

        viewfields.exit()
            .remove();

        viewfields.enter()               // viewfields may or may not be drawn...
            .insert('path', 'circle')    // but if they are, draw below the circles
            .attr('class', 'viewfield')
            .classed('pano', function() { return this.parentNode.__data__.pano; })
            .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
            .attr('d', viewfieldPath);

        function viewfieldPath() {
            var d = this.parentNode.__data__;
            if (d.pano) {
                return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
            } else {
                return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
            }
        }
    }

    function drawImages(selection) {
        var enabled = svgMapillaryImages.enabled;
        var service = getService();

        layer = selection.selectAll('.layer-mapillary')
            .data(service ? [0] : []);

        layer.exit()
            .remove();

        var layerEnter = layer.enter()
            .append('g')
            .attr('class', 'layer-mapillary')
            .style('display', enabled ? 'block' : 'none');

        layerEnter
            .append('g')
            .attr('class', 'sequences');

        layerEnter
            .append('g')
            .attr('class', 'markers');

        layer = layerEnter
            .merge(layer);

        if (enabled) {
            if (service && ~~context.map().zoom() >= minZoom) {
                editOn();
                update();
                service.loadImages(projection);
            } else {
                editOff();
            }
        }
    }

    drawImages.enabled = function(_) {
        if (!arguments.length) return svgMapillaryImages.enabled;
        svgMapillaryImages.enabled = _;
        if (svgMapillaryImages.enabled) {
            showLayer();
        } else {
            hideLayer();
        }
        dispatch.call('change');
        return this;
    };

    drawImages.supported = function() {
        return !!getService();
    };

    init();
    return drawImages;
}
<|endoftext|>


<commit_before>/*global Stats:true*/

// extends src/nodes/time.js which extends src/node-box-native-view.js

$(function(){

  var template =
    '<button class="button" style="font-size:120%; position:absolute; overflow:hidden; top:0;right:0;bottom:0;left:0; width:100%; padding: 0; margin: 0;"></button>';

  Iframework.NativeNodes["ui-button"] = Iframework.NativeNodes["ui"].extend({

    template: _.template(template),
    info: {
      title: "button",
      description: "a button sends a bang, and you can attach a keyboard key"
    },
    initializeModule: function(){
      var self = this;
      this.$(".button")
        .click(function(e){
          self.inputbang();
        });
    },
    inputbang: function(){
      this.send("bang", "!");
      this.$(".button").addClass("active");

      var self = this;
      _.delay(function(){
        self.$(".button").removeClass("active");
      }, 100);
      return false;
    },
    inputlabel: function (label) {
      this._label = label;
      if (this._label === undefined) {
        label = "";
      }
      if (this._key && this._key !== "") {
        label += " ("+this._key+")";
      }
      this.$(".button").text(label);
    },
    inputkey: function(key){
      // Unbind the old
      if (this._key && this._key !== "") {
        Mousetrap.unbind(this._key, 'keydown');
        this._key = "";
      }
      if (key !== "") {
        var self = this;
        Mousetrap.bind(key, function(){
          self.inputbang();
        }, 'keydown');
        this._key = key;
      }

      // Reset label
      this.inputlabel(this._label);
    },
    remove: function(){
      if (this._key && this._key !== "") {
        Mousetrap.unbind(this._key, 'keydown');
      }
      this._key = "";
    },
    inputs: {
      bang: {
        type: "bang",
        description: "manual input bang"
      },
      label: {
        type: "string",
        description: "label for button",
        "default": ""
      },
      key: {
        type: "string",
        description: "For modifier keys you can use shift, ctrl, alt, option, meta, and command. Other special keys are backspace, tab, enter, return, capslock, esc, escape, space, pageup, pagedown, end, home, left, up, right, down, ins, and del. Can be a combination like \"shift+r\", or sequence like \"a b c\".",
        "default": ""
      }
    },
    outputs: {
      bang: {
        type: "bang"
      }
    }

  });

});
<commit_msg>button color config<commit_after>/*global Stats:true*/

// extends src/nodes/time.js which extends src/node-box-native-view.js

$(function(){

  var template =
    '<button class="button" style="font-size:120%; position:absolute; overflow:hidden; top:0;right:0;bottom:0;left:0; width:100%; padding: 0; margin: 0;"></button>';

  Iframework.NativeNodes["ui-button"] = Iframework.NativeNodes["ui"].extend({

    template: _.template(template),
    info: {
      title: "button",
      description: "a button sends a bang, and you can attach a keyboard key"
    },
    initializeModule: function(){
      var self = this;
      this.$(".button")
        .click(function(e){
          self.inputbang();
        });
    },
    inputbang: function(){
      this.send("bang", "!");
      this.$(".button").addClass("active");

      var self = this;
      _.delay(function(){
        self.$(".button").removeClass("active");
      }, 100);
      return false;
    },
    inputlabel: function (label) {
      this._label = label;
      if (this._label === undefined) {
        label = "";
      }
      if (this._key && this._key !== "") {
        label += " ("+this._key+")";
      }
      this.$(".button").text(label);
    },
    inputcolor: function (color) {
      this.$(".button").css("color", color);
    },
    inputbackground: function (color) {
      this.$(".button").css("background-color", color);
    },
    inputkey: function(key){
      // Unbind the old
      if (this._key && this._key !== "") {
        Mousetrap.unbind(this._key, 'keydown');
        this._key = "";
      }
      if (key !== "") {
        var self = this;
        Mousetrap.bind(key, function(){
          self.inputbang();
        }, 'keydown');
        this._key = key;
      }

      // Reset label
      this.inputlabel(this._label);
    },
    remove: function(){
      if (this._key && this._key !== "") {
        Mousetrap.unbind(this._key, 'keydown');
      }
      this._key = "";
    },
    inputs: {
      bang: {
        type: "bang",
        description: "manual input bang"
      },
      label: {
        type: "string",
        description: "label for button",
        "default": ""
      },
      color: {
        type: "color",
        description: "color of button text",
        "default": ""
      },
      background: {
        type: "color",
        description: "color of button background",
        "default": ""
      },
      key: {
        type: "string",
        description: "For modifier keys you can use shift, ctrl, alt, option, meta, and command. Other special keys are backspace, tab, enter, return, capslock, esc, escape, space, pageup, pagedown, end, home, left, up, right, down, ins, and del. Can be a combination like \"shift+r\", or sequence like \"a b c\".",
        "default": ""
      }
    },
    outputs: {
      bang: {
        type: "bang"
      }
    }

  });

});
<|endoftext|>


<commit_before>QUnit.module("Stomp Message");

QUnit.test("Send and receive a message", function (assert) {
  var done = assert.async();

  var body = Math.random();

  var client = stompClient();
  client.debug = TEST.debug;
  client.connect(TEST.login, TEST.password,
    function () {
      client.subscribe(TEST.destination, function (message) {
        assert.equal(message.body, body);
        client.disconnect();

        done();
      });

      client.send(TEST.destination, {}, body);
    });
});

QUnit.test("Send and receive a message with a JSON body", function (assert) {
  var done = assert.async();

  var client = stompClient();
  var payload = { text: "hello", bool: true, value: Math.random() };

  client.connect(TEST.login, TEST.password,
    function () {
      client.subscribe(TEST.destination, function (message) {
        var res = JSON.parse(message.body);
        assert.equal(res.text, payload.text);
        assert.equal(res.bool, payload.bool);
        assert.equal(res.value, payload.value);
        client.disconnect();

        done();
      });

      client.send(TEST.destination, {}, JSON.stringify(payload));
    });
});

QUnit.test("Send and receive a message with a multi-byte UTF8 string", function (assert) {
  var done = assert.async();

  var client = stompClient();
  var payload = "Älä sinä yhtään and السابق";

  client.connect(TEST.login, TEST.password,
    function () {
      client.subscribe(TEST.destination, function (message) {
        assert.equal(message.body, payload);
        assert.equal(message.body.length, 28);
        client.disconnect();

        done();
      });

      client.send(TEST.destination, {}, JSON.stringify(payload));
    });
});
<commit_msg>Escaping starting and ending quotes from payload.<commit_after>QUnit.module("Stomp Message");

QUnit.test("Send and receive a message", function (assert) {
  var done = assert.async();

  var body = Math.random();

  var client = stompClient();
  client.debug = TEST.debug;
  client.connect(TEST.login, TEST.password,
    function () {
      client.subscribe(TEST.destination, function (message) {
        assert.equal(message.body, body);
        client.disconnect();

        done();
      });

      client.send(TEST.destination, {}, body);
    });
});

QUnit.test("Send and receive a message with a JSON body", function (assert) {
  var done = assert.async();

  var client = stompClient();
  var payload = { text: "hello", bool: true, value: Math.random() };

  client.connect(TEST.login, TEST.password,
    function () {
      client.subscribe(TEST.destination, function (message) {
        var res = JSON.parse(message.body);
        assert.equal(res.text, payload.text);
        assert.equal(res.bool, payload.bool);
        assert.equal(res.value, payload.value);
        client.disconnect();

        done();
      });

      client.send(TEST.destination, {}, JSON.stringify(payload));
    });
});

QUnit.test("Send and receive a message with a multi-byte UTF8 string", function (assert) {
  var done = assert.async();

  var client = stompClient();
  var payload = "Älä sinä yhtään and السابق";

  client.connect(TEST.login, TEST.password,
    function () {
      client.subscribe(TEST.destination, function (message) {
        assert.equal(message.body.replace(/^"(.+(?="$))"$/, '$1'), payload);
        assert.equal(message.body.length, 28);
        client.disconnect();

        done();
      });

      client.send(TEST.destination, {}, JSON.stringify(payload));
    });
});
<|endoftext|>


<commit_before>import OAuthError from './OAuthError';
import OAuth from './OAuth';

export default class DummyFlow extends OAuth {

  /**
   * Authenticate
   * @returns {Promise} - Always rejects with OAuthError
   */
  authenticate() {
    return new Promise((resolve, reject) => {
      reject(new OAuthError('dummy_error', 'Attempted authentication using a dummy authenticator'));
    });
  }
}
<commit_msg>Make DummyFlow resolve if the a token was found<commit_after>import OAuthError from './OAuthError';
import OAuth from './OAuth';

/**
 * Dummy flow for when the token should be available in
 * the cache and no attempt at authentication should be made.
 */
export default class DummyFlow extends OAuth {

  /**
   * Authenticate
   * @returns {Promise} - Promise resolves with OAuthToken and rejects with OAuthError
   */
  authenticate() {
    return new Promise((resolve, reject) => {
      if (this.authenticated) {
        resolve(this.token);
      } else {
        reject(new OAuthError('dummy_error', 'Attempted authentication using a dummy authenticator'));
      }
    });
  }
}
<|endoftext|>


<commit_before><commit_msg>test(without): add initial tests<commit_after>var without = Redash.without

describe('(Function) without', function () {
  it('Should properly report its arity (is binary)', function () {
    without.should.have.length(2)
  })

  it('Should be curried', function () {
    without([1, 2, 3]).should.be.a('function')
  })

  it('Should exclude items in the first list from the second list', function () {
    without([1, 2, 3], [5,  4, 3, 2, 1])
      .should.deep.equal([5, 4])
  })

  it('Should return a new list even if no items are excluded', function () {
    var arr = [1, 2, 3, 4]
      , res = without([], arr)

    arr.should.deep.equal([1, 2, 3, 4])
    res.should.deep.equal([1, 2, 3, 4])
    res.should.not.equal(arr)
  })
})
<|endoftext|>