<commit_before>Ui.Container.extend('Ui.Box',
/**@lends Ui.Box#*/
{
	paddingTop: 0,
	paddingBottom: 0,
	paddingLeft: 0,
	paddingRight: 0,
	uniform: false,
	spacing: 0,
	star: 0,
	vertical: true,

	/**
	 * @constructs
	 * @class
	 * @extends Ui.Container
	 * @param {Number} [config.padding] Set the same padding for all borders
	 * @param {Number} [config.paddingTop]
	 * @param {Number} [config.paddingBottom]
	 * @param {Number} [config.paddingLeft]
	 * @param {Number} [config.paddingRight]
	 * @param {Boolean} [config.uniform] Whether or not the size of the container's children is uniform (will fit to the biggest element)
	 * @param {String}  [config.orientation] A Box can be either "vertical" (VBox) or "horizontal" (HBox). Very usefull for mobil device.
	 */
	constructor: function(config) {
	},

	setContent: function(content) {
		while(this.getFirstChild() != undefined)
			this.removeChild(this.getFirstChild());
		if((content != undefined) && (typeof(content) == 'object')) {
			if(content.constructor == Array) {
				for(var i = 0; i < content.length; i++)
					this.append(content[i]);
			}
			else
				this.append(content);
		}
	},

	/**
	 * Get the layout orientation.
	 * Possible values: [vertical|horizontal|
	 */
	getOrientation: function() {
		if(this.vertical)
			return 'vertical';
		else
			return 'horizontal';
	},

	/**
	 * Set the layout orientation.
	 * Possible values: [vertical|horizontal]
	 */
	setOrientation: function(orientation) {
		var vertical = true;
		if(orientation != 'vertical')
			vertical = false;
		if(this.vertical != vertical) {
			this.vertical = vertical;
			this.invalidateMeasure();
		}
	},

	/**
	 * Set the padding for all borders
	 */
	setPadding: function(padding) {
		this.setPaddingTop(padding);
		this.setPaddingBottom(padding);
		this.setPaddingLeft(padding);
		this.setPaddingRight(padding);
	},

	/**
	 * Return the current element top padding
	 */
	getPaddingTop: function() {
		return this.paddingTop;
	},

	/*
	 * Set the current element top padding
	 */
	setPaddingTop: function(paddingTop) {
		if(this.paddingTop != paddingTop) {
			this.paddingTop = paddingTop;
			this.invalidateMeasure();
		}
	},

	/**
	 * Return the current element bottom padding
	 */
	getPaddingBottom: function() {
		return this.paddingBottom;
	},

	/**
	 * Set the current element bottom padding
	 */
	setPaddingBottom: function(paddingBottom) {
		if(this.paddingBottom != paddingBottom) {
			this.paddingBottom = paddingBottom;
			this.invalidateMeasure();
		}
	},

	//
	// Return the current element left padding
	//
	getPaddingLeft: function() {
		return this.paddingLeft;
	},

	/**
	 * Set the current element left padding
	 */
	setPaddingLeft: function(paddingLeft) {
		if(this.paddingLeft != paddingLeft) {
			this.paddingLeft = paddingLeft;
			this.invalidateMeasure();
		}
	},

	/**
	 * Return the current element right padding
	 */
	getPaddingRight: function() {
		return this.paddingRight;
	},

	/**
	 * Set the current element right padding
	 */
	setPaddingRight: function(paddingRight) {
		if(this.paddingRight != paddingRight) {
			this.paddingRight = paddingRight;
			this.invalidateMeasure();
		}
	},

	/**
	 * True if all children will be arrange to have the
	 * same width
	 */
	getUniform: function() {
		return this.uniform;
	},

	/**
	 * Set true to force children arrangement to have the
	 * same width
	 */
	setUniform: function(uniform) {
		if(this.uniform != uniform) {
			this.uniform = uniform;
			this.invalidateMeasure();
		}
	},

	/**
	 * Return the space inserted between each
	 * child
	 */
	getSpacing: function() {
		return this.spacing;
	},

	/**
	 * Set the space value inserted between each child
	 */
	setSpacing: function(spacing) {
		if(this.spacing != spacing) {
			this.spacing = spacing;
			this.invalidateMeasure();
		}
	},

	/**
	 * Append a child at the end of the box
	 */
	append: function(child, resizable) {
		child = Ui.Element.create(child);
		if(resizable)
			Ui.Box.setResizable(child, true);
		this.appendChild(child);
	},

	/**
	 * Append a child at the begining of the box
	 */
	prepend: function(child, resizable) {
		child = Ui.Element.create(child);
		if(resizable)
			Ui.Box.setResizable(child, true);
		this.prependChild(child);
	},

	/**
	 * Insert a child element in the current box at the given position
	 */
	insertAt: function(child, position, resizable) {
		child = Ui.Element.create(child);
		if(resizable)
			Ui.Box.setResizable(child, true);
		this.insertChildAt(child, position);
	},

	/**
	 * Move a child element in the current box at the given position
	 */
	moveAt: function(child, position) {
		this.moveChildAt(child, position);
	},

	/**
	 * Remove a child from the box
	 */
	remove: function(child) {
		this.removeChild(child);
	},

	/**#@+
	* @private
	*/
	measureUniform: function(width, height) {
		var constraintSize = this.vertical?height:width;
		var constraintOpSize = this.vertical?width:height;

		constraintSize -= this.spacing * (this.getChildren().length - 1);
		var childConstraintSize = constraintSize / this.getChildren().length;
		var countResizable = 0;
		var uniformSize = 0;
		var minOpSize = 0;

		var loop = true;
		while(loop) {
			for(var i = 0; i < this.getChildren().length; i++) {
				var child = this.getChildren()[i];
				if(Ui.Box.getResizable(child))
					countResizable++;
				var size;
				if(this.vertical)
					size = child.measure(constraintOpSize, childConstraintSize);
				else
					size = child.measure(childConstraintSize, constraintOpSize);
				if((this.vertical?size.width:size.height) > minOpSize)
					minOpSize = this.vertical?size.width:size.height;
				if((this.vertical?size.height:size.width) > uniformSize)
					uniformSize = this.vertical?size.height:size.width;
			}
			if((minOpSize > constraintOpSize) || (uniformSize > childConstraintSize)) {
				if(uniformSize > childConstraintSize)
					childConstraintSize = uniformSize;
				constraintOpSize = minOpSize;
				minOpSize = 0;
				uniformSize = 0;
				countResizable = 0;
			}
			else
				loop = false;
		}
		if((countResizable > 0) && (uniformSize * this.getChildren().length < constraintSize))
			uniformSize = constraintSize / this.getChildren().length;

		this.uniformSize = uniformSize;
		var minSize = this.uniformSize * this.getChildren().length;
		minSize += this.spacing * (this.getChildren().length - 1);
		if(this.vertical)
			return { width: minOpSize, height: minSize };
		else
			return { width: minSize, height: minOpSize };
	},

	measureNonUniformVertical: function(width, height) {
		var constraintWidth = width;
		var constraintHeight = height;
		constraintHeight -= this.spacing * (this.getChildren().length - 1);

		var countResizable = 0;
		var minWidth = 0;
		var minHeight = 0;
		var loop = true;
		var star = 0;

		while(loop) {
			for(var i = 0; i < this.getChildren().length; i++) {
				var child = this.getChildren()[i];
				var size = child.measure(constraintWidth, 0);
				if(size.width > minWidth)
					minWidth = size.width;
				if(!Ui.Box.getResizable(child)) {
					minHeight += size.height;
				}
				else {
					child.boxStarDone = false;
					countResizable++;
				}
			}
			if(minWidth > constraintWidth) {
				constraintWidth = minWidth;
				minWidth = 0;
				minHeight = 0;
				countResizable = 0;
			}
			else
				loop = false;
		}
		if(countResizable > 0) {
			var remainHeight = constraintHeight - minHeight;
			var starFound = true;
			star = remainHeight / countResizable;
			do {
				starFound = true;
				for(var i = 0; i < this.getChildren().length; i++) {
					var child = this.getChildren()[i];
					if(Ui.Box.getResizable(child)) {
						if(!child.boxStarDone) {
							if(child.getMeasureHeight() > star) {
								child.boxStarDone = true;
								starFound = false;
								remainHeight -= child.getMeasureHeight();
								minHeight += child.getMeasureHeight();
								countResizable--;
								star = remainHeight / countResizable;
								break;
							}
							else {
								child.measure(constraintWidth, star);
							}
						}
					}
				}
			} while(!starFound);
		}
		minHeight += this.spacing * (this.getChildren().length - 1);
		if(countResizable > 0) {
			minHeight += star * countResizable;
			this.star = star;
		}
		else
			this.star = 0;
		return { width: minWidth, height: minHeight };
	},

	measureNonUniformHorizontal: function(width, height) {
		var constraintWidth = width;
		var constraintHeight = height;
		constraintWidth -= this.spacing * (this.getChildren().length - 1);

		var countResizable;
		var minWidth;
		var minHeight;
		var loop = true;

		while(loop) {
			countResizable = 0;
			minWidth = 0;
			minHeight = 0;

			// handle not resizable
			for(var i = 0; i < this.getChildren().length; i++) {
				var child = this.getChildren()[i];
				if(!Ui.Box.getResizable(child)) {
					var size = child.measure(0, constraintHeight);
					if(size.height > minHeight)
						minHeight = size.height;
					minWidth += size.width;
				}
				else {
					child.boxStarDone = false;
					countResizable++;
				}
			}
			if(countResizable > 0) {
				var remainWidth = constraintWidth - minWidth;
				var starFound = true;
				var star = remainWidth / countResizable;
				do {
					starFound = true;
					for(var i = 0; i < this.getChildren().length; i++) {
						var child = this.getChildren()[i];
						if(Ui.Box.getResizable(child)) {
							if(!child.boxStarDone) {
								var size = child.measure(star, constraintHeight);
								if(size.height > minHeight)
									minHeight = size.height;
								if(size.width > star) {
									child.boxStarDone = true;
									starFound = false;
									remainWidth -= size.width;
									minWidth += size.width;
									countResizable--;
									star = remainWidth / countResizable;
									break;
								}
							}
						}
					}
				} while(!starFound);
			}
			if(minHeight > constraintHeight)
				constraintHeight = minHeight;
			else
				loop = false;
		}

		minWidth += this.spacing * (this.getChildren().length - 1);
		if(countResizable > 0) {
			minWidth += star * countResizable;
			this.star = star;
		}
		else
			this.star = 0;
		return { width: minWidth, height: minHeight };
	}
	/**#@-*/
},
/**@lends Ui.Box#*/
{
	measureCore: function(width, height) {
		var left = this.getPaddingLeft();
		var right = this.getPaddingRight();
		var top = this.getPaddingTop();
		var bottom = this.getPaddingBottom();
		var constraintWidth = Math.max(0, width - (left + right));
		var constraintHeight = Math.max(0, height - (top + bottom));
		var size;

		if(this.uniform)
			size = this.measureUniform(constraintWidth, constraintHeight);
		else {
			if(this.vertical)
				size = this.measureNonUniformVertical(constraintWidth, constraintHeight);
			else
				size = this.measureNonUniformHorizontal(constraintWidth, constraintHeight);
		}
		size.width += left + right;
		size.height += top + bottom;
		return size;
	},

	arrangeCore: function(width, height) {
		var left = this.paddingLeft;
		var right = this.paddingRight;
		var top = this.paddingTop;
		var bottom = this.paddingBottom;
		width -= left + right;
		height -= top + bottom;

		var offset = this.vertical?top:left;
		for(var i = 0; i < this.getChildren().length; i++) {
			var child = this.getChildren()[i];
			if(i != 0)
				offset += this.spacing;

			if(this.uniform) {
				if(this.vertical)
					child.arrange(left, offset, width, this.uniformSize);
				else
					child.arrange(offset, top, this.uniformSize, height);
				offset += this.uniformSize;
			}
			else {
				if((Ui.Box.getResizable(child)) && ((this.vertical?child.getMeasureHeight():child.getMeasureWidth()) < this.star)) {
					if(this.vertical)
						child.arrange(left, offset, width, this.star);
					else
						child.arrange(offset, top, this.star, height);
					offset += this.star;
				}
				else {
					if(this.vertical) {
						child.arrange(left, offset, width, child.getMeasureHeight());
						offset += child.getMeasureHeight();
					}
					else {
						child.arrange(offset, top, child.getMeasureWidth(), height);
						offset += child.getMeasureWidth();
					}
				}
			}
		}
	}
}, {
	getResizable: function(child) {
		return child['Ui.Box.resizable']?true:false;
	},

	setResizable: function(child, resizable) {
		if(Ui.Box.getResizable(child) != resizable) {
			child['Ui.Box.resizable'] = resizable;
			child.invalidateMeasure();
		}
	}
});

Ui.Box.extend('Ui.VBox',
/**@lends Ui.VBox#*/
{
	/**
	*	@constructs
	*	@class
	*	@extends Ui.Box
	*/
	constructor: function(config) {
		this.setOrientation('vertical');
	}
});

Ui.Box.extend('Ui.HBox',
/**@lends Ui.HBox#*/
{
	/**
	*	@constructs
	*	@class
	*	@extends Ui.Box
	*/
	constructor: function(config) {
		this.setOrientation('horizontal');
	}
});
<commit_msg>set resizable attribute for each element added in Ui.Box. Prevent problem with element previously resizable but insert not resizable<commit_after>Ui.Container.extend('Ui.Box',
/**@lends Ui.Box#*/
{
	paddingTop: 0,
	paddingBottom: 0,
	paddingLeft: 0,
	paddingRight: 0,
	uniform: false,
	spacing: 0,
	star: 0,
	vertical: true,

	/**
	 * @constructs
	 * @class
	 * @extends Ui.Container
	 * @param {Number} [config.padding] Set the same padding for all borders
	 * @param {Number} [config.paddingTop]
	 * @param {Number} [config.paddingBottom]
	 * @param {Number} [config.paddingLeft]
	 * @param {Number} [config.paddingRight]
	 * @param {Boolean} [config.uniform] Whether or not the size of the container's children is uniform (will fit to the biggest element)
	 * @param {String}  [config.orientation] A Box can be either "vertical" (VBox) or "horizontal" (HBox). Very usefull for mobil device.
	 */
	constructor: function(config) {
	},

	setContent: function(content) {
		while(this.getFirstChild() != undefined)
			this.removeChild(this.getFirstChild());
		if((content != undefined) && (typeof(content) == 'object')) {
			if(content.constructor == Array) {
				for(var i = 0; i < content.length; i++)
					this.append(content[i]);
			}
			else
				this.append(content);
		}
	},

	/**
	 * Get the layout orientation.
	 * Possible values: [vertical|horizontal|
	 */
	getOrientation: function() {
		if(this.vertical)
			return 'vertical';
		else
			return 'horizontal';
	},

	/**
	 * Set the layout orientation.
	 * Possible values: [vertical|horizontal]
	 */
	setOrientation: function(orientation) {
		var vertical = true;
		if(orientation != 'vertical')
			vertical = false;
		if(this.vertical != vertical) {
			this.vertical = vertical;
			this.invalidateMeasure();
		}
	},

	/**
	 * Set the padding for all borders
	 */
	setPadding: function(padding) {
		this.setPaddingTop(padding);
		this.setPaddingBottom(padding);
		this.setPaddingLeft(padding);
		this.setPaddingRight(padding);
	},

	/**
	 * Return the current element top padding
	 */
	getPaddingTop: function() {
		return this.paddingTop;
	},

	/*
	 * Set the current element top padding
	 */
	setPaddingTop: function(paddingTop) {
		if(this.paddingTop != paddingTop) {
			this.paddingTop = paddingTop;
			this.invalidateMeasure();
		}
	},

	/**
	 * Return the current element bottom padding
	 */
	getPaddingBottom: function() {
		return this.paddingBottom;
	},

	/**
	 * Set the current element bottom padding
	 */
	setPaddingBottom: function(paddingBottom) {
		if(this.paddingBottom != paddingBottom) {
			this.paddingBottom = paddingBottom;
			this.invalidateMeasure();
		}
	},

	//
	// Return the current element left padding
	//
	getPaddingLeft: function() {
		return this.paddingLeft;
	},

	/**
	 * Set the current element left padding
	 */
	setPaddingLeft: function(paddingLeft) {
		if(this.paddingLeft != paddingLeft) {
			this.paddingLeft = paddingLeft;
			this.invalidateMeasure();
		}
	},

	/**
	 * Return the current element right padding
	 */
	getPaddingRight: function() {
		return this.paddingRight;
	},

	/**
	 * Set the current element right padding
	 */
	setPaddingRight: function(paddingRight) {
		if(this.paddingRight != paddingRight) {
			this.paddingRight = paddingRight;
			this.invalidateMeasure();
		}
	},

	/**
	 * True if all children will be arrange to have the
	 * same width
	 */
	getUniform: function() {
		return this.uniform;
	},

	/**
	 * Set true to force children arrangement to have the
	 * same width
	 */
	setUniform: function(uniform) {
		if(this.uniform != uniform) {
			this.uniform = uniform;
			this.invalidateMeasure();
		}
	},

	/**
	 * Return the space inserted between each
	 * child
	 */
	getSpacing: function() {
		return this.spacing;
	},

	/**
	 * Set the space value inserted between each child
	 */
	setSpacing: function(spacing) {
		if(this.spacing != spacing) {
			this.spacing = spacing;
			this.invalidateMeasure();
		}
	},

	/**
	 * Append a child at the end of the box
	 */
	append: function(child, resizable) {
		child = Ui.Element.create(child);
		Ui.Box.setResizable(child, resizable === true);
		this.appendChild(child);
	},

	/**
	 * Append a child at the begining of the box
	 */
	prepend: function(child, resizable) {
		child = Ui.Element.create(child);
		Ui.Box.setResizable(child, resizable === true);
		this.prependChild(child);
	},

	/**
	 * Insert a child element in the current box at the given position
	 */
	insertAt: function(child, position, resizable) {
		child = Ui.Element.create(child);
		Ui.Box.setResizable(child, resizable === true);
		this.insertChildAt(child, position);
	},

	/**
	 * Move a child element in the current box at the given position
	 */
	moveAt: function(child, position) {
		this.moveChildAt(child, position);
	},

	/**
	 * Remove a child from the box
	 */
	remove: function(child) {
		this.removeChild(child);
	},

	/**#@+
	* @private
	*/
	measureUniform: function(width, height) {
		var constraintSize = this.vertical?height:width;
		var constraintOpSize = this.vertical?width:height;

		constraintSize -= this.spacing * (this.getChildren().length - 1);
		var childConstraintSize = constraintSize / this.getChildren().length;
		var countResizable = 0;
		var uniformSize = 0;
		var minOpSize = 0;

		var loop = true;
		while(loop) {
			for(var i = 0; i < this.getChildren().length; i++) {
				var child = this.getChildren()[i];
				if(Ui.Box.getResizable(child))
					countResizable++;
				var size;
				if(this.vertical)
					size = child.measure(constraintOpSize, childConstraintSize);
				else
					size = child.measure(childConstraintSize, constraintOpSize);
				if((this.vertical?size.width:size.height) > minOpSize)
					minOpSize = this.vertical?size.width:size.height;
				if((this.vertical?size.height:size.width) > uniformSize)
					uniformSize = this.vertical?size.height:size.width;
			}
			if((minOpSize > constraintOpSize) || (uniformSize > childConstraintSize)) {
				if(uniformSize > childConstraintSize)
					childConstraintSize = uniformSize;
				constraintOpSize = minOpSize;
				minOpSize = 0;
				uniformSize = 0;
				countResizable = 0;
			}
			else
				loop = false;
		}
		if((countResizable > 0) && (uniformSize * this.getChildren().length < constraintSize))
			uniformSize = constraintSize / this.getChildren().length;

		this.uniformSize = uniformSize;
		var minSize = this.uniformSize * this.getChildren().length;
		minSize += this.spacing * (this.getChildren().length - 1);
		if(this.vertical)
			return { width: minOpSize, height: minSize };
		else
			return { width: minSize, height: minOpSize };
	},

	measureNonUniformVertical: function(width, height) {
		var constraintWidth = width;
		var constraintHeight = height;
		constraintHeight -= this.spacing * (this.getChildren().length - 1);

		var countResizable = 0;
		var minWidth = 0;
		var minHeight = 0;
		var loop = true;
		var star = 0;

		while(loop) {
			for(var i = 0; i < this.getChildren().length; i++) {
				var child = this.getChildren()[i];
				var size = child.measure(constraintWidth, 0);
				if(size.width > minWidth)
					minWidth = size.width;
				if(!Ui.Box.getResizable(child)) {
					minHeight += size.height;
				}
				else {
					child.boxStarDone = false;
					countResizable++;
				}
			}
			if(minWidth > constraintWidth) {
				constraintWidth = minWidth;
				minWidth = 0;
				minHeight = 0;
				countResizable = 0;
			}
			else
				loop = false;
		}
		if(countResizable > 0) {
			var remainHeight = constraintHeight - minHeight;
			var starFound = true;
			star = remainHeight / countResizable;
			do {
				starFound = true;
				for(var i = 0; i < this.getChildren().length; i++) {
					var child = this.getChildren()[i];
					if(Ui.Box.getResizable(child)) {
						if(!child.boxStarDone) {
							if(child.getMeasureHeight() > star) {
								child.boxStarDone = true;
								starFound = false;
								remainHeight -= child.getMeasureHeight();
								minHeight += child.getMeasureHeight();
								countResizable--;
								star = remainHeight / countResizable;
								break;
							}
							else {
								child.measure(constraintWidth, star);
							}
						}
					}
				}
			} while(!starFound);
		}
		minHeight += this.spacing * (this.getChildren().length - 1);
		if(countResizable > 0) {
			minHeight += star * countResizable;
			this.star = star;
		}
		else
			this.star = 0;
		return { width: minWidth, height: minHeight };
	},

	measureNonUniformHorizontal: function(width, height) {
		var constraintWidth = width;
		var constraintHeight = height;
		constraintWidth -= this.spacing * (this.getChildren().length - 1);

		var countResizable;
		var minWidth;
		var minHeight;
		var loop = true;

		while(loop) {
			countResizable = 0;
			minWidth = 0;
			minHeight = 0;

			// handle not resizable
			for(var i = 0; i < this.getChildren().length; i++) {
				var child = this.getChildren()[i];
				if(!Ui.Box.getResizable(child)) {
					var size = child.measure(0, constraintHeight);
					if(size.height > minHeight)
						minHeight = size.height;
					minWidth += size.width;
				}
				else {
					child.boxStarDone = false;
					countResizable++;
				}
			}
			if(countResizable > 0) {
				var remainWidth = constraintWidth - minWidth;
				var starFound = true;
				var star = remainWidth / countResizable;
				do {
					starFound = true;
					for(var i = 0; i < this.getChildren().length; i++) {
						var child = this.getChildren()[i];
						if(Ui.Box.getResizable(child)) {
							if(!child.boxStarDone) {
								var size = child.measure(star, constraintHeight);
								if(size.height > minHeight)
									minHeight = size.height;
								if(size.width > star) {
									child.boxStarDone = true;
									starFound = false;
									remainWidth -= size.width;
									minWidth += size.width;
									countResizable--;
									star = remainWidth / countResizable;
									break;
								}
							}
						}
					}
				} while(!starFound);
			}
			if(minHeight > constraintHeight)
				constraintHeight = minHeight;
			else
				loop = false;
		}

		minWidth += this.spacing * (this.getChildren().length - 1);
		if(countResizable > 0) {
			minWidth += star * countResizable;
			this.star = star;
		}
		else
			this.star = 0;
		return { width: minWidth, height: minHeight };
	}
	/**#@-*/
},
/**@lends Ui.Box#*/
{
	measureCore: function(width, height) {
		var left = this.getPaddingLeft();
		var right = this.getPaddingRight();
		var top = this.getPaddingTop();
		var bottom = this.getPaddingBottom();
		var constraintWidth = Math.max(0, width - (left + right));
		var constraintHeight = Math.max(0, height - (top + bottom));
		var size;

		if(this.uniform)
			size = this.measureUniform(constraintWidth, constraintHeight);
		else {
			if(this.vertical)
				size = this.measureNonUniformVertical(constraintWidth, constraintHeight);
			else
				size = this.measureNonUniformHorizontal(constraintWidth, constraintHeight);
		}
		size.width += left + right;
		size.height += top + bottom;
		return size;
	},

	arrangeCore: function(width, height) {
		var left = this.paddingLeft;
		var right = this.paddingRight;
		var top = this.paddingTop;
		var bottom = this.paddingBottom;
		width -= left + right;
		height -= top + bottom;

		var offset = this.vertical?top:left;
		for(var i = 0; i < this.getChildren().length; i++) {
			var child = this.getChildren()[i];
			if(i != 0)
				offset += this.spacing;

			if(this.uniform) {
				if(this.vertical)
					child.arrange(left, offset, width, this.uniformSize);
				else
					child.arrange(offset, top, this.uniformSize, height);
				offset += this.uniformSize;
			}
			else {
				if((Ui.Box.getResizable(child)) && ((this.vertical?child.getMeasureHeight():child.getMeasureWidth()) < this.star)) {
					if(this.vertical)
						child.arrange(left, offset, width, this.star);
					else
						child.arrange(offset, top, this.star, height);
					offset += this.star;
				}
				else {
					if(this.vertical) {
						child.arrange(left, offset, width, child.getMeasureHeight());
						offset += child.getMeasureHeight();
					}
					else {
						child.arrange(offset, top, child.getMeasureWidth(), height);
						offset += child.getMeasureWidth();
					}
				}
			}
		}
	}
}, {
	getResizable: function(child) {
		return child['Ui.Box.resizable']?true:false;
	},

	setResizable: function(child, resizable) {
		if(Ui.Box.getResizable(child) != resizable) {
			child['Ui.Box.resizable'] = resizable;
			child.invalidateMeasure();
		}
	}
});

Ui.Box.extend('Ui.VBox',
/**@lends Ui.VBox#*/
{
	/**
	*	@constructs
	*	@class
	*	@extends Ui.Box
	*/
	constructor: function(config) {
		this.setOrientation('vertical');
	}
});

Ui.Box.extend('Ui.HBox',
/**@lends Ui.HBox#*/
{
	/**
	*	@constructs
	*	@class
	*	@extends Ui.Box
	*/
	constructor: function(config) {
		this.setOrientation('horizontal');
	}
});
<|endoftext|>


<commit_before>module.exports = {
  refreshOnSave : true,
  indexConfig :{
    settings: {
      index: {
        analysis :{
          analyzer: {
            email: {
              type : 'custom',
              tokenizer : 'uax_url_email',
              filter : ['standard', 'lowercase', 'stop']
            },
            sort: {
              type: 'custom',
              tokenizer: 'keyword',
              filter: 'lowercase'
            }
          }
        }
      }
    }
  },
  entities: [{
    base: 'cd',
    name: 'dojos',
    indexedAttributes: {
      'id': {
        type: 'string',
        index: 'not_analyzed'
      },
      'name': {
        'type': 'string',
        'fields': {
          'raw': {'type': 'string', analyzer: 'sort'}
        }
      },
      'creator': {
        type: 'string',
        index: 'not_analyzed'
      },
      'created': true,
      'verifiedAt': true,
      'verifiedBy': {
        type: 'string',
        index: 'not_analyzed'
      },
      'verified': true,
      'needMentors': true,
      'stage': true,
      'time': true,
      'country': true,
      'county': true,
      'state': true,
      'city': true,
      'place': true,
      'location': true,
      'coordinates': true,
      'geoPoint': {
        type: 'geo_point'
      },
      'notes': true,
      'email': {
        'analyzer': 'email',
        'type': 'string'
      },
      'website': true,
      'twitter': true,
      'googleGroup': true,
      'ebId': true,
      'supporterImage': true,
      'private': true,
      'urlSlug': true,
      'continent': true,
      'alpha2': true,
      'alpha3': true,
      'address1': true,
      'address2': true,
      'countryNumber': true,
      'countryName': true,
      'admin1Code': true,
      'admin1Name': true,
      'admin2Code': true,
      'admin2Name': true,
      'admin3Code': true,
      'admin3Name': true,
      'admin4Code': true,
      'admin4Name': true,
      'placeGeonameId': true,
      'placeName': true
    }
  }, {
    base: 'cd',
    name: 'dojoleads',
    indexedAttributes: {
      'id': {
        type: 'string',
        index: 'not_analyzed'
      },
      'userId': {
        type: 'string',
        index: 'not_analyzed'
      },
      'application': true,
      'email': {
        'analyzer': 'email',
        'type': 'string'
      },
      'currentStep': true,
      'completed': true
    }
  }]
};<commit_msg>Update mapping<commit_after>module.exports = {
  refreshOnSave : true,
  indexConfig :{
    settings: {
      index: {
        analysis :{
          analyzer: {
            email: {
              type : 'custom',
              tokenizer : 'uax_url_email',
              filter : ['standard', 'lowercase', 'stop']
            },
            sort: {
              type: 'custom',
              tokenizer: 'keyword',
              filter: 'lowercase'
            }
          }
        }
      }
    }
  },
  entities: [{
    base: 'cd',
    name: 'dojos',
    indexedAttributes: {
      'id': {
        type: 'string',
        index: 'not_analyzed'
      },
      'name': {
        'type': 'string',
        'fields': {
          'sort': {'type': 'string', analyzer: 'sort'},
          'search': {'type': 'string'}
        }
      },
      'creator': {
        type: 'string',
        index: 'not_analyzed'
      },
      'created': true,
      'verifiedAt': true,
      'verifiedBy': {
        type: 'string',
        index: 'not_analyzed'
      },
      'verified': true,
      'needMentors': true,
      'stage': true,
      'time': true,
      'country': true,
      'county': true,
      'state': true,
      'city': true,
      'place': true,
      'location': {'type': 'string'},
      'coordinates': true,
      'geoPoint': {
        type: 'geo_point'
      },
      'notes': true,
      'email': {
        'analyzer': 'email',
        'type': 'string'
      },
      'website': true,
      'twitter': true,
      'googleGroup': true,
      'ebId': true,
      'supporterImage': true,
      'private': true,
      'urlSlug': true,
      'continent': true,
      'alpha2': true,
      'alpha3': true,
      'address1': true,
      'address2': true,
      'countryNumber': true,
      'countryName': true,
      'admin1Code': true,
      'admin1Name': true,
      'admin2Code': true,
      'admin2Name': true,
      'admin3Code': true,
      'admin3Name': true,
      'admin4Code': true,
      'admin4Name': true,
      'placeGeonameId': true,
      'placeName': true
    }
  }, {
    base: 'cd',
    name: 'dojoleads',
    indexedAttributes: {
      'id': {
        type: 'string',
        index: 'not_analyzed'
      },
      'userId': {
        type: 'string',
        index: 'not_analyzed'
      },
      'application': true,
      'email': {
        'analyzer': 'email',
        'type': 'string'
      },
      'currentStep': true,
      'completed': true
    }
  }]
};<|endoftext|>


<commit_before>import { lstat, readdir } from 'fs';
import * as path from 'path';

import promisify from 'es6-promisify';

export var lstatPromise = promisify(lstat);
export var readdirPromise = promisify(readdir);

export function walkPromise(curPath) {
  var result = {};
  // Set a basePath var with the initial path
  // so all file paths (the result keys) can
  // be relative to the starting point.
  var basePath = curPath;

  return (function walk(curPath) {
    return lstatPromise(curPath)
      .then((stat) => {
        if (stat.isFile()) {
          var { size, ...other } = stat;
          result[path.relative(basePath, curPath)] = { size };
        } else if (stat.isDirectory()) {
          return readdirPromise(curPath)
            .then((files) => {
              // Map the list of files and make a list of readdir
              // promises to pass to Promise.all so we can recursively
              // get the data on all the files in the directory.
              return Promise.all(files.map((fileName) => {
                return walk(path.join(curPath, fileName));
              }));
            })
            .then(() => {
              return result;
            });
        }
      });
  })(curPath);
}
<commit_msg>Fix lint violation<commit_after>import { lstat, readdir } from 'fs';
import * as path from 'path';

import promisify from 'es6-promisify';

export var lstatPromise = promisify(lstat);
export var readdirPromise = promisify(readdir);

export function walkPromise(curPath) {
  var result = {};
  // Set a basePath var with the initial path
  // so all file paths (the result keys) can
  // be relative to the starting point.
  var basePath = curPath;

  return (function walk(curPath) {
    return lstatPromise(curPath)
      .then((stat) => {
        if (stat.isFile()) {
          var { size } = stat;
          result[path.relative(basePath, curPath)] = { size };
        } else if (stat.isDirectory()) {
          return readdirPromise(curPath)
            .then((files) => {
              // Map the list of files and make a list of readdir
              // promises to pass to Promise.all so we can recursively
              // get the data on all the files in the directory.
              return Promise.all(files.map((fileName) => {
                return walk(path.join(curPath, fileName));
              }));
            })
            .then(() => {
              return result;
            });
        }
      });
  })(curPath);
}
<|endoftext|>


<commit_before>const StageLayering = require('../engine/stage-layering');

class Video {
    constructor (runtime) {
        this.runtime = runtime;

        /**
         * @typedef VideoProvider
         * @property {Function} enableVideo - Requests camera access from the user, and upon success,
         * enables the video feed
         * @property {Function} disableVideo - Turns off the video feed
         * @property {Function} getFrame - Return frame data from the video feed in
         * specified dimensions, format, and mirroring.
         */
        this.provider = null;

        /**
         * Id representing a Scratch Renderer skin the video is rendered to for
         * previewing.
         * @type {number}
         */
        this._skinId = -1;

        /**
         * The Scratch Renderer Skin object.
         * @type {Skin}
         */
        this._skin = null;

        /**
         * Id for a drawable using the video's skin that will render as a video
         * preview.
         * @type {Drawable}
         */
        this._drawable = -1;

        /**
         * Store the last state of the video transparency ghost effect
         * @type {number}
         */
        this._ghost = 0;
    }

    static get FORMAT_IMAGE_DATA () {
        return 'image-data';
    }

    static get FORMAT_CANVAS () {
        return 'canvas';
    }

    /**
     * Dimensions the video stream is analyzed at after its rendered to the
     * sample canvas.
     * @type {Array.<number>}
     */
    static get DIMENSIONS () {
        return [480, 360];
    }

    /**
     * Order preview drawable is inserted at in the renderer.
     * @type {number}
     */
    static get ORDER () {
        return 1;
    }

    /**
     * Set a video provider for this device. A default implementation of
     * a video provider can be found in scratch-gui/src/lib/video/video-provider
     * @param {VideoProvider} provider - Video provider to use
     */
    setProvider (provider) {
        this.provider = provider;
    }

    /**
     * Request video be enabled.  Sets up video, creates video skin and enables preview.
     *
     * ioDevices.video.requestVideo()
     *
     * @return {Promise.<Video>} resolves a promise to this IO device when video is ready.
     */
    enableVideo () {
        if (!this.provider) return null;
        return this.provider.enableVideo().then(() => this._setupPreview());
    }

    /**
     * Disable video stream (turn video off)
     * @return {void}
     */
    disableVideo () {
        this._disablePreview();
        if (!this.provider) return null;
        this.provider.disableVideo();
    }

    /**
     * Return frame data from the video feed in a specified dimensions, format, and mirroring.
     *
     * @param {object} frameInfo A descriptor of the frame you would like to receive.
     * @param {Array.<number>} frameInfo.dimensions [width, height] array of numbers.  Defaults to [480,360]
     * @param {boolean} frameInfo.mirror If you specificly want a mirror/non-mirror frame, defaults to the global
     *                                   mirror state (ioDevices.video.mirror)
     * @param {string} frameInfo.format Requested video format, available formats are 'image-data' and 'canvas'.
     * @param {number} frameInfo.cacheTimeout Will reuse previous image data if the time since capture is less than
     *                                        the cacheTimeout.  Defaults to 16ms.
     *
     * @return {ArrayBuffer|Canvas|string|null} Frame data in requested format, null when errors.
     */
    getFrame ({
        dimensions = Video.DIMENSIONS,
        mirror = this.mirror,
        format = Video.FORMAT_IMAGE_DATA,
        cacheTimeout = this._frameCacheTimeout
    }) {
        if (this.provider) return this.provider.getFrame({dimensions, mirror, format, cacheTimeout});
        return null;
    }

    /**
     * Set the preview ghost effect
     * @param {number} ghost from 0 (visible) to 100 (invisible) - ghost effect
     */
    setPreviewGhost (ghost) {
        this._ghost = ghost;
        if (this._drawable) {
            this.runtime.renderer.updateDrawableProperties(this._drawable, {ghost});
        }
    }

    _disablePreview () {
        if (this._skin) {
            this._skin.clear();
            this.runtime.renderer.updateDrawableProperties(this._drawable, {visible: false});
        }
        this._renderPreviewFrame = null;
    }

    _setupPreview () {
        const {renderer} = this.runtime;
        if (!renderer) return;

        if (this._skinId === -1 && this._skin === null && this._drawable === -1) {
            this._skinId = renderer.createPenSkin();
            this._skin = renderer._allSkins[this._skinId];
            this._drawable = renderer.createDrawable(StageLayering.VIDEO_LAYER);
            renderer.updateDrawableProperties(this._drawable, {
                skinId: this._skinId
            });
        }

        // if we haven't already created and started a preview frame render loop, do so
        if (!this._renderPreviewFrame) {
            renderer.updateDrawableProperties(this._drawable, {
                ghost: this._ghost,
                visible: true
            });

            this._renderPreviewFrame = () => {
                clearTimeout(this._renderPreviewTimeout);
                if (!this._renderPreviewFrame) {
                    return;
                }

                this._renderPreviewTimeout = setTimeout(this._renderPreviewFrame, this.runtime.currentStepTime);

                const canvas = this.getFrame({format: Video.FORMAT_CANVAS});

                if (!canvas) {
                    this._skin.clear();
                    return;
                }

                const xOffset = Video.DIMENSIONS[0] / -2;
                const yOffset = Video.DIMENSIONS[1] / 2;
                this._skin.drawStamp(canvas, xOffset, yOffset);
                this.runtime.requestRedraw();
            };

            this._renderPreviewFrame();
        }
    }

    get videoReady () {
        if (this.provider) return this.provider.videoReady;
        return false;
    }
}

module.exports = Video;
<commit_msg>Add a flag to force the video layer to be transparent.<commit_after>const StageLayering = require('../engine/stage-layering');

class Video {
    constructor (runtime) {
        this.runtime = runtime;

        /**
         * @typedef VideoProvider
         * @property {Function} enableVideo - Requests camera access from the user, and upon success,
         * enables the video feed
         * @property {Function} disableVideo - Turns off the video feed
         * @property {Function} getFrame - Return frame data from the video feed in
         * specified dimensions, format, and mirroring.
         */
        this.provider = null;

        /**
         * Id representing a Scratch Renderer skin the video is rendered to for
         * previewing.
         * @type {number}
         */
        this._skinId = -1;

        /**
         * The Scratch Renderer Skin object.
         * @type {Skin}
         */
        this._skin = null;

        /**
         * Id for a drawable using the video's skin that will render as a video
         * preview.
         * @type {Drawable}
         */
        this._drawable = -1;

        /**
         * Store the last state of the video transparency ghost effect
         * @type {number}
         */
        this._ghost = 0;

        /**
         * Store a flag that allows the preview to be forced transparent.
         * @type {number}
         */
        this._forceTransparentPreview = false;
    }

    static get FORMAT_IMAGE_DATA () {
        return 'image-data';
    }

    static get FORMAT_CANVAS () {
        return 'canvas';
    }

    /**
     * Dimensions the video stream is analyzed at after its rendered to the
     * sample canvas.
     * @type {Array.<number>}
     */
    static get DIMENSIONS () {
        return [480, 360];
    }

    /**
     * Order preview drawable is inserted at in the renderer.
     * @type {number}
     */
    static get ORDER () {
        return 1;
    }

    /**
     * Set a video provider for this device. A default implementation of
     * a video provider can be found in scratch-gui/src/lib/video/video-provider
     * @param {VideoProvider} provider - Video provider to use
     */
    setProvider (provider) {
        this.provider = provider;
    }

    /**
     * Request video be enabled.  Sets up video, creates video skin and enables preview.
     *
     * ioDevices.video.requestVideo()
     *
     * @return {Promise.<Video>} resolves a promise to this IO device when video is ready.
     */
    enableVideo () {
        if (!this.provider) return null;
        return this.provider.enableVideo().then(() => this._setupPreview());
    }

    /**
     * Disable video stream (turn video off)
     * @return {void}
     */
    disableVideo () {
        this._disablePreview();
        if (!this.provider) return null;
        this.provider.disableVideo();
    }

    /**
     * Return frame data from the video feed in a specified dimensions, format, and mirroring.
     *
     * @param {object} frameInfo A descriptor of the frame you would like to receive.
     * @param {Array.<number>} frameInfo.dimensions [width, height] array of numbers.  Defaults to [480,360]
     * @param {boolean} frameInfo.mirror If you specificly want a mirror/non-mirror frame, defaults to the global
     *                                   mirror state (ioDevices.video.mirror)
     * @param {string} frameInfo.format Requested video format, available formats are 'image-data' and 'canvas'.
     * @param {number} frameInfo.cacheTimeout Will reuse previous image data if the time since capture is less than
     *                                        the cacheTimeout.  Defaults to 16ms.
     *
     * @return {ArrayBuffer|Canvas|string|null} Frame data in requested format, null when errors.
     */
    getFrame ({
        dimensions = Video.DIMENSIONS,
        mirror = this.mirror,
        format = Video.FORMAT_IMAGE_DATA,
        cacheTimeout = this._frameCacheTimeout
    }) {
        if (this.provider) return this.provider.getFrame({dimensions, mirror, format, cacheTimeout});
        return null;
    }

    /**
     * Set the preview ghost effect
     * @param {number} ghost from 0 (visible) to 100 (invisible) - ghost effect
     */
    setPreviewGhost (ghost) {
        this._ghost = ghost;
        if (this._drawable) {
            this.runtime.renderer.updateDrawableProperties(this._drawable, {
                ghost: this._forceTransparentPreview ? 100 : ghost
            });
        }
    }

    _disablePreview () {
        if (this._skin) {
            this._skin.clear();
            this.runtime.renderer.updateDrawableProperties(this._drawable, {visible: false});
        }
        this._renderPreviewFrame = null;
    }

    _setupPreview () {
        const {renderer} = this.runtime;
        if (!renderer) return;

        if (this._skinId === -1 && this._skin === null && this._drawable === -1) {
            this._skinId = renderer.createPenSkin();
            this._skin = renderer._allSkins[this._skinId];
            this._drawable = renderer.createDrawable(StageLayering.VIDEO_LAYER);
            renderer.updateDrawableProperties(this._drawable, {
                skinId: this._skinId
            });
        }

        // if we haven't already created and started a preview frame render loop, do so
        if (!this._renderPreviewFrame) {
            renderer.updateDrawableProperties(this._drawable, {
                ghost: this._ghost,
                visible: true
            });

            this._renderPreviewFrame = () => {
                clearTimeout(this._renderPreviewTimeout);
                if (!this._renderPreviewFrame) {
                    return;
                }

                this._renderPreviewTimeout = setTimeout(this._renderPreviewFrame, this.runtime.currentStepTime);

                const canvas = this.getFrame({format: Video.FORMAT_CANVAS});

                if (!canvas) {
                    this._skin.clear();
                    return;
                }

                const xOffset = Video.DIMENSIONS[0] / -2;
                const yOffset = Video.DIMENSIONS[1] / 2;
                this._skin.drawStamp(canvas, xOffset, yOffset);
                this.runtime.requestRedraw();
            };

            this._renderPreviewFrame();
        }
    }

    get videoReady () {
        if (this.provider) return this.provider.videoReady;
        return false;
    }

    /**
     * Method implemented by all IO devices to allow external changes.
     * The only change available externally is hiding the preview, used e.g. to
     * prevent drawing the preview into project thumbnails.
     * @param {object} - data passed to this IO device.
     * @property {boolean} forceTransparentPreview - whether the preview should be forced transparent.
     */
    postData ({forceTransparentPreview}) {
        this._forceTransparentPreview = forceTransparentPreview;
        // Setting the ghost to the current value will pick up the forceTransparentPreview
        // flag and override the current ghost. The complexity is to prevent blocks
        // from overriding forceTransparentPreview
        this.setPreviewGhost(this._ghost);
    }
}

module.exports = Video;
<|endoftext|>


<commit_before>/*
	Copyright 2010-2011 Vodafone Group Services GmbH

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/
(function(){

	function __loadScriptFile(fileName){
		//var node = document.createElement("script");
		//node.type = "text/javascript";
		//node.src = "js/" + fileName + "?nocache="+(+new Date());
		//document.body.appendChild(node);
		document.write('<script type="text/javascript" src="js/' + fileName + "?nocache="+(+new Date()) + '"></script>');
	}

	// Currently we are using embed.toJson() and need the "vodafone-apps-manager2.2" version
	// for those devices that have no JSON implementation natively.
	if (window.navigator.userAgent.split("MSIE 7.0").length>1) {
		__loadScriptFile("embedjs-windows-phone-7-ie7.js");
	} else if (!window["JSON"]){
		__loadScriptFile("embedjs-vodafone-apps-manager2.2.js");
	} else {
		__loadScriptFile("embedjs-android.js");
	}
})();
<commit_msg>Some debug code ...<commit_after>/*
	Copyright 2010-2011 Vodafone Group Services GmbH

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/
(function(){

	function __loadScriptFile(fileName){
		//fileName = fileName.replace(".js", ".uncompressed.js")
		//var node = document.createElement("script");
		//node.type = "text/javascript";
		//node.src = "js/" + fileName + "?nocache="+(+new Date());
		//document.body.appendChild(node);
		document.write('<script type="text/javascript" src="js/' + fileName + "?nocache="+(+new Date()) + '"></script>');
	}

	// Currently we are using embed.toJson() and need the "vodafone-apps-manager2.2" version
	// for those devices that have no JSON implementation natively.
	if (window.navigator.userAgent.split("MSIE 7.0").length>1) {
		__loadScriptFile("embedjs-windows-phone-7-ie7.js");
	} else if (!window["JSON"]){
		__loadScriptFile("embedjs-vodafone-apps-manager2.2.js");
	} else {
		__loadScriptFile("embedjs-android.js");
	}
})();
<|endoftext|>


<commit_before>/**
 *	Form Controller
 *	@author
 *	@Contructor
 *	@return An interface object
 */

/*

conf:{
	[ messages ]: "algo que pisa lo de andentro",
	[ callbacks ]: {
		[ submit ]: function,
		[ clear ]: function
	},
}
*/

ui.forms = function(conf){

	// Validation
	// Are there action and submit type?
	if ($(conf.element).find(":submit").length == 0 || $(conf.element).attr('action') == "" ){
		 alert("Forms fatal error: The <input type=submit> is missing, or need to define a action attribute on the form tag.");
		 return;
	};

	if (ui.instances.forms) {
		if(ui.instances.forms.length > 0){ // Is there forms in map instances?
			for(var i = 0, j = ui.instances.forms.length; i < j; i ++){
				if(ui.instances.forms[i].element === conf.element){
					return {
		                exists: true,
		                object: ui.instances.forms[i]
		            };
				};
			};
		};
	}

	// Start new forms
	var that = ui.controllers(); // Inheritance
	var status = false;

	// patch exists because the components need a trigger
	$(conf.element).bind('submit', function(event){ that.prevent(event); });
	$(conf.element).find(":submit").unbind('click'); // Delete all click handlers asociated to submit button >NATAN: Why?

	// Create the Messages for General Error
	if (!conf.messages) conf.messages = {};
	conf.messages["general"] = conf.messages["general"] || "Revisa los datos, por favor.";

	// General Error
	var $error = $('
Error: ' + conf.messages["general"] + '
');
	var createError = function(){ // Create
		$(conf.element).before( $error );
		$("body").trigger(ui.events.CHANGE_LAYOUT);

	};
	var removeError = function(){ // Remove
		$error.detach();
		$("body").trigger(ui.events.CHANGE_LAYOUT);
	};

	// Publics Methods
	var checkStatus = function(){
		// Check status of my childrens
		for(var i = 0, j = that.children.length; i < j; i ++){
			// Status error (cut the flow)
			if( !that.children[i].status ){
				if (!status) removeError();
				createError();
				status = false;
				return;
			};
		};

		// Status OK (with previous error)
		if (!status) {
			removeError();
			status = true;
		};
	};

	var validate = function(event){

        that.callbacks(conf, 'beforeValidate');

		that.prevent(event);

		// Shoot validations
		for(var i = 0, j = that.children.length; i < j; i ++){
			that.children[i].validate();
		};

		checkStatus();

        that.callbacks(conf, 'afterValidate');

		return conf.publish; // Return publish object
	};

	var submit = function(event){

        that.callbacks(conf, 'beforeSubmit');

		that.prevent(event);

		validate(event); // Validate start

		if ( status ){ // Status OK
			if ( that.callbacks(conf, 'onSubmit') === undefined ) {
				conf.element.submit();
			}
		};

        that.callbacks(conf, 'afterSubmit');

		return conf.publish; // Return publish object
	};

	var clear = function(event){
		that.prevent(event);
		conf.element.reset(); // Reset html form
		removeError();
		for(var i = 0, j = that.children.length; i < j; i ++) that.children[i].reset(); // Reset helpers
		return conf.publish; // Return publish object
	};

	// Bind the submit
	$(conf.element).bind('submit', function(event){
		that.prevent(event);
		submit(event);
	});

	// Bind the reset
	$(conf.element).find(":reset, .resetForm").bind('click', clear);

    // Create the publish object to be returned
	conf.publish = that.publish;

	/**
	 *  @ Public Properties
	 */
	conf.publish.uid = conf.uid;
	conf.publish.element = conf.element;
	conf.publish.type = conf.type;
	conf.publish.status = status;
	conf.publish.children = that.children;

	/**
	 *  @ Public Methods
	 */
	conf.publish.validate = validate;
	conf.publish.submit = submit;
	conf.publish.checkStatus = checkStatus;
	conf.publish.clear = clear;

	return conf.publish;
};
<commit_msg>UI-255 ya está funcionando el submit del forms.<commit_after>/**
 *	Form Controller
 *	@author
 *	@Contructor
 *	@return An interface object
 */

/*

conf:{
	[ messages ]: "algo que pisa lo de andentro",
	[ callbacks ]: {
		[ submit ]: function,
		[ clear ]: function
	},
}
*/

ui.forms = function(conf){

	// Validation
	// Are there action and submit type?
	if ($(conf.element).find(":submit").length == 0 || $(conf.element).attr('action') == "" ){
		 alert("Forms fatal error: The <input type=submit> is missing, or need to define a action attribute on the form tag.");
		 return;
	};

	if (ui.instances.forms) {
		if(ui.instances.forms.length > 0){ // Is there forms in map instances?
			for(var i = 0, j = ui.instances.forms.length; i < j; i ++){
				if(ui.instances.forms[i].element === conf.element){
					return {
		                exists: true,
		                object: ui.instances.forms[i]
		            };
				};
			};
		};
	}

	// Start new forms
	var that = ui.controllers(); // Inheritance
	var status = false;

	// patch exists because the components need a trigger
	$(conf.element).bind('submit', function(event){ that.prevent(event); });
	$(conf.element).find(":submit").unbind('click'); // Delete all click handlers asociated to submit button >NATAN: Why?

	// Create the Messages for General Error
	if (!conf.messages) conf.messages = {};
	conf.messages["general"] = conf.messages["general"] || "Revisa los datos, por favor.";

	// General Error
	var $error = $('
Error: ' + conf.messages["general"] + '
');
	var createError = function(){ // Create
		$(conf.element).before( $error );
		$("body").trigger(ui.events.CHANGE_LAYOUT);

	};
	var removeError = function(){ // Remove
		$error.detach();
		$("body").trigger(ui.events.CHANGE_LAYOUT);
	};

	// Publics Methods
	var checkStatus = function(){
		// Check status of my childrens
		for(var i = 0, j = that.children.length; i < j; i ++){
			// Status error (cut the flow)
			if( !that.children[i].status ){
				if (!status) removeError();
				createError();
				status = false;
				return;
			};
		};

		// Status OK (with previous error)
		if (!status) {
			removeError();
			status = true;
		};
	};

	var validate = function(event){

        that.callbacks(conf, 'beforeValidate');

		that.prevent(event);

		// Shoot validations
		for(var i = 0, j = that.children.length; i < j; i ++){
			that.children[i].validate();
		};

		checkStatus();

        that.callbacks(conf, 'afterValidate');

		return conf.publish; // Return publish object
	};

	var submit = function(event){

        that.callbacks(conf, 'beforeSubmit');

		that.prevent(event);

		validate(event); // Validate start

		if ( status ){ // Status OK
			if ( !conf.hasOwnProperty("onSubmit") ) {
				conf.element.submit();
			}else{
				that.callbacks(conf, "onSubmit");
			};
		};

        that.callbacks(conf, 'afterSubmit');

		return conf.publish; // Return publish object
	};

	var clear = function(event){
		that.prevent(event);
		conf.element.reset(); // Reset html form
		removeError();
		for(var i = 0, j = that.children.length; i < j; i ++) that.children[i].reset(); // Reset helpers
		return conf.publish; // Return publish object
	};

	// Bind the submit
	$(conf.element).bind('submit', function(event){
		that.prevent(event);
		submit(event);
	});

	// Bind the reset
	$(conf.element).find(":reset, .resetForm").bind('click', clear);

    // Create the publish object to be returned
	conf.publish = that.publish;

	/**
	 *  @ Public Properties
	 */
	conf.publish.uid = conf.uid;
	conf.publish.element = conf.element;
	conf.publish.type = conf.type;
	conf.publish.status = status;
	conf.publish.children = that.children;

	/**
	 *  @ Public Methods
	 */
	conf.publish.validate = validate;
	conf.publish.submit = submit;
	conf.publish.checkStatus = checkStatus;
	conf.publish.clear = clear;

	return conf.publish;
};
<|endoftext|>


<commit_before>import {Context, Dispatcher} from 'almin'
import React from 'react'
import openpgp, {config as openPGPConfig} from 'openpgp'
import ReactDOM from 'react-dom'
// import PropTypes from 'prop-types'

import Application from './Application'
import AppStore from './store/AppStore'

import Dashboard from 'src/pages/Dashboard'
import BrowserHistory from 'src/controllers/BrowserHistory'

// install Raven @ production
if(process.env.NODE_ENV === 'production') {
  const Raven = require('raven-js')
  Raven
      .config('https://95c423d821584e798c480087ae77d823@sentry.io/166289')
      .install()
}

async function main() {
  const dispatcher = new Dispatcher()
  const context = new Context({
    dispatcher,
    store: AppStore.create(),
  })
  Application.context = context
  Application.history = new BrowserHistory(context)

  if(process.env.NODE_ENV !== 'production') {
    const AlminLogger = require('almin-logger')
    const logger = new AlminLogger()
    logger.startLogging(context)
  }

  // init open pgp
  openpgp.initWorker({
    path: '/static/openpgp.worker.js',
  })
  openPGPConfig.aead_protect = true // activate fast AES-GCM mode (not yet OpenPGP standard)

  ReactDOM.render(<Dashboard app={Application} />, document.getElementById('appContainer'))
}
main()

window.resetAll = () => {
  window.indexedDB.deleteDatabase('naummanni_database')
  localStorage.removeItem('naumanni::columns')
  history.replaceState('', null, '/')
  location.reload()
}
<commit_msg>momentを日本語に<commit_after>import {Context, Dispatcher} from 'almin'
import React from 'react'
import openpgp, {config as openPGPConfig} from 'openpgp'
import ReactDOM from 'react-dom'
import moment from 'moment'

import Application from './Application'
import AppStore from './store/AppStore'

import Dashboard from 'src/pages/Dashboard'
import BrowserHistory from 'src/controllers/BrowserHistory'

// moment.locale(window.navigator.language)
moment.locale('ja')

// install Raven @ production
if(process.env.NODE_ENV === 'production') {
  const Raven = require('raven-js')
  Raven
      .config('https://95c423d821584e798c480087ae77d823@sentry.io/166289')
      .install()
}

async function main() {
  const dispatcher = new Dispatcher()
  const context = new Context({
    dispatcher,
    store: AppStore.create(),
  })
  Application.context = context
  Application.history = new BrowserHistory(context)

  if(process.env.NODE_ENV !== 'production') {
    const AlminLogger = require('almin-logger')
    const logger = new AlminLogger()
    logger.startLogging(context)
  }

  // init open pgp
  openpgp.initWorker({
    path: '/static/openpgp.worker.js',
  })
  openPGPConfig.aead_protect = true // activate fast AES-GCM mode (not yet OpenPGP standard)

  ReactDOM.render(<Dashboard app={Application} />, document.getElementById('appContainer'))
}
main()

window.resetAll = () => {
  window.indexedDB.deleteDatabase('naummanni_database')
  localStorage.removeItem('naumanni::columns')
  history.replaceState('', null, '/')
  location.reload()
}
<|endoftext|>


<commit_before>import { SW_CACHE_NAME, STORAGE_SCHEMA } from '../constants';
import IDBConnection from '../modules/IDBConnection.module';

/**
 * Respond to a request to fetch offline video and contruct a response stream.
 *
 * @todo Support byte range requests properly.
 *
 * Currently the whole video is pushed to the stream and `206 Partial Content` is not sent.
 *
 * @param {IDBConnection} db  IDBConnection instance.
 * @param {object} metaEntry  Video metadata from the IDB.
 * @param {number} streamFrom To support byte range requests. WIP.
 * @param {number} streamTo   To support byte range requests. WIP.
 *
 * @returns {Response} Response object.
 */
const getResponseStream = (db, metaEntry, streamFrom = null, streamTo = null) => {
  /* eslint-disable no-unused-vars */
  streamFrom = streamFrom || 0;
  streamTo = streamTo || metaEntry.sizeInBytes;
  /* eslint-enable no-unused-vars */

  const stream = new ReadableStream({
    async start(controller) {
      const rawIDB = db.unwrap();
      const transaction = rawIDB.transaction(STORAGE_SCHEMA.data.name, 'readonly');
      const store = transaction.objectStore(STORAGE_SCHEMA.data.name);
      const index = store.index('offset');
      const request = index.openCursor();

      request.onsuccess = (e) => {
        const cursor = e.target.result;

        if (cursor) {
          controller.enqueue(cursor.value.data);
          cursor.continue();
        } else {
          controller.close();
        }
      };
      request.onerror = () => controller.close();
    },
  });

  const response = new Response(stream, {
    headers: {
      'Content-Type': metaEntry.mime || 'application/octet-stream',
      'Content-Length': metaEntry.sizeInBytes,
    },
  });
  return response;
};

/**
 * Respond to a offline video request.
 *
 * @param {Event} event The `fetch` event.
 *
 * @returns {Response|null} Response stream or null.
 */
const maybeGetVideoResponse = async (event) => {
  const db = await IDBConnection.getConnection();
  const metaEntry = await db.meta.get(event.request.url);

  return metaEntry.done ? getResponseStream(db, metaEntry) : null;
};

/**
 * Precache all application assets.
 *
 * @param {Event} event Install event.
 */
const precacheAssets = (event) => {
  // In the future we can generate this list with a simple script (looking at video-list.json)
  const assetsToCache = [
    '/',
    '/index.html',
    '/dist/js/index.js',
    '/api/video-list.json',
    '/favicon.svg',
  ];

  event.waitUntil(
    caches.open(SW_CACHE_NAME).then((cache) => cache.addAll(assetsToCache)),
  );
};

/**
 * The main fetch handler.
 *
 * @param {Event} event Featch event.
 */
const fetchHandler = (event) => {
  event.respondWith(
    caches.open(SW_CACHE_NAME)
      .then(async (cache) => cache.match(event.request).then(async (response) => {
        if (response) return response;

        const videoResponse = await maybeGetVideoResponse(event);
        if (videoResponse) return videoResponse;

        return fetch(event.request);
      })),
  );
};

/* eslint-disable no-restricted-globals */
self.addEventListener('install', precacheAssets);
self.addEventListener('fetch', fetchHandler);
/* eslint-enable no-restricted-globals */
<commit_msg>Offline video to use 206 Partial Content w/ correct response headers.<commit_after>import { SW_CACHE_NAME, STORAGE_SCHEMA } from '../constants';
import IDBConnection from '../modules/IDBConnection.module';

/**
 * Respond to a request to fetch offline video and contruct a response stream.
 *
 * @todo Support byte range requests properly.
 *
 * Currently the whole video is pushed to the stream and `206 Partial Content` is not sent.
 *
 * @param {Request} request   Request object.
 * @param {IDBConnection} db  IDBConnection instance.
 * @param {object} metaEntry  Video metadata from the IDB.
 *
 * @returns {Response} Response object.
 */
const getResponseStream = (request, db, metaEntry) => {
  const rangeRequest = request.headers.get('range') || '';
  const byteRanges = rangeRequest.match(/bytes=(?<from>[0-9]+)?-(?<to>[0-9]+)?/);
  const rangeFrom = byteRanges.groups?.from || 0;
  const rangeTo = byteRanges.groups?.to || metaEntry.sizeInBytes - 1;

  const stream = new ReadableStream({
    async start(controller) {
      const rawIDB = db.unwrap();
      const transaction = rawIDB.transaction(STORAGE_SCHEMA.data.name, 'readonly');
      const store = transaction.objectStore(STORAGE_SCHEMA.data.name);
      const index = store.index('offset');
      const cursor = index.openCursor();

      cursor.onsuccess = (e) => {
        const newCursor = e.target.result;
        if (newCursor) {
          const dataObject = newCursor.value;
          const previousDataLength = dataObject.offset - dataObject.size;

          if (rangeFrom < dataObject.offset && rangeTo > previousDataLength) {
            const overlapFrom = Math.max(rangeFrom, previousDataLength);
            const overlapTo = Math.min(rangeTo, dataObject.offset - 1);

            if (overlapTo - overlapFrom !== dataObject.size - 1) {
              const sliceBufferFrom = overlapFrom - previousDataLength;
              const sliceBufferTo = overlapTo - previousDataLength + 1;

              const bufferSlice = new Uint8Array(
                newCursor.value.data.slice(sliceBufferFrom, sliceBufferTo),
              );
              controller.enqueue(bufferSlice);
            } else {
              controller.enqueue(newCursor.value.data);
            }
          }
          newCursor.continue();
        } else {
          controller.close();
        }
      };
      cursor.onerror = () => controller.close();
    },
  });

  const responseOpts = {
    status: rangeRequest ? 206 : 200,
    statusText: rangeRequest ? 'Partial Content' : 'OK',
    headers: {
      'Accept-Ranges': 'bytes',
      'Content-Type': metaEntry.mime || 'application/octet-stream',
      'Content-Length': rangeTo - rangeFrom + 1,
    },
  };
  if (rangeRequest) {
    responseOpts.headers['Content-Range'] = `bytes ${rangeFrom}-${rangeTo}/${metaEntry.sizeInBytes}`;
  }
  const response = new Response(stream, responseOpts);
  return response;
};

/**
 * Respond to a offline video request.
 *
 * @param {Event} event The `fetch` event.
 *
 * @returns {Response|null} Response stream or null.
 */
const maybeGetVideoResponse = async (event) => {
  const db = await IDBConnection.getConnection();
  const metaEntry = await db.meta.get(event.request.url);

  return metaEntry.done ? getResponseStream(event.request, db, metaEntry) : null;
};

/**
 * Precache all application assets.
 *
 * @param {Event} event Install event.
 */
const precacheAssets = (event) => {
  // In the future we can generate this list with a simple script (looking at video-list.json)
  const assetsToCache = [
    '/',
    '/index.html',
    '/dist/js/index.js',
    '/api/video-list.json',
    '/favicon.svg',
  ];

  event.waitUntil(
    caches.open(SW_CACHE_NAME).then((cache) => cache.addAll(assetsToCache)),
  );
};

/**
 * The main fetch handler.
 *
 * @param {Event} event Featch event.
 */
const fetchHandler = (event) => {
  event.respondWith(
    caches.open(SW_CACHE_NAME)
      .then(async (cache) => cache.match(event.request).then(async (response) => {
        if (response) return response;

        const videoResponse = await maybeGetVideoResponse(event);
        if (videoResponse) return videoResponse;

        return fetch(event.request);
      })),
  );
};

/* eslint-disable no-restricted-globals */
self.addEventListener('install', precacheAssets);
self.addEventListener('fetch', fetchHandler);
/* eslint-enable no-restricted-globals */
<|endoftext|>


<commit_before>/* Copyright(c) 2018 Philip Mulcahy. */
/* Copyright(c) 2016 Philip Mulcahy. */

/* jshint strict: true, esversion: 6 */

import util from './util';
import csv from './csv';
import $ from 'jquery';
import 'datatables';
import sprintf from 'sprintf-js';

'use strict';

const tableStyle = 'border: 1px solid black;';
let datatable = null;

/**
 * Add a td to the row tr element, and return the td.
 */
const addCell = function(row, value) {
    const td = row.ownerDocument.createElement('td');
    td.setAttribute('style', tableStyle);
    row.appendChild(td);
    td.textContent = value;
    return td;
};

/**
 * Add a td to the row tr element, and return the td.
 */
const addElemCell = function(row, elem) {
    const td = row.ownerDocument.createElement('td');
    td.setAttribute('style', tableStyle);
    row.appendChild(td);
    td.appendChild(elem);
    return td;
};

/**
 * Add a td to the row tr element, and return the td.
 */
const addLinkCell = function(row, text, href) {
    const a = row.ownerDocument.createElement('a');
    a.textContent = text;
    a.href = href;
    return addElemCell(row, a);
};

const cols = [
    {
        field_name: 'order id',
        type: 'func',
        func: function(order, row){
            addLinkCell(
                row, order.id,
                util.getOrderDetailUrl(order.id)
            );
        },
        is_numeric: false
    },
    {
        field_name: 'items',
        type: 'func',
        func: (order, row) => addElemCell(row, order.itemsHtml(document)),
        is_numeric: false
    },
    {
        field_name: 'to',
        type: 'plain',
        property_name: 'who',
        is_numeric: false
    },
    {
        field_name: 'date',
        type: 'detail',
        property_name: 'date',
        is_numeric: false,
    },
    {
        field_name: 'total',
        type: 'detail',
        property_name: 'total',
        is_numeric: true
    },
    {
        field_name: 'postage',
        type: 'detail',
        property_name: 'postage',
        is_numeric: true,
        help: 'If there are only N/A values in this column, your login session may have partially expired, meaning you (and the extension) cannot fetch order details. Try clicking on one of the order links in the left hand column and then retrying the extension button you clicked to get here.'
    },
    {
        field_name: 'gift',
        type: 'detail',
        property_name: 'gift',
        is_numeric: true
    },
    {
        field_name: 'VAT',
        type: 'detail',
        property_name: 'vat',
        is_numeric: true,
        help: 'Caution: when stuff is not supplied by Amazon, then tax is often not listed.',
        sites: new RegExp('amazon(?!.com)')
    },
    {
        field_name: 'TAX',
        type: 'detail',
        property_name: 'us_tax',
        is_numeric: true,
        help: 'Caution: when stuff is not supplied by Amazon, then tax is often not listed.',
        sites: new RegExp('\.com$')
    },
    {
        field_name: 'GST',
        type: 'detail',
        property_name: 'gst',
        is_numeric: true,
        sites: new RegExp('\.ca$')
    },
    {
        field_name: 'PST',
        type: 'detail',
        property_name: 'pst',
        is_numeric: true,
        sites: new RegExp('\.ca$')
    },
    {
        field_name: 'refund',
        type: 'detail',
        property_name: 'refund',
        is_numeric: true
    },
    {
        field_name: 'payments',
        type: 'payments',
        property_name: 'payments',
        is_numeric: false
    }
].filter( col => ('sites' in col) ?
    col.sites.test(util.getSite()):
    true
);

function reallyDisplayOrders(orders, beautiful) {
    console.log('amazon_order_history_table.reallyDisplayOrders starting');
    const addOrderTable = function(orders) {
        const addHeader = function(row, value, help) {
            const th = row.ownerDocument.createElement('th');
            th.setAttribute('style', tableStyle);
            row.appendChild(th);
            th.textContent = value;
            if( help ) {
                th.setAttribute('title', help);
            }
            return th;
        };

        const appendOrderRow = function(table, order) {
            const tr = document.createElement('tr');
            tr.setAttribute('style', tableStyle);
            tr.order = order;
            table.appendChild(tr);
            cols.forEach( col_spec => {
                let elem = null;
                switch(col_spec.type) {
                    case 'plain':
                        elem = addCell(tr, order[col_spec.property_name]);
                        break;
                    case 'detail':
                        elem = addCell(tr, 'pending');
                        order.detail_promise.then( detail => {
                            elem.innerHTML = detail[col_spec.property_name];
                            if(datatable) {
                                datatable.rows().invalidate();
                                datatable.draw();
                            }
                        });
                        break;
                    case 'payments':
                        elem = addCell(tr, 'pending');
                        order.payments_promise.then( payments => {
                            const ul = document.createElement('ul');
                            payments.forEach( payment => {
                                const li = document.createElement('li');
                                ul.appendChild(li);
                                const a = document.createElement('a');
                                li.appendChild(a);
                                a.textContent = payment + '; ';
                                a.href = util.getOrderPaymentUrl(order.id);
                            });
                            elem.textContent = '';
                            elem.appendChild(ul);
                            if(datatable) {
                                datatable.rows().invalidate();
                                datatable.draw();
                            }
                        });
                        break;
                    case 'func':
                        col_spec.func(order, tr);
                        break;
                }
                if ('help' in col_spec) {
                    elem.setAttribute('title', col_spec.help);
                }
            });
        };
        // remove any old table
        let table = document.querySelector('[id="order_table"]');
        if ( table !== null ) {
            console.log('removing old table');
            table.parentNode.removeChild(table);
            console.log('removed old table');
        }
        console.log('adding table');
        table = document.createElement('table');
        console.log('added table');
        document.body.appendChild(table);
        table.setAttribute('id', 'order_table');
        table.setAttribute('class', 'order_reporter_table stripe compact');
        table.setAttribute('style', tableStyle);

        const thead = document.createElement('thead');
        table.appendChild(thead);

        const hr = document.createElement('tr');
        thead.appendChild(hr);

        const tfoot = document.createElement('tfoot');
        table.appendChild(tfoot);

        const fr = document.createElement('tr');
        tfoot.appendChild(fr);

        cols.forEach( col_spec => {
            addHeader(hr, col_spec.field_name, col_spec.help);
            addHeader(fr, col_spec.field_name, col_spec.help);
        });

        const tbody = document.createElement('tbody');
        table.appendChild(tbody);

        orders.forEach( order => {
            appendOrderRow(tbody, order);
            console.log('Added row for ' + order.id);
        });

        return table;
    };
    util.clearBody();
    const table = addOrderTable(orders);
    if(beautiful) {
        $(document).ready( () => {
            if (datatable) {
                datatable.destroy();
            }
            datatable = $('#order_table').DataTable({
                'bPaginate': true,
                'lengthMenu': [ [10, 25, 50, 100, -1],
                    [10, 25, 50, 100, 'All'] ],
                'footerCallback': function(row, data, start, end, display) {
                    const api = this.api();
                    // Remove the formatting to get integer data for summation
                    const floatVal = function(i) {
                        if(typeof i === 'string') {
                            return (i === 'N/A' || i === '?') ?
                                0 : parseFloat(i.replace(/^([£$]|CAD|EUR|GBP) */, '')
                                                .replace(/,/, '.'));
                        }
                        if(typeof i === 'number') { return i; }
                        return 0;
                    };
                    let col_index = 0;
                    cols.forEach( col_spec => {
                        if(col_spec.is_numeric) {
                            col_spec.sum = floatVal(
                                api.column(col_index)
                                   .data()
                                   .map( v => floatVal(v) )
                                   .reduce( (a, b) => a + b, 0 )
                            );
                            col_spec.pageSum = floatVal(
                                api.column(col_index, { page: 'current' })
                                   .data()
                                   .map( v => floatVal(v) )
                                   .reduce( (a, b) => a + b, 0 )
                            );
                            $(api.column(col_index).footer()).html(
                                sprintf.sprintf('page=%s; all=%s',
                                    col_spec.pageSum.toFixed(2),
                                    col_spec.sum.toFixed(2))
                            );
                        }
                        col_index += 1;
                    });
                }
            });
            util.removeButton('data table');
            util.addButton(
                'plain table',
                function() {
                    console.log('amazon_order_history_table plain table button clicked');
                    displayOrders(orders, false);
                },
                'background-color:cornflowerblue; color:white'
            );
        });
    } else {
        util.removeButton('plain table');
        util.addButton(
            'data table',
            function() {
                console.log('amazon_order_history_table data table button clicked');
                displayOrders(orders, true);
            },
            'background-color:cornflowerblue; color:white'
        );
    }
    util.addButton(
        'download csv',
        function() {
            displayOrders(orders, false).then(
                (table) => { csv.download(table); }
            );
        },
        'background-color:cornflowerblue; color:white'
    );
    console.log('amazon_order_history_table.reallyDisplayOrders returning');
    return table;
}

// TODO: refactor so that order retrieval belongs to azaz_table, but
// diagnostics building belongs to azad_order.
function displayOrders(orderPromises, beautiful) {
    console.log('amazon_order_history_table.displayOrders starting');
    return Promise.all(orderPromises).then( orders => {
        console.log('amazon_order_history_table.displayOrders then func starting');
        const return_val = reallyDisplayOrders(orders, beautiful);
        console.log('amazon_order_history_table.displayOrders then func returning');
        return return_val;
    });
}

function dumpOrderDiagnostics(detail_link) {
    console.log('dumpOrderDiagnostics: ' + detail_link);
}

export default {
    displayOrders: displayOrders,

    dumpOrderDiagnostics: dumpOrderDiagnostics
};
<commit_msg>fix typo<commit_after>/* Copyright(c) 2018 Philip Mulcahy. */
/* Copyright(c) 2016 Philip Mulcahy. */

/* jshint strict: true, esversion: 6 */

import util from './util';
import csv from './csv';
import $ from 'jquery';
import 'datatables';
import sprintf from 'sprintf-js';

'use strict';

const tableStyle = 'border: 1px solid black;';
let datatable = null;

/**
 * Add a td to the row tr element, and return the td.
 */
const addCell = function(row, value) {
    const td = row.ownerDocument.createElement('td');
    td.setAttribute('style', tableStyle);
    row.appendChild(td);
    td.textContent = value;
    return td;
};

/**
 * Add a td to the row tr element, and return the td.
 */
const addElemCell = function(row, elem) {
    const td = row.ownerDocument.createElement('td');
    td.setAttribute('style', tableStyle);
    row.appendChild(td);
    td.appendChild(elem);
    return td;
};

/**
 * Add a td to the row tr element, and return the td.
 */
const addLinkCell = function(row, text, href) {
    const a = row.ownerDocument.createElement('a');
    a.textContent = text;
    a.href = href;
    return addElemCell(row, a);
};

const cols = [
    {
        field_name: 'order id',
        type: 'func',
        func: function(order, row){
            addLinkCell(
                row, order.id,
                util.getOrderDetailUrl(order.id)
            );
        },
        is_numeric: false
    },
    {
        field_name: 'items',
        type: 'func',
        func: (order, row) => addElemCell(row, order.itemsHtml(document)),
        is_numeric: false
    },
    {
        field_name: 'to',
        type: 'plain',
        property_name: 'who',
        is_numeric: false
    },
    {
        field_name: 'date',
        type: 'detail',
        property_name: 'date',
        is_numeric: false,
    },
    {
        field_name: 'total',
        type: 'detail',
        property_name: 'total',
        is_numeric: true
    },
    {
        field_name: 'postage',
        type: 'detail',
        property_name: 'postage',
        is_numeric: true,
        help: 'If there are only N/A values in this column, your login session may have partially expired, meaning you (and the extension) cannot fetch order details. Try clicking on one of the order links in the left hand column and then retrying the extension button you clicked to get here.'
    },
    {
        field_name: 'gift',
        type: 'detail',
        property_name: 'gift',
        is_numeric: true
    },
    {
        field_name: 'VAT',
        type: 'detail',
        property_name: 'vat',
        is_numeric: true,
        help: 'Caution: when stuff is not supplied by Amazon, then tax is often not listed.',
        sites: new RegExp('amazon(?!.com)')
    },
    {
        field_name: 'TAX',
        type: 'detail',
        property_name: 'us_tax',
        is_numeric: true,
        help: 'Caution: when stuff is not supplied by Amazon, then tax is often not listed.',
        sites: new RegExp('\.com$')
    },
    {
        field_name: 'GST',
        type: 'detail',
        property_name: 'gst',
        is_numeric: true,
        sites: new RegExp('\.ca$')
    },
    {
        field_name: 'PST',
        type: 'detail',
        property_name: 'pst',
        is_numeric: true,
        sites: new RegExp('\.ca$')
    },
    {
        field_name: 'refund',
        type: 'detail',
        property_name: 'refund',
        is_numeric: true
    },
    {
        field_name: 'payments',
        type: 'payments',
        property_name: 'payments',
        is_numeric: false
    }
].filter( col => ('sites' in col) ?
    col.sites.test(util.getSite()):
    true
);

function reallyDisplayOrders(orders, beautiful) {
    console.log('amazon_order_history_table.reallyDisplayOrders starting');
    const addOrderTable = function(orders) {
        const addHeader = function(row, value, help) {
            const th = row.ownerDocument.createElement('th');
            th.setAttribute('style', tableStyle);
            row.appendChild(th);
            th.textContent = value;
            if( help ) {
                th.setAttribute('title', help);
            }
            return th;
        };

        const appendOrderRow = function(table, order) {
            const tr = document.createElement('tr');
            tr.setAttribute('style', tableStyle);
            tr.order = order;
            table.appendChild(tr);
            cols.forEach( col_spec => {
                let elem = null;
                switch(col_spec.type) {
                    case 'plain':
                        elem = addCell(tr, order[col_spec.property_name]);
                        break;
                    case 'detail':
                        elem = addCell(tr, 'pending');
                        order.detail_promise.then( detail => {
                            elem.innerHTML = detail[col_spec.property_name];
                            if(datatable) {
                                datatable.rows().invalidate();
                                datatable.draw();
                            }
                        });
                        break;
                    case 'payments':
                        elem = addCell(tr, 'pending');
                        order.payments_promise.then( payments => {
                            const ul = document.createElement('ul');
                            payments.forEach( payment => {
                                const li = document.createElement('li');
                                ul.appendChild(li);
                                const a = document.createElement('a');
                                li.appendChild(a);
                                a.textContent = payment + '; ';
                                a.href = util.getOrderPaymentUrl(order.id);
                            });
                            elem.textContent = '';
                            elem.appendChild(ul);
                            if(datatable) {
                                datatable.rows().invalidate();
                                datatable.draw();
                            }
                        });
                        break;
                    case 'func':
                        col_spec.func(order, tr);
                        break;
                }
                if ('help' in col_spec) {
                    elem.setAttribute('title', col_spec.help);
                }
            });
        };
        // remove any old table
        let table = document.querySelector('[id="order_table"]');
        if ( table !== null ) {
            console.log('removing old table');
            table.parentNode.removeChild(table);
            console.log('removed old table');
        }
        console.log('adding table');
        table = document.createElement('table');
        console.log('added table');
        document.body.appendChild(table);
        table.setAttribute('id', 'order_table');
        table.setAttribute('class', 'order_reporter_table stripe compact');
        table.setAttribute('style', tableStyle);

        const thead = document.createElement('thead');
        table.appendChild(thead);

        const hr = document.createElement('tr');
        thead.appendChild(hr);

        const tfoot = document.createElement('tfoot');
        table.appendChild(tfoot);

        const fr = document.createElement('tr');
        tfoot.appendChild(fr);

        cols.forEach( col_spec => {
            addHeader(hr, col_spec.field_name, col_spec.help);
            addHeader(fr, col_spec.field_name, col_spec.help);
        });

        const tbody = document.createElement('tbody');
        table.appendChild(tbody);

        orders.forEach( order => {
            appendOrderRow(tbody, order);
            console.log('Added row for ' + order.id);
        });

        return table;
    };
    util.clearBody();
    const table = addOrderTable(orders);
    if(beautiful) {
        $(document).ready( () => {
            if (datatable) {
                datatable.destroy();
            }
            datatable = $('#order_table').DataTable({
                'bPaginate': true,
                'lengthMenu': [ [10, 25, 50, 100, -1],
                    [10, 25, 50, 100, 'All'] ],
                'footerCallback': function(row, data, start, end, display) {
                    const api = this.api();
                    // Remove the formatting to get integer data for summation
                    const floatVal = function(i) {
                        if(typeof i === 'string') {
                            return (i === 'N/A' || i === '?') ?
                                0 : parseFloat(i.replace(/^([£$]|CAD|EUR|GBP) */, '')
                                                .replace(/,/, '.'));
                        }
                        if(typeof i === 'number') { return i; }
                        return 0;
                    };
                    let col_index = 0;
                    cols.forEach( col_spec => {
                        if(col_spec.is_numeric) {
                            col_spec.sum = floatVal(
                                api.column(col_index)
                                   .data()
                                   .map( v => floatVal(v) )
                                   .reduce( (a, b) => a + b, 0 )
                            );
                            col_spec.pageSum = floatVal(
                                api.column(col_index, { page: 'current' })
                                   .data()
                                   .map( v => floatVal(v) )
                                   .reduce( (a, b) => a + b, 0 )
                            );
                            $(api.column(col_index).footer()).html(
                                sprintf.sprintf('page=%s; all=%s',
                                    col_spec.pageSum.toFixed(2),
                                    col_spec.sum.toFixed(2))
                            );
                        }
                        col_index += 1;
                    });
                }
            });
            util.removeButton('data table');
            util.addButton(
                'plain table',
                function() {
                    console.log('amazon_order_history_table plain table button clicked');
                    displayOrders(orders, false);
                },
                'background-color:cornflowerblue; color:white'
            );
        });
    } else {
        util.removeButton('plain table');
        util.addButton(
            'data table',
            function() {
                console.log('amazon_order_history_table data table button clicked');
                displayOrders(orders, true);
            },
            'background-color:cornflowerblue; color:white'
        );
    }
    util.addButton(
        'download csv',
        function() {
            displayOrders(orders, false).then(
                (table) => { csv.download(table); }
            );
        },
        'background-color:cornflowerblue; color:white'
    );
    console.log('amazon_order_history_table.reallyDisplayOrders returning');
    return table;
}

// TODO: refactor so that order retrieval belongs to azad_table, but
// diagnostics building belongs to azad_order.
function displayOrders(orderPromises, beautiful) {
    console.log('amazon_order_history_table.displayOrders starting');
    return Promise.all(orderPromises).then( orders => {
        console.log('amazon_order_history_table.displayOrders then func starting');
        const return_val = reallyDisplayOrders(orders, beautiful);
        console.log('amazon_order_history_table.displayOrders then func returning');
        return return_val;
    });
}

function dumpOrderDiagnostics(detail_link) {
    console.log('dumpOrderDiagnostics: ' + detail_link);
}

export default {
    displayOrders: displayOrders,

    dumpOrderDiagnostics: dumpOrderDiagnostics
};
<|endoftext|>