<commit_before>/**
 * Patterns toggle - toggle class on click
 *
 * Copyright 2012 Simplon B.V. - Wichert Akkerman
 * Copyright 2011 Humberto Sermeño
 * Copyright 2011 SYSLAB.COM GmbH
 */
define([
    "jquery",
    "pat-registry",
    "pat-logger",
    "pat-parser",
    "pat-store"
], function($, patterns, logger, Parser, store) {
    var log = logger.getLogger("pat.toggle"),
        parser = new Parser("toggle");

    parser.add_argument("selector");
    parser.add_argument("attr", "class");
    parser.add_argument("value");
    parser.add_argument("store", "none", ["none", "session", "local"]);

    var toggle = {
        name: "toggle",
        trigger: ".pat-toggle",

        init: function($el) {
            return $el.each(function() {
                var $trigger = $(this),
                    options = toggle._validateOptions(this, parser.parse($trigger, true)),
                    state = {toggled: false, options: options},
                    i, storage;

                if (!options.length)
                    return;

                if (options[0].store!=="none") {
                    storage=(options[0].store==="local" ? store.local : store.session)(toggle.name);
                    if (storage.get(this.id))
                        state.toggled=true;
                }

                if (state.toggled)
                    for (i=0; i<options.length; i++)
                        toggle._update(options[i].selector, options[i].attr, options[i].value, true);

                $trigger
                    .off(".toggle")
                    .data("patternToggle", state)
                    .on("click.toggle", toggle.onClick);
            });
        },

        _validateOptions: function(trigger, options) {
            var correct=[],
                i, option, store_error;

            if (!options.length)
                return correct;

            if (options[0].store!=="none") {
                if (!trigger.id) {
                    log.warn("state persistance requested, but element has no id");
                    options[0].store="none";
                } else if (!store.supported) {
                    store_error="browser does not support webstorage";
                    log.warn("state persistance requested, but browser does not support webstorage");
                    options[0].store="none";
                }
            }

            for (i=0; i<options.length; i++) {
                option=options[i];
                if (i && option.store!=="none") {
                    log.warn("store option can only be set on first argument");
                    option.store="none";
                }

                if (!option.selector || !option.attr || !option.value)
                    log.error("Toggle pattern requires selector, attr and value.");
                else
                    correct.push(option);
            }
            return correct;
        },

        onClick: function(event) {
            var $trigger = $(this),
                state = $trigger.data("patternToggle"),
                option, i;

            state.toggled=!state.toggled;
            $trigger.data("patternToggle", state);

            if (state.options[0].store!=="none") {
                var storage=(state.options[0].store==="local" ? store.local : store.session)(toggle.name);
                if (state.toggled)
                    storage.set(this.id, true);
                else
                    storage.remove(this.id);
            }

            for (i=0; i<state.options.length; i++) {
                option=state.options[i];
                toggle._update(option.selector, option.attr, option.value, false);
            }
            event.preventDefault();
        },

        _update: function(selector, attr, value, reset) {
            var $targets = $(selector),
                $target;

            if (!$targets.length)
                return;

            if (attr==="class") {
                $targets.toggleClass(value);
            } else {
                for (var i=0; i<$targets.length; i++) {
                    $target=$targets.eq(i);
                    if ($target.attr(attr)) {
                        if (reset)
                            $target.removeAttr(attr);
                        else
                            $target.prop(attr, false);
                    } else {
                        if (reset)
                            $target.attr(attr, attr);
                        else
                            $target.prop(attr, true);
                    }
                }
            }
            $targets.trigger("pat-update", {pattern: "toggle"});
        }
    };

    patterns.register(toggle);
    return toggle; // XXX for tests only
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>toggle: Use named functions.<commit_after>/**
 * Patterns toggle - toggle class on click
 *
 * Copyright 2012 Simplon B.V. - Wichert Akkerman
 * Copyright 2011 Humberto Sermeño
 * Copyright 2011 SYSLAB.COM GmbH
 */
define([
    "jquery",
    "pat-registry",
    "pat-logger",
    "pat-parser",
    "pat-store"
], function($, patterns, logger, Parser, store) {
    var log = logger.getLogger("pat.toggle"),
        parser = new Parser("toggle");

    parser.add_argument("selector");
    parser.add_argument("attr", "class");
    parser.add_argument("value");
    parser.add_argument("store", "none", ["none", "session", "local"]);

    var toggle = {
        name: "toggle",
        trigger: ".pat-toggle",

        init: function toggle_init($el) {
            return $el.each(function toggle_init_el() {
                var $trigger = $(this),
                    options = toggle._validateOptions(this, parser.parse($trigger, true)),
                    state = {toggled: false, options: options},
                    i, storage;

                if (!options.length)
                    return;

                if (options[0].store!=="none") {
                    storage=(options[0].store==="local" ? store.local : store.session)(toggle.name);
                    if (storage.get(this.id))
                        state.toggled=true;
                }

                if (state.toggled)
                    for (i=0; i<options.length; i++)
                        toggle._update(options[i].selector, options[i].attr, options[i].value, true);

                $trigger
                    .off(".toggle")
                    .data("patternToggle", state)
                    .on("click.toggle", toggle._onClick);
            });
        },

        _validateOptions: functioni toggle_validateOptions(trigger, options) {
            var correct=[],
                i, option, store_error;

            if (!options.length)
                return correct;

            if (options[0].store!=="none") {
                if (!trigger.id) {
                    log.warn("state persistance requested, but element has no id");
                    options[0].store="none";
                } else if (!store.supported) {
                    store_error="browser does not support webstorage";
                    log.warn("state persistance requested, but browser does not support webstorage");
                    options[0].store="none";
                }
            }

            for (i=0; i<options.length; i++) {
                option=options[i];
                if (i && option.store!=="none") {
                    log.warn("store option can only be set on first argument");
                    option.store="none";
                }

                if (!option.selector || !option.attr || !option.value)
                    log.error("Toggle pattern requires selector, attr and value.");
                else
                    correct.push(option);
            }
            return correct;
        },

        _onClick: function toggle_onClick(event) {
            var $trigger = $(this),
                state = $trigger.data("patternToggle"),
                option, i;

            state.toggled=!state.toggled;
            $trigger.data("patternToggle", state);

            if (state.options[0].store!=="none") {
                var storage=(state.options[0].store==="local" ? store.local : store.session)(toggle.name);
                if (state.toggled)
                    storage.set(this.id, true);
                else
                    storage.remove(this.id);
            }

            for (i=0; i<state.options.length; i++) {
                option=state.options[i];
                toggle._update(option.selector, option.attr, option.value, false);
            }
            event.preventDefault();
        },

        _update: function toggle_update(selector, attr, value, reset) {
            var $targets = $(selector),
                $target;

            if (!$targets.length)
                return;

            if (attr==="class") {
                $targets.toggleClass(value);
            } else {
                for (var i=0; i<$targets.length; i++) {
                    $target=$targets.eq(i);
                    if ($target.attr(attr)) {
                        if (reset)
                            $target.removeAttr(attr);
                        else
                            $target.prop(attr, false);
                    } else {
                        if (reset)
                            $target.attr(attr, attr);
                        else
                            $target.prop(attr, true);
                    }
                }
            }
            $targets.trigger("pat-update", {pattern: "toggle"});
        }
    };

    patterns.register(toggle);
    return toggle; // XXX for tests only
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>


<commit_before>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://scriptographer.org/
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * All rights reserved. See LICENSE file for details.
 */

var Curve = this.Curve = Base.extend({
	beans: true,

	initialize: function(arg0, arg1, arg2, arg3) {
		if (arguments.length == 0) {
			this._segment1 = new Segment();
			this._segment2 = new Segment();
		} else if (arguments.length == 1) {
			// TODO: If beans are not activated, this won't copy from
			// an existing segment. OK?
			this._segment1 = new Segment(arg0.segment1);
			this._segment2 = new Segment(arg0.segment2);
		} else if (arguments.length == 2) {
			if (arg0 instanceof Path) {
				this._path = arg0;
				this._index1 = arg1;
				this._updateSegments();
			} else {
				this._segment1 = new Segment(arg0);
				this._segment2 = new Segment(arg1);
			}
		} else if (arguments.length == 4) {
			this._segment1 = new Segment(arg0, null, arg1);
			this._segment2 = new Segment(arg3, arg2, null);
		}
	},

	_updateSegments: function() {
		if (this._path) {
			this._index2 = this._index1 + 1;
			// A closing curve?
			var segments = this._path._segments;
			if (this._index2 >= segments.length)
				this._index2 = 0;
			this._segment1 = segments[this._index1];
			this._segment2 = segments[this._index2];
		}
	},

	/**
	 * The first anchor point of the curve.
	 */
	getPoint1: function() {
		return this._segment1._point;
	},

	setPoint1: function() {
		var point = Point.read(arguments);
		this._segment1._point.set(point.x, point.y);
	},

	/**
	 * The second anchor point of the curve.
	 */
	getPoint2: function() {
		return this._segment2._point;
	},

	setPoint2: function() {
		var point = Point.read(arguments);
		this._segment2._point.set(point.x, point.y);
	},

	/**
	 * The handle point that describes the tangent in the first anchor point.
	 */
	getHandle1: function() {
		return this._segment1._handleOut;
	},

	setHandle1: function() {
		var point = Point.read(arguments);
		this._segment1._handleOut.set(point.x, point.y);
	},

	/**
	 * The handle point that describes the tangent in the second anchor point.
	 */
	getHandle2: function() {
		return this._segment2._handleIn;
	},

	setHandle2: function() {
		var point = Point.read(arguments);
		this._segment2._handleIn.set(point.x, point.y);
	},

	/**
	 * The first segment of the curve.
	 */
	getSegment1: function() {
		return this._segment1;
	},

	/**
	 * The second segment of the curve.
	 */
	getSegment2: function() {
		return this._segment2;
	},

	getPath: function() {
		return this._path;
	},

	getIndex: function() {
		return this._index1;
	},

	_setIndex: function(index) {
		this._index1 = index;
		this._updateSegments();
	},

	getNext: function() {
		var curves = this._path && this._path._curves;
		// TODO: Add cyclic looping when closed back to Scriptographer
		return curves && (curves[this._index1 + 1]
				|| this._path.closed && curves[0]) || null;
	},

	getPrevious: function() {
		var curves = this._path && this._path._curves;
		return curves && (curves[this._index1 - 1]
				|| this._path.closed && curves[curves.length - 1]) || null;
	},

	getCurveValues: function() {
		var p1 = this._segment1._point,
			h1 = this._segment1._handleOut,
			h2 = this._segment2._handleIn,
			p2 = this._segment2._point;
		return [
			p1.x, p1.y,
			p1.x + h1.x, p1.y + h1.y,
			p2.x + h2.x, p2.y + h2.y,
			p2.x, p2.y
		];
	},

	// TODO: Port back to Scriptographer, optionally suppporting from, to
	// TODO: Replaces getPartLength(fromParameter, toParameter)?
	getLength: function(from, to) {
		var values = this.getCurveValues();
		if (arguments.length > 0)
			values.push(from, to);
		return Curve.getLength.apply(Curve, values);
	},

	/**
	 * Checks if this curve is linear, meaning it does not define any curve
	 * handle.

	 * @return {@true if the curve is linear}
	 */
	isLinear: function() {
		return this._segment1._handleOut.isZero()
				&& this._segment2._handleIn.isZero();
	},

	getParameter: function(length) {
		return Curve.getParameter.apply(Curve,
				this.getCurveValues().concat(length));
	},

	// TODO: getParameter(point, precision)
	// TODO: getLocation
	// TODO: getIntersections
	// TODO: adjustThroughPoint

	transform: function(matrix) {
		return new Curve(
				matrix.transform(this._segment1._point),
				matrix.transform(this._segment1._handleOut),
				matrix.transform(this._segment2._handleIn),
				matrix.transform(this._segment2._point));
	},

	reverse: function() {
		return new Curve(this._segment2.reverse(), this._segment1.reverse());
	},

	// TODO: divide
	// TODO: split

	clone: function() {
		return new Curve(this._segment1, this._segment2);
	},

	toString: function() {
		return '{ point1: ' + this._segment1._point
				+ (!this._segment1._handleOut.isZero()
					? ', handle1: ' + this._segment1._handleOut : '')
				+ (this._segment2._handleIn.isZero()
					? ', handle2: ' + this._segment2._handleIn : '')
				+ ', point2: ' + this._segment2._point
				+ ' }';
	}
}, new function() {
	function evaluate(that, t, type) {
		// Calculate the polynomial coefficients. caution: handles are relative
		// to points
		var point1 = that._segment1._point,
			handle1 = that._segment1._handleOut,
			handle2 = that._segment2._handleIn,
			point2 = that._segment2._point,
			x, y;

		// Handle special case at beginning / end of curve
		// TODO: Port back to Scriptographer, so 0.000000000001 won't be
		// required anymore
		if (t == 0 || t == 1) {
			var point;
			switch (type) {
			case 0: // point
				point = t == 0 ? point1 : point2;
				break;
			case 1: // tangent
			case 2: // normal
				point = t == 0
					? handle1.isZero()
						? handle2.isZero()
							? point2.subtract(point1)
							: point2.add(handle2).subtract(point1)
						: handle1
					: handle2.isZero() // t == 1
						? handle1.isZero()
							? point1.subtract(point2)
							: point1.add(handle1).subtract(point2)
						: handle2;
				break;
			}
			x = point.x;
			y = point.y;
		} else {
			var dx = point2.x - point1.x,
				cx = 3 * handle1.x,
				bx = 3 * (dx + handle2.x - handle1.x) - cx,
				ax = dx - cx - bx,

				dy = point2.y - point1.y,
				cy = 3 * handle1.y,
				by = 3 * (dy + handle2.y - handle1.y) - cy,
				ay = dy - cy - by;

			switch (type) {
			case 0: // point
				x = ((ax * t + bx) * t + cx) * t + point1.x;
				y = ((ay * t + by) * t + cy) * t + point1.y;
				break;
			case 1: // tangent
			case 2: // normal
				// Simply use the derivation of the bezier function for both
				// the x and y coordinates:
				x = (3 * ax * t + 2 * bx) * t + cx,
				y = (3 * ay * t + 2 * by) * t + cy;
			}
		}
		// The normal is simply the rotated tangent:
		// TODO: Rotate normals the other way in Scriptographer too?
		// (Depending on orientation, I guess?)
		return type == 2 ? new Point(y, -x) : new Point(x, y);
	}

	function getLengthIntegrand(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
		// Calculate the coefficients of a Bezier derivative.
		var ax = 9 * (c1x - c2x) + 3 * (p2x - p1x),
			bx = 6 * (p1x + c2x) - 12 * c1x,
			cx = 3 * (c1x - p1x),

			ay = 9 * (c1y - c2y) + 3 * (p2y - p1y),
			by = 6 * (p1y + c2y) - 12 * c1y,
			cy = 3 * (c1y - p1y);

		return function(t) {
			// Calculate quadratic equations of derivatives for x and y
			var dx = (ax * t + bx) * t + cx,
				dy = (ay * t + by) * t + cy;
			return Math.sqrt(dx * dx + dy * dy);
		}
	}

	return {
		getPoint: function(parameter) {
			return evaluate(this, parameter, 0);
		},

		getTangent: function(parameter) {
			return evaluate(this, parameter, 1);
		},

		getNormal: function(parameter) {
			return evaluate(this, parameter, 2);
		},

		statics: {
			getLength: function(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, a, b) {
				if (a == undefined)
					a = 0;
				if (b == undefined)
					b = 1;
				if (p1x == c1x && p1y == c1y && p2x == c2x && p2y == c2y) {
					// Straight line
					var dx = p2x - p1x,
						dy = p2y - p1y;
					return Math.sqrt(dx * dx + dy * dy) * (b - a);
				}
				var ds = getLengthIntegrand(
						p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
				return Numerical.gauss(ds, a, b, 8);
			},

			getParameter: function(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y,
					length) {
				if (length <= 0)
					return 0;
				if (p1x == c1x && p1y == c1y && p2x == c2x && p2y == c2y) {
					// Straight line, calculate directly
					// t = length / lineLength:
					var dx = p2x - p1x,
						dy = p2y - p1y;
					return Math.min(length / Math.sqrt(dx * dx + dy * dy), 1);
				}
				var ds = getLengthIntegrand(
						p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
				// Use integrand both to calculate total length and part lengths
				// in f(t) below.
				var bezierLength = Numerical.gauss(ds, 0, 1, 8);
				if (length >= bezierLength)
					return 1;
				function f(t) {
					// The precision of 5 iterations seems enough for this
					return length - Numerical.gauss(ds, 0, t, 5);
				}
				// Let's use the Van Wijngaarden–Dekker–Brent Method to find
				// solutions more reliably than with False Position Method.
				// Use length / bezierLength for an initial guess for b, to
				// bring us closer:
				return Numerical.brent(f, 0, length / bezierLength,
						Numerical.TOLERANCE);
			},

			subdivide: function(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
				var u = 1 - t,
					// Interpolate from 4 to 3 points
					p3x = u * p1x + t * c1x,
					p3y = u * p1y + t * c1y,
					p4x = u * c1x + t * c2x,
					p4y = u * c1y + t * c2y,
					p5x = u * c2x + t * p2x,
					p5y = u * c2y + t * p2y,
					// Interpolate from 3 to 2 points
					p6x = u * p3x + t * p4x,
					p6y = u * p3y + t * p4y,
					p7x = u * p4x + t * p5x,
					p7y = u * p4y + t * p5y,
					// Interpolate from 2 points to 1 point
					p8x = u * p6x + t * p7x,
					p8y = u * p6y + t * p7y;
				// We now have all the values we need to build the subcurves
				return [
					[p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y], // left
					[p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y] // right
				];
			}
		}
	};
});
<commit_msg>Use push() instead fo concat() for better getParameter() performance.<commit_after>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://scriptographer.org/
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * All rights reserved. See LICENSE file for details.
 */

var Curve = this.Curve = Base.extend({
	beans: true,

	initialize: function(arg0, arg1, arg2, arg3) {
		if (arguments.length == 0) {
			this._segment1 = new Segment();
			this._segment2 = new Segment();
		} else if (arguments.length == 1) {
			// TODO: If beans are not activated, this won't copy from
			// an existing segment. OK?
			this._segment1 = new Segment(arg0.segment1);
			this._segment2 = new Segment(arg0.segment2);
		} else if (arguments.length == 2) {
			if (arg0 instanceof Path) {
				this._path = arg0;
				this._index1 = arg1;
				this._updateSegments();
			} else {
				this._segment1 = new Segment(arg0);
				this._segment2 = new Segment(arg1);
			}
		} else if (arguments.length == 4) {
			this._segment1 = new Segment(arg0, null, arg1);
			this._segment2 = new Segment(arg3, arg2, null);
		}
	},

	_updateSegments: function() {
		if (this._path) {
			this._index2 = this._index1 + 1;
			// A closing curve?
			var segments = this._path._segments;
			if (this._index2 >= segments.length)
				this._index2 = 0;
			this._segment1 = segments[this._index1];
			this._segment2 = segments[this._index2];
		}
	},

	/**
	 * The first anchor point of the curve.
	 */
	getPoint1: function() {
		return this._segment1._point;
	},

	setPoint1: function() {
		var point = Point.read(arguments);
		this._segment1._point.set(point.x, point.y);
	},

	/**
	 * The second anchor point of the curve.
	 */
	getPoint2: function() {
		return this._segment2._point;
	},

	setPoint2: function() {
		var point = Point.read(arguments);
		this._segment2._point.set(point.x, point.y);
	},

	/**
	 * The handle point that describes the tangent in the first anchor point.
	 */
	getHandle1: function() {
		return this._segment1._handleOut;
	},

	setHandle1: function() {
		var point = Point.read(arguments);
		this._segment1._handleOut.set(point.x, point.y);
	},

	/**
	 * The handle point that describes the tangent in the second anchor point.
	 */
	getHandle2: function() {
		return this._segment2._handleIn;
	},

	setHandle2: function() {
		var point = Point.read(arguments);
		this._segment2._handleIn.set(point.x, point.y);
	},

	/**
	 * The first segment of the curve.
	 */
	getSegment1: function() {
		return this._segment1;
	},

	/**
	 * The second segment of the curve.
	 */
	getSegment2: function() {
		return this._segment2;
	},

	getPath: function() {
		return this._path;
	},

	getIndex: function() {
		return this._index1;
	},

	_setIndex: function(index) {
		this._index1 = index;
		this._updateSegments();
	},

	getNext: function() {
		var curves = this._path && this._path._curves;
		// TODO: Add cyclic looping when closed back to Scriptographer
		return curves && (curves[this._index1 + 1]
				|| this._path.closed && curves[0]) || null;
	},

	getPrevious: function() {
		var curves = this._path && this._path._curves;
		return curves && (curves[this._index1 - 1]
				|| this._path.closed && curves[curves.length - 1]) || null;
	},

	getCurveValues: function() {
		var p1 = this._segment1._point,
			h1 = this._segment1._handleOut,
			h2 = this._segment2._handleIn,
			p2 = this._segment2._point;
		return [
			p1.x, p1.y,
			p1.x + h1.x, p1.y + h1.y,
			p2.x + h2.x, p2.y + h2.y,
			p2.x, p2.y
		];
	},

	// TODO: Port back to Scriptographer, optionally suppporting from, to
	// TODO: Replaces getPartLength(fromParameter, toParameter)?
	getLength: function(from, to) {
		var values = this.getCurveValues();
		if (arguments.length > 0)
			values.push(from, to);
		return Curve.getLength.apply(Curve, values);
	},

	/**
	 * Checks if this curve is linear, meaning it does not define any curve
	 * handle.

	 * @return {@true if the curve is linear}
	 */
	isLinear: function() {
		return this._segment1._handleOut.isZero()
				&& this._segment2._handleIn.isZero();
	},

	getParameter: function(length) {
		var values = this.getCurveValues();
		values.push(length)
		return Curve.getParameter.apply(Curve, values);
	},

	// TODO: getParameter(point, precision)
	// TODO: getLocation
	// TODO: getIntersections
	// TODO: adjustThroughPoint

	transform: function(matrix) {
		return new Curve(
				matrix.transform(this._segment1._point),
				matrix.transform(this._segment1._handleOut),
				matrix.transform(this._segment2._handleIn),
				matrix.transform(this._segment2._point));
	},

	reverse: function() {
		return new Curve(this._segment2.reverse(), this._segment1.reverse());
	},

	// TODO: divide
	// TODO: split

	clone: function() {
		return new Curve(this._segment1, this._segment2);
	},

	toString: function() {
		return '{ point1: ' + this._segment1._point
				+ (!this._segment1._handleOut.isZero()
					? ', handle1: ' + this._segment1._handleOut : '')
				+ (this._segment2._handleIn.isZero()
					? ', handle2: ' + this._segment2._handleIn : '')
				+ ', point2: ' + this._segment2._point
				+ ' }';
	}
}, new function() {
	function evaluate(that, t, type) {
		// Calculate the polynomial coefficients. caution: handles are relative
		// to points
		var point1 = that._segment1._point,
			handle1 = that._segment1._handleOut,
			handle2 = that._segment2._handleIn,
			point2 = that._segment2._point,
			x, y;

		// Handle special case at beginning / end of curve
		// TODO: Port back to Scriptographer, so 0.000000000001 won't be
		// required anymore
		if (t == 0 || t == 1) {
			var point;
			switch (type) {
			case 0: // point
				point = t == 0 ? point1 : point2;
				break;
			case 1: // tangent
			case 2: // normal
				point = t == 0
					? handle1.isZero()
						? handle2.isZero()
							? point2.subtract(point1)
							: point2.add(handle2).subtract(point1)
						: handle1
					: handle2.isZero() // t == 1
						? handle1.isZero()
							? point1.subtract(point2)
							: point1.add(handle1).subtract(point2)
						: handle2;
				break;
			}
			x = point.x;
			y = point.y;
		} else {
			var dx = point2.x - point1.x,
				cx = 3 * handle1.x,
				bx = 3 * (dx + handle2.x - handle1.x) - cx,
				ax = dx - cx - bx,

				dy = point2.y - point1.y,
				cy = 3 * handle1.y,
				by = 3 * (dy + handle2.y - handle1.y) - cy,
				ay = dy - cy - by;

			switch (type) {
			case 0: // point
				x = ((ax * t + bx) * t + cx) * t + point1.x;
				y = ((ay * t + by) * t + cy) * t + point1.y;
				break;
			case 1: // tangent
			case 2: // normal
				// Simply use the derivation of the bezier function for both
				// the x and y coordinates:
				x = (3 * ax * t + 2 * bx) * t + cx,
				y = (3 * ay * t + 2 * by) * t + cy;
			}
		}
		// The normal is simply the rotated tangent:
		// TODO: Rotate normals the other way in Scriptographer too?
		// (Depending on orientation, I guess?)
		return type == 2 ? new Point(y, -x) : new Point(x, y);
	}

	function getLengthIntegrand(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
		// Calculate the coefficients of a Bezier derivative.
		var ax = 9 * (c1x - c2x) + 3 * (p2x - p1x),
			bx = 6 * (p1x + c2x) - 12 * c1x,
			cx = 3 * (c1x - p1x),

			ay = 9 * (c1y - c2y) + 3 * (p2y - p1y),
			by = 6 * (p1y + c2y) - 12 * c1y,
			cy = 3 * (c1y - p1y);

		return function(t) {
			// Calculate quadratic equations of derivatives for x and y
			var dx = (ax * t + bx) * t + cx,
				dy = (ay * t + by) * t + cy;
			return Math.sqrt(dx * dx + dy * dy);
		}
	}

	return {
		getPoint: function(parameter) {
			return evaluate(this, parameter, 0);
		},

		getTangent: function(parameter) {
			return evaluate(this, parameter, 1);
		},

		getNormal: function(parameter) {
			return evaluate(this, parameter, 2);
		},

		statics: {
			getLength: function(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, a, b) {
				if (a == undefined)
					a = 0;
				if (b == undefined)
					b = 1;
				if (p1x == c1x && p1y == c1y && p2x == c2x && p2y == c2y) {
					// Straight line
					var dx = p2x - p1x,
						dy = p2y - p1y;
					return Math.sqrt(dx * dx + dy * dy) * (b - a);
				}
				var ds = getLengthIntegrand(
						p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
				return Numerical.gauss(ds, a, b, 8);
			},

			getParameter: function(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y,
					length) {
				if (length <= 0)
					return 0;
				if (p1x == c1x && p1y == c1y && p2x == c2x && p2y == c2y) {
					// Straight line, calculate directly
					// t = length / lineLength:
					var dx = p2x - p1x,
						dy = p2y - p1y;
					return Math.min(length / Math.sqrt(dx * dx + dy * dy), 1);
				}
				var ds = getLengthIntegrand(
						p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
				// Use integrand both to calculate total length and part lengths
				// in f(t) below.
				var bezierLength = Numerical.gauss(ds, 0, 1, 8);
				if (length >= bezierLength)
					return 1;
				function f(t) {
					// The precision of 5 iterations seems enough for this
					return length - Numerical.gauss(ds, 0, t, 5);
				}
				// Let's use the Van Wijngaarden–Dekker–Brent Method to find
				// solutions more reliably than with False Position Method.
				// Use length / bezierLength for an initial guess for b, to
				// bring us closer:
				return Numerical.brent(f, 0, length / bezierLength,
						Numerical.TOLERANCE);
			},

			subdivide: function(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
				var u = 1 - t,
					// Interpolate from 4 to 3 points
					p3x = u * p1x + t * c1x,
					p3y = u * p1y + t * c1y,
					p4x = u * c1x + t * c2x,
					p4y = u * c1y + t * c2y,
					p5x = u * c2x + t * p2x,
					p5y = u * c2y + t * p2y,
					// Interpolate from 3 to 2 points
					p6x = u * p3x + t * p4x,
					p6y = u * p3y + t * p4y,
					p7x = u * p4x + t * p5x,
					p7y = u * p4y + t * p5y,
					// Interpolate from 2 points to 1 point
					p8x = u * p6x + t * p7x,
					p8y = u * p6y + t * p7y;
				// We now have all the values we need to build the subcurves
				return [
					[p1x, p1y, p3x, p3y, p6x, p6y, p8x, p8y], // left
					[p8x, p8y, p7x, p7y, p5x, p5y, p2x, p2y] // right
				];
			}
		}
	};
});
<|endoftext|>


<commit_before>function Polynomial(args) {
	this.coefs = [];
	if (arguments[0] instanceof Array) {
		this.coefs = arguments[0];
	}
	else for (var i = 0; i<arguments.length; i++) {
		this.coefs.push(arguments[i]);
	}
}

Polynomial.evaluate = function(coefs, x) {
	if (coefs.length === 0) return 0;
	return coefs.shift() + x*Polynomial.evaluate(coefs, x);
};

Polynomial.lagrange = function(points) { // points = [[0,2], [1,5], [12,pi], ...]
	var res = new Polynomial();
	for (var j = 0; j<points.length; j++) {
		var prod = new Polynomial(1),
			pj = points[j];
		for (var i = 0; i<points.length; i++) {
			var pi = points[i];
			if (i != j) {
				var p = new Polynomial(-pi[0], 1).lin(1/(pj[0] - pi[0]));
				prod = prod.mult(p);
			}
		}
		res = res.add(prod.lin(pj[1]));
	}
	return res;
};

Polynomial.prototype.coef = function(idx) {
	return this.coefs[idx] || 0;
};

Polynomial.prototype.calc = function(x) {
	return Polynomial.evaluate(this.coefs.slice(), x);
};

Polynomial.prototype.add = function(p) {
	var t = Math.max(this.coefs.length, p.coefs.length),
		res = [];
	for (var i = 0; i<t; i++) {
		res.push(this.coef(i) + p.coef(i));
	}
	return new Polynomial(res);
};

Polynomial.prototype.lin = function(a) {
	var res = [];
	for (var i = 0; i<this.coefs.length; i++) res.push(a*this.coef(i));
	return new Polynomial(res);
};

Polynomial.prototype.mult = function(p) {
	var t = this.coefs.length + p.coefs.length - 1,
		res = [];
	for (var i = 0; i<t; i++) {
		res[i] = 0;
		for (var j = 0; j<=i; j++) {
			res[i] += this.coef(j)*p.coef(i-j);
		}
	}
	return new Polynomial(res);
};<commit_msg>Added polynomial derivation and integration.<commit_after>function Polynomial(args) {
	this.coefs = [];
	if (arguments[0] instanceof Array) {
		this.coefs = arguments[0];
	}
	else for (var i = 0; i<arguments.length; i++) {
		this.coefs.push(arguments[i]);
	}
}

Polynomial.evaluate = function(coefs, x) {
	if (coefs.length === 0) return 0;
	return coefs.shift() + x*Polynomial.evaluate(coefs, x);
};

Polynomial.lagrange = function(points) { // points = [[0,2], [1,5], [12,pi], ...]
	var res = new Polynomial();
	for (var j = 0; j<points.length; j++) {
		var prod = new Polynomial(1),
			pj = points[j];
		for (var i = 0; i<points.length; i++) {
			var pi = points[i];
			if (i != j) {
				var p = new Polynomial(-pi[0], 1).lin(1/(pj[0] - pi[0]));
				prod = prod.mult(p);
			}
		}
		res = res.add(prod.lin(pj[1]));
	}
	return res;
};

Polynomial.prototype.coef = function(idx) {
	return this.coefs[idx] || 0;
};

Polynomial.prototype.calc = function(x) {
	return Polynomial.evaluate(this.coefs.slice(), x);
};

Polynomial.prototype.add = function(p) {
	var t = Math.max(this.coefs.length, p.coefs.length),
		res = [];
	for (var i = 0; i<t; i++) {
		res.push(this.coef(i) + p.coef(i));
	}
	return new Polynomial(res);
};

Polynomial.prototype.lin = function(a) {
	var res = [];
	for (var i = 0; i<this.coefs.length; i++) res.push(a*this.coef(i));
	return new Polynomial(res);
};

Polynomial.prototype.mult = function(p) {
	var t = this.coefs.length + p.coefs.length - 1,
		res = [];
	for (var i = 0; i<t; i++) {
		res[i] = 0;
		for (var j = 0; j<=i; j++) {
			res[i] += this.coef(j)*p.coef(i-j);
		}
	}
	return new Polynomial(res);
};

Polynomial.prototype.deriv = function() {
	return new Polynomial(this.coefs.slice(1));
};

Polynomial.prototype.int = function(c) {
	var coefs = [c];
	for (var i = 0; i<this.coefs.length; i++) coefs.push(this.coefs[i]);
	return new Polynomial(coefs);
};<|endoftext|>


<commit_before>const oppositeDockMap = {
  top: 'bottom',
  right: 'left',
  bottom: 'top',
  left: 'right'
};

export function oppositeDock(dock) {
  return oppositeDockMap[dock];
}

export function getDocks(dock) {
  let order = [dock];
  if (dock === 'top') {
    order = order.concat(['bottom', 'right', 'left']);
  } else if (dock === 'right') {
    order = order.concat(['bottom', 'left', 'top']);
  } else if (dock === 'left') {
    order = order.concat(['bottom', 'right', 'top']);
  } else {
    order = order.concat(['top', 'right', 'left']);
  }
  return order;
}

export function addOffset(dock, left = 0, top = 0, offset = 0) {
  if (dock === 'top') {
    return {
      top: top - offset,
      left
    };
  } else if (dock === 'right') {
    return {
      top,
      left: left + offset
    };
  } else if (dock === 'left') {
    return {
      top,
      left: left - offset
    };
  }
  return {
    top: top + offset,
    left
  };
}

export function createRect(top = 0, left = 0, width = 0, height = 0) {
  return {
    top,
    right: left + width,
    bottom: top + height,
    left,
    width,
    height
  };
}

export function getDockCenterPoint(rect, dock) {
  let top;
  let left;
  if (dock === 'top') {
    top = rect.top;
    left = rect.left + rect.width / 2;
  } else if (dock === 'right') {
    top = rect.top + rect.height / 2;
    left = rect.right;
  } else if (dock === 'left') {
    top = rect.top + rect.height / 2;
    left = rect.left;
  } else {
    top = rect.bottom;
    left = rect.left + rect.width / 2;
  }
  return {
    top,
    left
  };
}

export function tryPosition(rect, withinRect) {
  const left = rect.left >= withinRect.left;
  const right = rect.right <= withinRect.right;
  const top = rect.top >= withinRect.top;
  const bottom = rect.bottom <= withinRect.bottom;

  return {
    left,
    right,
    top,
    bottom
  };
}

export function createTryRect(elemRect, toPosition, dock, offset) {
  let top;
  let left;
  if (dock === 'top') {
    top = toPosition.top - elemRect.height - offset;
    left = toPosition.left - elemRect.width / 2;
  } else if (dock === 'right') {
    top = toPosition.top - elemRect.height / 2;
    left = toPosition.left + offset;
  } else if (dock === 'left') {
    top = toPosition.top - elemRect.height / 2;
    left = toPosition.left - elemRect.width - offset;
  } else {
    top = toPosition.top + offset;
    left = toPosition.left - elemRect.width / 2;
  }

  return createRect(top, left, elemRect.width, elemRect.height);
}

export function tryDock(elemRect, alignToRect, windowRect, dock, options = {}) {
  const {
    offset = 0,
    minWindowOffset = 0,
    minEdgeOffset = 0
  } = options;

  const windowOffsetRect = createRect(
    windowRect.top + minWindowOffset,
    windowRect.left + minWindowOffset,
    windowRect.width - minWindowOffset * 2,
    windowRect.height - minWindowOffset * 2
  );

  const toPosition = getDockCenterPoint(alignToRect, dock);
  const tryRect = createTryRect(elemRect, toPosition, dock, offset);
  let fitResult = tryPosition(tryRect, windowOffsetRect);
  if (dock === 'top' || dock === 'bottom') {
    if (!fitResult.left) {
      tryRect.left = Math.min(windowOffsetRect.left, toPosition.left - minEdgeOffset);
      tryRect.right = tryRect.left + tryRect.width;
      fitResult = tryPosition(tryRect, windowOffsetRect);
    }
    if (!fitResult.right) {
      tryRect.right = Math.max(windowOffsetRect.right, toPosition.left + minEdgeOffset);
      tryRect.left = tryRect.right - tryRect.width;
      fitResult = tryPosition(tryRect, windowOffsetRect);
    }
  } else {
    if (!fitResult.top) {
      tryRect.top = Math.min(windowOffsetRect.top, toPosition.top - minEdgeOffset);
      tryRect.bottom = tryRect.top + tryRect.height;
      fitResult = tryPosition(tryRect, windowOffsetRect);
    }
    if (!fitResult.bottom) {
      tryRect.bottom = Math.max(windowOffsetRect.bottom, toPosition.top + minWindowOffset);
      tryRect.top = tryRect.bottom - tryRect.height;
      fitResult = tryPosition(tryRect, windowOffsetRect);
    }
  }

  return {
    fits: fitResult.top && fitResult.right && fitResult.bottom && fitResult.left,
    dock,
    position: {
      left: tryRect.left,
      top: tryRect.top
    },
    toPosition: getDockCenterPoint(alignToRect, dock)
  };
}

export function positionToRect(element, rect, dock = 'bottom', options = {}) {
  const elemRect = element.getBoundingClientRect();
  const scrollTop = document.body.scrollTop;
  const scrollLeft = document.body.scrollLeft;
  const windowRect = createRect(
    0,
    0,
    document.body.clientWidth,
    document.body.clientHeight
  );

  const getOffset = (fromElement) => {
    const parent = fromElement.offsetParent;
    if (parent) {
      const parentOffset = getOffset(parent);
      return {
        top: parent.offsetTop + parentOffset.top,
        left: parent.offsetLeft + parentOffset.left
      };
    }
    return {
      top: 0,
      left: 0
    };
  };

  const docks = getDocks(dock);
  let firstResult = null;
  for (let i = 0; i < docks.length; i++) {
    const result = tryDock(elemRect, rect, windowRect, docks[i], options);
    result.position.top += scrollTop;
    result.toPosition.top += scrollTop;
    result.position.left += scrollLeft;
    result.toPosition.left += scrollLeft;

    if (options.containerElement) {
      const offset = getOffset(options.containerElement);
      result.position.left -= offset.left;
      result.position.top -= offset.top;
      result.toPosition.left -= offset.left;
      result.toPosition.top -= offset.top;
    }

    if (result.fits) {
      return result;
    }
    if (i === 0) {
      firstResult = result;
    }
  }
  // If no fit is found - return the first position
  return firstResult;
}

export function positionToElement(element, alignToElement, dock = 'bottom', options = {}) {
  const rect = alignToElement.getBoundingClientRect();
  return positionToRect(element, rect, dock, options);
}

export function positionToCoordinate(element, x, y, dock = 'bottom', options = {}) {
  const rect = {
    top: y,
    bottom: y,
    left: x,
    right: x,
    width: 0,
    height: 0
  };
  return positionToRect(element, rect, dock, options);
}
<commit_msg>Fix firefox positioning problem<commit_after>const oppositeDockMap = {
  top: 'bottom',
  right: 'left',
  bottom: 'top',
  left: 'right'
};

export function oppositeDock(dock) {
  return oppositeDockMap[dock];
}

export function getDocks(dock) {
  let order = [dock];
  if (dock === 'top') {
    order = order.concat(['bottom', 'right', 'left']);
  } else if (dock === 'right') {
    order = order.concat(['bottom', 'left', 'top']);
  } else if (dock === 'left') {
    order = order.concat(['bottom', 'right', 'top']);
  } else {
    order = order.concat(['top', 'right', 'left']);
  }
  return order;
}

export function addOffset(dock, left = 0, top = 0, offset = 0) {
  if (dock === 'top') {
    return {
      top: top - offset,
      left
    };
  } else if (dock === 'right') {
    return {
      top,
      left: left + offset
    };
  } else if (dock === 'left') {
    return {
      top,
      left: left - offset
    };
  }
  return {
    top: top + offset,
    left
  };
}

export function createRect(top = 0, left = 0, width = 0, height = 0) {
  return {
    top,
    right: left + width,
    bottom: top + height,
    left,
    width,
    height
  };
}

export function getDockCenterPoint(rect, dock) {
  let top;
  let left;
  if (dock === 'top') {
    top = rect.top;
    left = rect.left + rect.width / 2;
  } else if (dock === 'right') {
    top = rect.top + rect.height / 2;
    left = rect.right;
  } else if (dock === 'left') {
    top = rect.top + rect.height / 2;
    left = rect.left;
  } else {
    top = rect.bottom;
    left = rect.left + rect.width / 2;
  }
  return {
    top,
    left
  };
}

export function tryPosition(rect, withinRect) {
  const left = rect.left >= withinRect.left;
  const right = rect.right <= withinRect.right;
  const top = rect.top >= withinRect.top;
  const bottom = rect.bottom <= withinRect.bottom;

  return {
    left,
    right,
    top,
    bottom
  };
}

export function createTryRect(elemRect, toPosition, dock, offset) {
  let top;
  let left;
  if (dock === 'top') {
    top = toPosition.top - elemRect.height - offset;
    left = toPosition.left - elemRect.width / 2;
  } else if (dock === 'right') {
    top = toPosition.top - elemRect.height / 2;
    left = toPosition.left + offset;
  } else if (dock === 'left') {
    top = toPosition.top - elemRect.height / 2;
    left = toPosition.left - elemRect.width - offset;
  } else {
    top = toPosition.top + offset;
    left = toPosition.left - elemRect.width / 2;
  }

  return createRect(top, left, elemRect.width, elemRect.height);
}

export function tryDock(elemRect, alignToRect, windowRect, dock, options = {}) {
  const {
    offset = 0,
    minWindowOffset = 0,
    minEdgeOffset = 0
  } = options;

  const windowOffsetRect = createRect(
    windowRect.top + minWindowOffset,
    windowRect.left + minWindowOffset,
    windowRect.width - minWindowOffset * 2,
    windowRect.height - minWindowOffset * 2
  );

  const toPosition = getDockCenterPoint(alignToRect, dock);
  const tryRect = createTryRect(elemRect, toPosition, dock, offset);
  let fitResult = tryPosition(tryRect, windowOffsetRect);
  if (dock === 'top' || dock === 'bottom') {
    if (!fitResult.left) {
      tryRect.left = Math.min(windowOffsetRect.left, toPosition.left - minEdgeOffset);
      tryRect.right = tryRect.left + tryRect.width;
      fitResult = tryPosition(tryRect, windowOffsetRect);
    }
    if (!fitResult.right) {
      tryRect.right = Math.max(windowOffsetRect.right, toPosition.left + minEdgeOffset);
      tryRect.left = tryRect.right - tryRect.width;
      fitResult = tryPosition(tryRect, windowOffsetRect);
    }
  } else {
    if (!fitResult.top) {
      tryRect.top = Math.min(windowOffsetRect.top, toPosition.top - minEdgeOffset);
      tryRect.bottom = tryRect.top + tryRect.height;
      fitResult = tryPosition(tryRect, windowOffsetRect);
    }
    if (!fitResult.bottom) {
      tryRect.bottom = Math.max(windowOffsetRect.bottom, toPosition.top + minWindowOffset);
      tryRect.top = tryRect.bottom - tryRect.height;
      fitResult = tryPosition(tryRect, windowOffsetRect);
    }
  }

  return {
    fits: fitResult.top && fitResult.right && fitResult.bottom && fitResult.left,
    dock,
    position: {
      left: tryRect.left,
      top: tryRect.top
    },
    toPosition: getDockCenterPoint(alignToRect, dock)
  };
}

export function positionToRect(element, rect, dock = 'bottom', options = {}) {
  const elemRect = element.getBoundingClientRect();
  const pageYOffset = window.pageYOffset;
  const pageXOffset = window.pageXOffset;
  const windowRect = createRect(
    0,
    0,
    document.body.clientWidth,
    document.body.clientHeight
  );

  const getOffset = (fromElement) => {
    const parent = fromElement.offsetParent;
    if (parent) {
      const parentOffset = getOffset(parent);
      return {
        top: parent.offsetTop + parentOffset.top,
        left: parent.offsetLeft + parentOffset.left
      };
    }
    return {
      top: 0,
      left: 0
    };
  };

  const docks = getDocks(dock);
  let firstResult = null;
  for (let i = 0; i < docks.length; i++) {
    const result = tryDock(elemRect, rect, windowRect, docks[i], options);
    result.position.top += pageYOffset;
    result.toPosition.top += pageYOffset;
    result.position.left += pageXOffset;
    result.toPosition.left += pageXOffset;

    if (options.containerElement) {
      const offset = getOffset(options.containerElement);
      result.position.left -= offset.left;
      result.position.top -= offset.top;
      result.toPosition.left -= offset.left;
      result.toPosition.top -= offset.top;
    }

    if (result.fits) {
      return result;
    }
    if (i === 0) {
      firstResult = result;
    }
  }
  // If no fit is found - return the first position
  return firstResult;
}

export function positionToElement(element, alignToElement, dock = 'bottom', options = {}) {
  const rect = alignToElement.getBoundingClientRect();
  return positionToRect(element, rect, dock, options);
}

export function positionToCoordinate(element, x, y, dock = 'bottom', options = {}) {
  const rect = {
    top: y,
    bottom: y,
    left: x,
    right: x,
    width: 0,
    height: 0
  };
  return positionToRect(element, rect, dock, options);
}
<|endoftext|>


<commit_before>//By Kevin Le - http://stackoverflow.com/users/1244013/khnle
//v1.0

angular.module('ui.bootstrap.progresscircle', [])

.constant('progressConfig', {
  elementWidth: 400,
  elementHeight: 400,
  outerCircleWidth: 20,
  innerCircleWidth: 5,
  outerCircleRadius: 100,
  innerCircleRadius: 70,
  labelFont: '30pt Calibri',
  outerCircleBackgroundColor: '#d9d9d9',
  outerCircleForegroundColor: '#428bca',
  innerCircleColor: '#d9d9d9',
  labelColor: '#428bca',
  percentFormat: false,
  displayPercentSign: true,
  max: 60,
  displayMax: true
})

.controller('ProgressCircleController', ['$scope', '$attrs', '$timeout', 'progressConfig', function($scope, $attrs, $timeout, progressConfig) {
//just a place holder for now
}])

.directive('progressCircle', ['$parse', 'progressConfig', function(parse, progressConfig) {
  return {
    restrict: 'EA',
    replace: true,
    transclude: true,
    controller: 'ProgressCircleController',
    link: function(s, e, a, progressCtrl) {

      var width = parse(a.elementWidth)(s) || progressConfig.elementWidth,
          height = parse(a.elementHeight)(s) || progressConfig.elementHeight,
          outerCircleWidth = parse(a.outerCircleWidth)(s) || progressConfig.outerCircleWidth,
          innerCircleWidth = parse(a.innerCircleWidth)(s) || progressConfig.innerCircleWidth,
          outerCircleBackgroundColor = parse(a.outerCircleBackgroundColor)(s) || progressConfig.outerCircleBackgroundColor,
          outerCircleForegroundColor = parse(a.outerCircleForegroundColor)(s) || progressConfig.outerCircleForegroundColor,
          innerCircleColor = parse(a.innerCircleColor)(s) || progressConfig.innerCircleColor,
          labelColor = parse(a.labelColor)(s) || progressConfig.labelColor,
          outerCircleRadius = parse(a.outerCircleRadius)(s) || progressConfig.outerCircleRadius,
          innerCircleRadius = parse(a.innerCircleRadius)(s) || progressConfig.innerCircleRadius,
          labelFont = parse(a.labelFont)(s) || progressConfig.labelFont,
          percentFormat = parse(a.percentFormat)(s) || progressConfig.percentFormat,
          displayPercentSign = parse(a.displayPercentSign)(s) || progressConfig.displayPercentSign,
          max = parse(a.max)(s) || progressConfig.max,
          displayMax = parse(a.displayMax)(s) || progressConfig.displayMax;

      var canvas = angular.element('<canvas>').attr({'width': width, 'height': height});

      e.replaceWith(canvas);

      s.$watch(a.progressCircleModel, function(newValue) {
        // Create the content of the canvas
        var ctx = canvas[0].getContext('2d');
        ctx.clearRect(0, 0, width, height);

        // The "background" circle
        var x = width / 2;
        var y = height / 2;
        ctx.beginPath();
        ctx.arc(x, y, outerCircleRadius, 0, Math.PI * 2, false);
        ctx.lineWidth = outerCircleWidth;
        ctx.strokeStyle = outerCircleBackgroundColor;
        ctx.stroke();

        // The inner circle
        ctx.beginPath();
        ctx.arc(x, y, innerCircleRadius, 0, Math.PI * 2, false);
        ctx.lineWidth = innerCircleWidth;
        ctx.strokeStyle = innerCircleColor;
        ctx.stroke();

        // The inner number
        ctx.font = labelFont;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillStyle = labelColor;
        if (percentFormat) {
          if (displayPercentSign) {
            ctx.fillText(newValue.value + ' %', x, y);
          } else {
            ctx.fillText(newValue.value, x, y);
          }
        } else {
          if (displayMax) {
            ctx.fillText(newValue.value + '/' + max, x, y);
          } else {
            ctx.fillText(newValue.value, x, y);
          }
        }

        // The "foreground" circle
        var startAngle = - (Math.PI / 2);
        var endAngle = percentFormat ? ((Math.PI * 2 ) * (newValue.value/100)) - (Math.PI / 2):
          ((Math.PI * 2 ) * (newValue.value/max)) - (Math.PI / 2);
        var anticlockwise = false;
        ctx.beginPath();
        ctx.arc(x, y, outerCircleRadius, startAngle, endAngle, anticlockwise);
        ctx.lineWidth = outerCircleWidth;
        ctx.strokeStyle = outerCircleForegroundColor;
        ctx.stroke();
      }, true);
    }
  };
}]);

<commit_msg>use === to compare<commit_after>//By Kevin Le - http://stackoverflow.com/users/1244013/khnle
//v1.0

angular.module('ui.bootstrap.progresscircle', [])

.constant('progressConfig', {
  elementWidth: 400,
  elementHeight: 400,
  outerCircleWidth: 20,
  innerCircleWidth: 5,
  outerCircleRadius: 100,
  innerCircleRadius: 70,
  labelFont: '30pt Calibri',
  outerCircleBackgroundColor: '#d9d9d9',
  outerCircleForegroundColor: '#428bca',
  innerCircleColor: '#d9d9d9',
  labelColor: '#428bca',
  percentFormat: true,
  displayPercentSign: true,
  max: 60,
  displayMax: true
})

.controller('ProgressCircleController', ['$scope', '$attrs', '$timeout', 'progressConfig', function($scope, $attrs, $timeout, progressConfig) {
//just a place holder for now
}])

.directive('progressCircle', ['$parse', 'progressConfig', function(parse, progressConfig) {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    controller: 'ProgressCircleController',
    link: function(s, e, a, progressCtrl) {

      var width = a.elementWidth || progressConfig.elementWidth,
          height = a.elementHeight || progressConfig.elementHeight,
          outerCircleWidth = a.outerCircleWidth || progressConfig.outerCircleWidth,
          innerCircleWidth = a.innerCircleWidth || progressConfig.innerCircleWidth,
          outerCircleBackgroundColor = a.outerCircleBackgroundColor || progressConfig.outerCircleBackgroundColor,
          outerCircleForegroundColor = a.outerCircleForegroundColor || progressConfig.outerCircleForegroundColor,
          innerCircleColor = a.innerCircleColor || progressConfig.innerCircleColor,
          labelColor = a.labelColor || progressConfig.labelColor,
          outerCircleRadius = a.outerCircleRadius || progressConfig.outerCircleRadius,
          innerCircleRadius = a.innerCircleRadius || progressConfig.innerCircleRadius,
          labelFont = a.labelFont || progressConfig.labelFont,
          percentFormat = a.percentFormat || progressConfig.percentFormat,
          displayPercentSign = a.displayPercentSign || progressConfig.displayPercentSign,
          max = a.max || progressConfig.max,
          displayMax = a.displayMax || progressConfig.displayMax;

      var canvas = angular.element('<canvas>').attr({'width': width, 'height': height});

      e.replaceWith(canvas);

      s.$watch(a.progressCircleModel, function(newValue) {
        // Create the content of the canvas
        var ctx = canvas[0].getContext('2d');
        ctx.clearRect(0, 0, width, height);

        // The "background" circle
        var x = width / 2;
        var y = height / 2;
        ctx.beginPath();
        ctx.arc(x, y, outerCircleRadius, 0, Math.PI * 2, false);
        ctx.lineWidth = outerCircleWidth;
        ctx.strokeStyle = outerCircleBackgroundColor;
        ctx.stroke();

        // The inner circle
        ctx.beginPath();
        ctx.arc(x, y, innerCircleRadius, 0, Math.PI * 2, false);
        ctx.lineWidth = innerCircleWidth;
        ctx.strokeStyle = innerCircleColor;
        ctx.stroke();

        // The inner number
        ctx.font = labelFont;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillStyle = labelColor;
        if (percentFormat === true) {
          if (displayPercentSign === true) {
            ctx.fillText(newValue.value + ' %', x, y);
          } else {
            ctx.fillText(newValue.value, x, y);
          }
        } else {
          if (displayMax === true) {
            ctx.fillText(newValue.value + '/' + max, x, y);
          } else {
            ctx.fillText(newValue.value, x, y);
          }
        }

        // The "foreground" circle
        var startAngle = - (Math.PI / 2);
        var endAngle = percentFormat ? ((Math.PI * 2 ) * (newValue.value/100)) - (Math.PI / 2):
          ((Math.PI * 2 ) * (newValue.value/max)) - (Math.PI / 2);
        var anticlockwise = false;
        ctx.beginPath();
        ctx.arc(x, y, outerCircleRadius, startAngle, endAngle, anticlockwise);
        ctx.lineWidth = outerCircleWidth;
        ctx.strokeStyle = outerCircleForegroundColor;
        ctx.stroke();
      }, true);
<|endoftext|>


<commit_before>export function project(d, options){
    return {
        x: options.origin[0] + options.scale * d.x,
        y: options.origin[1] + options.scale * d.y
    };
}
<commit_msg>markup<commit_after>export function project(d, options){
    return {
        x:  (options.origin[0] + options.scale * d.x),
        y: -(options.origin[1] + options.scale * d.y)
    };
}
<|endoftext|>


<commit_before>/**
 * Created by avim on 11/9/2014.
 */
'use strict';
var cheerio = require('cheerio');
var _ = require('lodash');
var esprima = require('esprima');
var escodegen = require('escodegen');
var React = require('react');
var fs = require('fs');

var repeatTemplate = _.template('_.map(<%= collection %>,<%= repeatFunction %>.bind(<%= repeatBinds %>))');
var ifTemplate = _.template('((<%= condition %>)?(<%= body %>):null)');
var classSetTemplate = _.template('React.addons.classSet(<%= classSet %>)');
var simpleTagTemplate = _.template('<%= name %>(<%= props %><%= children %>)');
var tagTemplate = _.template('<%= name %>.apply(this,_.flatten([<%= props %><%= children %>]))');
var commentTemplate = _.template(' /* <%= data %> */ ');
var templateTemplate = _.template("define([<%= requirePaths %>], function (<%= requireNames %>) {\n'use strict';\n <%= injectedFunctions %>\nreturn function(){ return <%= body %>};\n});");

var templateProp = 'rt-repeat';
var ifProp = 'rt-if';
var classSetProp = 'rt-class';
var scopeProp = 'rt-scope';

var reactSupportedAttributes = ['accept', 'acceptCharset', 'accessKey', 'action', 'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete', 'autoPlay', 'cellPadding', 'cellSpacing', 'charSet', 'checked', 'classID', 'className', 'cols', 'colSpan', 'content', 'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data', 'dateTime', 'defer', 'dir', 'disabled', 'download', 'draggable', 'encType', 'form', 'formNoValidate', 'frameBorder', 'height', 'hidden', 'href', 'hrefLang', 'htmlFor', 'httpEquiv', 'icon', 'id', 'label', 'lang', 'list', 'loop', 'manifest', 'max', 'maxLength', 'media', 'mediaGroup', 'method', 'min', 'multiple', 'muted', 'name', 'noValidate', 'open', 'pattern', 'placeholder', 'poster', 'preload', 'radioGroup', 'readOnly', 'rel', 'required', 'role', 'rows', 'rowSpan', 'sandbox', 'scope', 'scrolling', 'seamless', 'selected', 'shape', 'size', 'sizes', 'span', 'spellCheck', 'src', 'srcDoc', 'srcSet', 'start', 'step', 'style', 'tabIndex', 'target', 'title', 'type', 'useMap', 'value', 'width', 'wmode'];
var attributesMapping = {'class': 'className', 'rt-class': 'className'};
_.forEach(reactSupportedAttributes,function (attributeReactName) {
    if (attributeReactName !== attributeReactName.toLowerCase()) {
        attributesMapping[attributeReactName.toLowerCase()] = attributeReactName;
    }
});

function concatChildren(children) {
    var res = '';
    _.forEach(children, function (child) {
        if (child.indexOf(' /*') !== 0 && child) {
            res += ',' + child;
        } else {
            res += child;
        }
    }, this);
    return res;
}

function convertToCamelCase(str) {
    return str.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
}

function capitalize(str) {
    return str[0].toUpperCase() + str.slice(1);
}

var curlyMap = {'{': 1, '}': -1};

function convertText(txt) {
    txt = txt.trim();
    var res = '';
    var first = true;
    while (txt.indexOf('{') !== -1) {
        var start = txt.indexOf('{');
        var pre = txt.substr(0,start);
        if (pre) {
            res += (first ? '' : '+') + JSON.stringify(pre);
            first = false;
        }
        var curlyCounter = 1;
        for (var end = start + 1; end < txt.length && curlyCounter > 0; end++) {
            curlyCounter += curlyMap[txt.charAt(end)] || 0;
        }
        if (curlyCounter !== 0) {
            throw 'Failed to parse text';
        } else {
            res += (first ? '' : '+') + txt.substr(start + 1, end - start - 2);
            first = false;
            txt = txt.substr(end);
        }
    }
    if (txt) {
        res += (first ? '' : '+') + JSON.stringify(txt);
    }
    if (res === "") {
        res = "true";
    }

    return res;
}

function isStringOnlyCode(txt) {
    txt = txt.trim();
    return txt.length && txt.charAt(0) === '{' && txt.charAt(txt.length - 1) === '}';
}

function generateInjectedFunc(context, namePrefix, body, extraParams) {
    var generatedFuncName = namePrefix.replace(",","") + (context.injectedFunctions.length + 1);
    var params = context.boundParams;
    if (extraParams && extraParams.trim().length > 0) {
        params = params.concat(extraParams.trim());
    }

    var funcText = "function " + generatedFuncName + "(" + params.join(",");
    funcText += ") {\n" + body + "\n}\n";
    context.injectedFunctions.push(funcText);
    return generatedFuncName;
}

function generateProps(node, context) {
    var props = {};
    _.forOwn(node.attribs, function (val, key) {
        var propKey = attributesMapping[key.toLowerCase()] || key;
        if (props.hasOwnProperty(propKey)) {
            throw 'duplicate definition of ' + propKey + ' ' + JSON.stringify(node.attribs);
        }
        if (key.indexOf('on') === 0 && !isStringOnlyCode(val)) {
            var funcParts = val.split('=>');
            var evtParams = funcParts[0].replace('(', '').replace(')', '').trim();
            var funcBody = funcParts[1].trim();
            var generatedFuncName = generateInjectedFunc(context, key, funcBody,evtParams);
            props[propKey] = generatedFuncName + ".bind(" + (["this"].concat(context.boundParams)).join(",") + ")";
        } else if (key === "style" && !isStringOnlyCode(val)) {
            var styleParts = val.trim().split(";");
            styleParts = _.compact(_.map(styleParts, function (str) {
                str = str.trim();
                if (!str || str.indexOf(':') === -1) {
                    return null;
                }
                var res = str.split(':');
                res[0] = res[0].trim();
                res[1] = res[1].trim();
                return res;
            }));
            var styleArray = [];
            _.forEach(styleParts, function (stylePart) {
                styleArray.push(convertToCamelCase(stylePart[0]) + ' : ' + convertText(stylePart[1]));
            });
            props[propKey] = '{' + styleArray.join(',') + '}';
        } else if (key === classSetProp) {
            props[propKey] = classSetTemplate({classSet: val});
        } else if (key.indexOf('rt-') !== 0) {
            props[propKey] = convertText(val);
        }
    });

    return '{' + _.map(props, function (val, key) {
        return JSON.stringify(key) + ' : ' + val;
    }).join(',') + '}';
}

function convertTagNameToConstructor(tagName) {
    return React.DOM.hasOwnProperty(tagName) ? 'React.DOM.' + tagName : tagName;
}

function defaultContext() {
    return {
        boundParams: [],
        injectedFunctions: []
    };
}

function addIfNotThere(array, obj) {
    if (!_.contains(array, obj)) {
        array.push(obj);
    }
}

function hasNonSimpleChildren(node) {
  return _.any(node.children,function (child) {
    return child.type === 'tag' && child.attribs[templateProp];
  });
}

function convertHtmlToReact(node, context) {
    if (node.type === 'tag') {
        context = {
            boundParams: _.clone(context.boundParams),
            injectedFunctions: context.injectedFunctions
        };

        var data = {name: convertTagNameToConstructor(node.name)};
        if (node.attribs[scopeProp]) {
            data.scopeName = node.attribs[scopeProp].split(" as ")[1].trim();
            data.scopeValue = node.attribs[scopeProp].split(" as ")[0].trim();
            addIfNotThere(context.boundParams, data.scopeName);
        }

        if (node.attribs[templateProp]) {
            data.item = node.attribs[templateProp].split(' in ')[0].trim();
            data.collection = node.attribs[templateProp].split(' in ')[1].trim();
            addIfNotThere(context.boundParams, data.item);
            addIfNotThere(context.boundParams, data.item + 'Index');
        }
        data.props = generateProps(node, context);
        if (node.attribs[ifProp]) {
            data.condition = node.attribs[ifProp].trim();
        }
        data.children = concatChildren(_.map(node.children, function (child) {
            return convertHtmlToReact(child, context);
        }));

        if (hasNonSimpleChildren(node)) {
          data.body = tagTemplate(data);
        } else {
          data.body = simpleTagTemplate(data);
        }

        if (node.attribs[templateProp]) {
            data.repeatFunction = generateInjectedFunc(context,"repeat"+capitalize(data.item),"return "+data.body);
            data.repeatBinds = ["this"].concat(_.reject(context.boundParams, function (param) {
                return (param === data.item || param === data.item+"Index");
            }));
            console.log(data.repeatBinds);
            data.body = repeatTemplate(data);
        }
        if (node.attribs[ifProp]) {
            data.body = ifTemplate(data);
        }
        if (node.attribs[scopeProp]) {
            var generatedFuncName = generateInjectedFunc(context,"scope"+capitalize(data.scopeName),"return "+data.body);
            var scopeParams = _.map(context.boundParams, function (param) {
                return param === data.scopeName?data.scopeValue:param;
            });
            data.body = generatedFuncName + ".apply(this, [" + scopeParams.join(",") + "])";
        }
        return data.body;
    } else if (node.type === 'comment') {
        return (commentTemplate(node));
    } else if (node.type === 'text') {
        if (node.data.trim()) {
            return convertText(node.data.trim());
        }
        return '';
    }
}

function extractDefinesFromJSXTag(html, defines) {
    html = html.replace(/\<\!doctype jsx\s*(.*?)\s*\>/i, function(full, reqStr) {
        var match = true;
        while (match) {
            match = false;
            reqStr = reqStr.replace(/\s*(\w+)\s*\=\s*\"([^\"]*)\"\s*/, function(full, varName, reqPath) {
                defines[reqPath] = varName;
                match = true;
                return '';
            });
        }
        return '';
    });
    return html;
}

/**
 * @param {string} html
 * @return {string}
 */
function convertTemplateToReact(html) {
//    var x = cheerio.load(html);
    var defines = {react: 'React', lodash: '_'};
    html = extractDefinesFromJSXTag(html, defines);
    var rootNode = cheerio.load(html.trim(), {lowerCaseTags: false, lowerCaseAttributeNames: false, xmlMode: true});
    var context = defaultContext();
    var body = convertHtmlToReact(rootNode.root()[0].children[0], context);
    var requirePaths = _(defines).keys().map(function (reqName) { return '"' + reqName + '"'; }).value().join(',');
    var requireVars = _(defines).values().value().join(',');
    var data = {body: body, injectedFunctions: '', requireNames: requireVars, requirePaths: requirePaths};
    data.injectedFunctions = context.injectedFunctions.join('\n');
    var code = templateTemplate(data);
    try {
        var tree = esprima.parse(code, {range: true, tokens: true, comment: true});
        tree = escodegen.attachComments(tree, tree.comments, tree.tokens);
        code = escodegen.generate(tree, {comment: true});
    } catch (e) {
        // TODO error handling
        console.log(e);
    }
    return code;
}

/**
 * @param {string} source
 * @param {string} target
 */
function convertFile(source, target) {
//    if (path.extname(filename) !== ".html") {
//        console.log('invalid file, only handle html files');
//        return;// only handle html files
//    }
    var util = require('./util');

    if (!util.isStale(source, target)) {
        console.log('target file ' + target + ' is up to date, skipping');
//        return;
    }

    var html = fs.readFileSync(source).toString();
    if (!html.match(/\<\!doctype jsx/i)) {
        throw new Error('invalid file, missing header');
    }
    var js = convertTemplateToReact(html);
    fs.writeFileSync(target, js);
}

module.exports = {
    convertTemplateToReact: convertTemplateToReact,
    convertFile: convertFile,
    _test: {}
};
<commit_msg>support multi param scoping<commit_after>/**
 * Created by avim on 11/9/2014.
 */
'use strict';
var cheerio = require('cheerio');
var _ = require('lodash');
var esprima = require('esprima');
var escodegen = require('escodegen');
var React = require('react');
var fs = require('fs');

var repeatTemplate = _.template('_.map(<%= collection %>,<%= repeatFunction %>.bind(<%= repeatBinds %>))');
var ifTemplate = _.template('((<%= condition %>)?(<%= body %>):null)');
var classSetTemplate = _.template('React.addons.classSet(<%= classSet %>)');
var simpleTagTemplate = _.template('<%= name %>(<%= props %><%= children %>)');
var tagTemplate = _.template('<%= name %>.apply(this,_.flatten([<%= props %><%= children %>]))');
var commentTemplate = _.template(' /* <%= data %> */ ');
var templateTemplate = _.template("define([<%= requirePaths %>], function (<%= requireNames %>) {\n'use strict';\n <%= injectedFunctions %>\nreturn function(){ return <%= body %>};\n});");

var templateProp = 'rt-repeat';
var ifProp = 'rt-if';
var classSetProp = 'rt-class';
var scopeProp = 'rt-scope';

var reactSupportedAttributes = ['accept', 'acceptCharset', 'accessKey', 'action', 'allowFullScreen', 'allowTransparency', 'alt', 'async', 'autoComplete', 'autoPlay', 'cellPadding', 'cellSpacing', 'charSet', 'checked', 'classID', 'className', 'cols', 'colSpan', 'content', 'contentEditable', 'contextMenu', 'controls', 'coords', 'crossOrigin', 'data', 'dateTime', 'defer', 'dir', 'disabled', 'download', 'draggable', 'encType', 'form', 'formNoValidate', 'frameBorder', 'height', 'hidden', 'href', 'hrefLang', 'htmlFor', 'httpEquiv', 'icon', 'id', 'label', 'lang', 'list', 'loop', 'manifest', 'max', 'maxLength', 'media', 'mediaGroup', 'method', 'min', 'multiple', 'muted', 'name', 'noValidate', 'open', 'pattern', 'placeholder', 'poster', 'preload', 'radioGroup', 'readOnly', 'rel', 'required', 'role', 'rows', 'rowSpan', 'sandbox', 'scope', 'scrolling', 'seamless', 'selected', 'shape', 'size', 'sizes', 'span', 'spellCheck', 'src', 'srcDoc', 'srcSet', 'start', 'step', 'style', 'tabIndex', 'target', 'title', 'type', 'useMap', 'value', 'width', 'wmode'];
var attributesMapping = {'class': 'className', 'rt-class': 'className'};
_.forEach(reactSupportedAttributes,function (attributeReactName) {
    if (attributeReactName !== attributeReactName.toLowerCase()) {
        attributesMapping[attributeReactName.toLowerCase()] = attributeReactName;
    }
});

function concatChildren(children) {
    var res = '';
    _.forEach(children, function (child) {
        if (child.indexOf(' /*') !== 0 && child) {
            res += ',' + child;
        } else {
            res += child;
        }
    }, this);
    return res;
}

function convertToCamelCase(str) {
    return str.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
}

function capitalize(str) {
    return str[0].toUpperCase() + str.slice(1);
}

var curlyMap = {'{': 1, '}': -1};

function convertText(txt) {
    txt = txt.trim();
    var res = '';
    var first = true;
    while (txt.indexOf('{') !== -1) {
        var start = txt.indexOf('{');
        var pre = txt.substr(0,start);
        if (pre) {
            res += (first ? '' : '+') + JSON.stringify(pre);
            first = false;
        }
        var curlyCounter = 1;
        for (var end = start + 1; end < txt.length && curlyCounter > 0; end++) {
            curlyCounter += curlyMap[txt.charAt(end)] || 0;
        }
        if (curlyCounter !== 0) {
            throw 'Failed to parse text';
        } else {
            res += (first ? '' : '+') + txt.substr(start + 1, end - start - 2);
            first = false;
            txt = txt.substr(end);
        }
    }
    if (txt) {
        res += (first ? '' : '+') + JSON.stringify(txt);
    }
    if (res === "") {
        res = "true";
    }

    return res;
}

function isStringOnlyCode(txt) {
    txt = txt.trim();
    return txt.length && txt.charAt(0) === '{' && txt.charAt(txt.length - 1) === '}';
}

function generateInjectedFunc(context, namePrefix, body, params) {
    params = params || context.boundParams;
    var generatedFuncName = namePrefix.replace(",","") + (context.injectedFunctions.length + 1);
    var funcText = "function " + generatedFuncName + "(" + params.join(",");
    funcText += ") {\n" + body + "\n}\n";
    context.injectedFunctions.push(funcText);
    return generatedFuncName;
}

function generateProps(node, context) {
    var props = {};
    _.forOwn(node.attribs, function (val, key) {
        var propKey = attributesMapping[key.toLowerCase()] || key;
        if (props.hasOwnProperty(propKey)) {
            throw 'duplicate definition of ' + propKey + ' ' + JSON.stringify(node.attribs);
        }
        if (key.indexOf('on') === 0 && !isStringOnlyCode(val)) {
            var funcParts = val.split('=>');
            var evtParams = funcParts[0].replace('(', '').replace(')', '').trim();
            var funcBody = funcParts[1].trim();
            var generatedFuncName = generateInjectedFunc(context, key, funcBody,context.boundParams.concat([evtParams]));
            props[propKey] = generatedFuncName + ".bind(" + (["this"].concat(context.boundParams)).join(",") + ")";
        } else if (key === "style" && !isStringOnlyCode(val)) {
            var styleParts = val.trim().split(";");
            styleParts = _.compact(_.map(styleParts, function (str) {
                str = str.trim();
                if (!str || str.indexOf(':') === -1) {
                    return null;
                }
                var res = str.split(':');
                res[0] = res[0].trim();
                res[1] = res[1].trim();
                return res;
            }));
            var styleArray = [];
            _.forEach(styleParts, function (stylePart) {
                styleArray.push(convertToCamelCase(stylePart[0]) + ' : ' + convertText(stylePart[1]));
            });
            props[propKey] = '{' + styleArray.join(',') + '}';
        } else if (key === classSetProp) {
            props[propKey] = classSetTemplate({classSet: val});
        } else if (key.indexOf('rt-') !== 0) {
            props[propKey] = convertText(val);
        }
    });

    return '{' + _.map(props, function (val, key) {
        return JSON.stringify(key) + ' : ' + val;
    }).join(',') + '}';
}

function convertTagNameToConstructor(tagName) {
    return React.DOM.hasOwnProperty(tagName) ? 'React.DOM.' + tagName : tagName;
}

function defaultContext() {
    return {
        boundParams: [],
        injectedFunctions: []
    };
}

function addIfNotThere(array, obj) {
    if (!_.contains(array, obj)) {
        array.push(obj);
    }
}

function hasNonSimpleChildren(node) {
  return _.any(node.children,function (child) {
    return child.type === 'tag' && child.attribs[templateProp];
  });
}

function convertHtmlToReact(node, context) {
    if (node.type === 'tag') {
        context = {
            boundParams: _.clone(context.boundParams),
            injectedFunctions: context.injectedFunctions
        };

        var data = {name: convertTagNameToConstructor(node.name)};
        if (node.attribs[scopeProp]) {
            data.scopeMapping = {};
            data.scopeName = "";
            _.each(context.boundParams,function (boundParam) {
              data.scopeMapping[boundParam] = boundParam;
            });
            _.each(node.attribs[scopeProp].split(";"),function (scopePart) {
              var scopeSubParts = scopePart.split(" as ");
              var scopeName = scopeSubParts[1].trim();
              addIfNotThere(context.boundParams, scopeName);
              data.scopeName += capitalize(scopeName);
              data.scopeMapping[scopeName] = scopeSubParts[0].trim();
            });
        }

        if (node.attribs[templateProp]) {
            data.item = node.attribs[templateProp].split(' in ')[0].trim();
            data.collection = node.attribs[templateProp].split(' in ')[1].trim();
            addIfNotThere(context.boundParams, data.item);
            addIfNotThere(context.boundParams, data.item + 'Index');
        }
        data.props = generateProps(node, context);
        if (node.attribs[ifProp]) {
            data.condition = node.attribs[ifProp].trim();
        }
        data.children = concatChildren(_.map(node.children, function (child) {
            return convertHtmlToReact(child, context);
        }));

        if (hasNonSimpleChildren(node)) {
          data.body = tagTemplate(data);
        } else {
          data.body = simpleTagTemplate(data);
        }

        if (node.attribs[templateProp]) {
            data.repeatFunction = generateInjectedFunc(context,"repeat"+capitalize(data.item),"return "+data.body);
            data.repeatBinds = ["this"].concat(_.reject(context.boundParams, function (param) {
                return (param === data.item || param === data.item+"Index");
            }));
            console.log(data.repeatBinds);
            data.body = repeatTemplate(data);
        }
        if (node.attribs[ifProp]) {
            data.body = ifTemplate(data);
        }
        if (node.attribs[scopeProp]) {
            var generatedFuncName = generateInjectedFunc(context,"scope"+data.scopeName,"return "+data.body,_.keys(data.scopeMapping));
            data.body = generatedFuncName + ".apply(this, [" + _.values(data.scopeMapping).join(",") + "])";
        }
        return data.body;
    } else if (node.type === 'comment') {
        return (commentTemplate(node));
    } else if (node.type === 'text') {
        if (node.data.trim()) {
            return convertText(node.data.trim());
        }
        return '';
    }
}

function extractDefinesFromJSXTag(html, defines) {
    html = html.replace(/\<\!doctype jsx\s*(.*?)\s*\>/i, function(full, reqStr) {
        var match = true;
        while (match) {
            match = false;
            reqStr = reqStr.replace(/\s*(\w+)\s*\=\s*\"([^\"]*)\"\s*/, function(full, varName, reqPath) {
                defines[reqPath] = varName;
                match = true;
                return '';
            });
        }
        return '';
    });
    return html;
}

/**
 * @param {string} html
 * @return {string}
 */
function convertTemplateToReact(html) {
//    var x = cheerio.load(html);
    var defines = {react: 'React', lodash: '_'};
    html = extractDefinesFromJSXTag(html, defines);
    var rootNode = cheerio.load(html.trim(), {lowerCaseTags: false, lowerCaseAttributeNames: false, xmlMode: true});
    var context = defaultContext();
    var body = convertHtmlToReact(rootNode.root()[0].children[0], context);
    var requirePaths = _(defines).keys().map(function (reqName) { return '"' + reqName + '"'; }).value().join(',');
    var requireVars = _(defines).values().value().join(',');
    var data = {body: body, injectedFunctions: '', requireNames: requireVars, requirePaths: requirePaths};
    data.injectedFunctions = context.injectedFunctions.join('\n');
    var code = templateTemplate(data);
    try {
        var tree = esprima.parse(code, {range: true, tokens: true, comment: true});
        tree = escodegen.attachComments(tree, tree.comments, tree.tokens);
        code = escodegen.generate(tree, {comment: true});
    } catch (e) {
        // TODO error handling
        console.log(e);
    }
    return code;
}

/**
 * @param {string} source
 * @param {string} target
 */
function convertFile(source, target) {
//    if (path.extname(filename) !== ".html") {
//        console.log('invalid file, only handle html files');
//        return;// only handle html files
//    }
    var util = require('./util');

    if (!util.isStale(source, target)) {
        console.log('target file ' + target + ' is up to date, skipping');
//        return;
    }

    var html = fs.readFileSync(source).toString();
    if (!html.match(/\<\!doctype jsx/i)) {
        throw new Error('invalid file, missing header');
    }
    var js = convertTemplateToReact(html);
    fs.writeFileSync(target, js);
}

module.exports = {
    convertTemplateToReact: convertTemplateToReact,
    convertFile: convertFile,
    _test: {}
};
<|endoftext|>


<commit_before>/**
 * @copyright 2016-present, Prometheus Research, LLC
 */

import memoize from 'memoize-decorator';
import {atom, derivation} from 'derivable';
import selectValue  from 'lodash/get';

import * as Schema from '../Schema';
import toKeyPath from '../keyPath';
import applyDecorator from '../applyDecorator';
import {update as updateValue} from '../update';

export function create({
  schema,
  value = {},
  params = {},
  externalErrorList = [],
} = {}) {
  value = atom(value);
  params = atom(params);
  externalErrorList = atom(externalErrorList);
  let validationErrorList = value.derive(value => Schema.validate(schema, value));
  return new Value(
    null,
    [],
    schema,
    value,
    validationErrorList,
    externalErrorList,
    params
  );
}

export function select(parent, ...key) {
  let keyPath = parent.keyPath.concat(key);
  let schema = Schema.select(parent.schema, key);
  let value;
  if (schema && schema.select) {
    value = parent.root._value.derive(value =>
      schema.select(value, keyPath, schema));
  } else {
    value = parent._value.derive(value =>
      selectValue(value, key));
  }
  let validationErrorList = parent._validationErrorList.derive(errorList =>
    filterErrorListByKeyPathPrefix(errorList, keyPath));
  let externalErrorList = parent._externalErrorList.derive(errorList =>
    filterErrorListByKeyPathPrefix(errorList, keyPath));
  return new Value(
    parent,
    keyPath,
    schema,
    value,
    validationErrorList,
    externalErrorList,
    parent._params,
  );
}

export function update(cursor, value) {
  let nextValue;
  if (cursor.keyPath.length === 0) {
    nextValue = value;
  } else {
    nextValue = updateValue(
      cursor.root._value.get(),
      cursor.keyPath,
      value,
      cursor.root.schema,
    );
  }
  cursor.root._value.set(nextValue);
  return cursor;
}

class Value {

  constructor(
    parent,
    keyPath,
    schema,
    value,
    validationErrorList,
    externalErrorList,
    params
  ) {
    this.parent = parent;
    this.keyPath = keyPath;
    this.schema = schema;
    this._value = value;
    this._validationErrorList = validationErrorList;
    this._externalErrorList = externalErrorList;
    this._params = params;

    this._completeErrorList = derivation(() =>
      this._validationErrorList.get().concat(this._externalErrorList.get()));
    this._errorList = this._completeErrorList.derive(errorList =>
      filterErrorListByKeyPath(errorList, this.keyPath));
  }

  get root() {
    let root = this;
    while (root.parent) {
      root = root.parent;
    }
    return root;
  }

  get errorList() {
    return this._errorList.get();
  }

  get completeErrorList() {
    return this._completeErrorList.get();
  }

  get value() {
    return this._value.get();
  }

  get params() {
    return this._params.get();
  }

  select(keyPath) {
    keyPath = toKeyPath(keyPath);
    return select(this, ...keyPath);
  }

  update(value) {
    return update(this, value);
  }

}

applyDecorator(Value.prototype, 'root', memoize);

function filterErrorListByKeyPath(errorList, keyPath) {
  let field = ['data'].concat(keyPath).join('.');
  return errorList.filter(error => error.field === field);
}

function filterErrorListByKeyPathPrefix(errorList, keyPath) {
  if (keyPath.length === 0) {
    return errorList;
  }
  let field = ['data'].concat(keyPath).join('.');
  let length = field.length;
  return errorList.filter(error =>
    error.field === field ||
    error.field.slice(0, length) === field && error.field[length] === '.'
  );
}
<commit_msg>feat(reactive): smart compare for errorList/completeErrorList<commit_after>/**
 * @copyright 2016-present, Prometheus Research, LLC
 */

import memoize from 'memoize-decorator';
import {atom, derivation} from 'derivable';
import selectValue  from 'lodash/get';

import * as Schema from '../Schema';
import toKeyPath from '../keyPath';
import applyDecorator from '../applyDecorator';
import {update as updateValue} from '../update';
import {eqArray} from '../equality';

export function create({
  schema,
  value = {},
  params = {},
  externalErrorList = [],
} = {}) {
  value = atom(value);
  params = atom(params);
  externalErrorList = atom(externalErrorList);
  let validationErrorList = value.derive(value => Schema.validate(schema, value));
  return new Value(
    null,
    [],
    schema,
    value,
    validationErrorList,
    externalErrorList,
    params
  );
}

export function select(parent, ...key) {
  let keyPath = parent.keyPath.concat(key);
  let schema = Schema.select(parent.schema, key);
  let value;
  if (schema && schema.select) {
    value = parent.root._value.derive(value =>
      schema.select(value, keyPath, schema));
  } else {
    value = parent._value.derive(value =>
      selectValue(value, key));
  }
  let validationErrorList = parent._validationErrorList.derive(errorList =>
    filterErrorListByKeyPathPrefix(errorList, keyPath));
  let externalErrorList = parent._externalErrorList.derive(errorList =>
    filterErrorListByKeyPathPrefix(errorList, keyPath));
  return new Value(
    parent,
    keyPath,
    schema,
    value,
    validationErrorList,
    externalErrorList,
    parent._params,
  );
}

export function update(cursor, value) {
  let nextValue;
  if (cursor.keyPath.length === 0) {
    nextValue = value;
  } else {
    nextValue = updateValue(
      cursor.root._value.get(),
      cursor.keyPath,
      value,
      cursor.root.schema,
    );
  }
  cursor.root._value.set(nextValue);
  return cursor;
}

class Value {

  constructor(
    parent,
    keyPath,
    schema,
    value,
    validationErrorList,
    externalErrorList,
    params
  ) {
    this.parent = parent;
    this.keyPath = keyPath;
    this.schema = schema;
    this._value = value;
    this._validationErrorList = validationErrorList;
    this._externalErrorList = externalErrorList;
    this._params = params;

    this._completeErrorList = derivation(() => {
      let validationErrorList = this._validationErrorList.get();
      let externalErrorList = this._externalErrorList.get();
      return validationErrorList.concat(externalErrorList);
    }).withEquality(eqArray);
    this._errorList = derivation(() => {
      let completeErrorList = this._completeErrorList.get();
      return filterErrorListByKeyPath(completeErrorList, this.keyPath);
    }).withEquality(eqArray);
  }

  get root() {
    let root = this;
    while (root.parent) {
      root = root.parent;
    }
    return root;
  }

  get errorList() {
    return this._errorList.get();
  }

  get completeErrorList() {
    return this._completeErrorList.get();
  }

  get value() {
    return this._value.get();
  }

  get params() {
    return this._params.get();
  }

  select(keyPath) {
    keyPath = toKeyPath(keyPath);
    return select(this, ...keyPath);
  }

  update(value) {
    return update(this, value);
  }

}

applyDecorator(Value.prototype, 'root', memoize);

function filterErrorListByKeyPath(errorList, keyPath) {
  let field = ['data'].concat(keyPath).join('.');
  return errorList.filter(error => error.field === field);
}

function filterErrorListByKeyPathPrefix(errorList, keyPath) {
  if (keyPath.length === 0) {
    return errorList;
  }
  let field = ['data'].concat(keyPath).join('.');
  let length = field.length;
  return errorList.filter(error =>
    error.field === field ||
    error.field.slice(0, length) === field && error.field[length] === '.'
  );
}
<|endoftext|>


<commit_before>import validator from 'validator';
import Enums from './Enums';

const isString = function (stringValue) {
    return typeof stringValue === 'string';
}
const validateEnum = function (obj) {
    let isValid = false;
    Object.keys(Enums).forEach(function (key) {
        if((Enums[key])[obj]){
            isValid = true;
            return;
        }

    });

    return isValid;
}

module.exports = function (args, parameters) {

    let errorMessage = '';
    let isValid = true;
    if (typeof args === 'undefined') {
        args = {};
    }
    Object.keys(args).forEach(function (key) {
        const val = args[key];
        const parameterOptions = parameters[key];

        if (parameterOptions) {
            if (parameterOptions.isMandatory && !val) {
                isValid = false;
                errorMessage = 'Mandatory argument is missing:' + key;
                return;

            }

            if (parameterOptions.type && parameterOptions.type === 'ENUM') {

                if (!validateEnum(val)) {
                    isValid = false;
                    errorMessage = 'Enum doesnt exist:' + key + '/' + val;
                    return;
                }

            }

            if (parameterOptions.type && parameterOptions.type === 'STRING') {

                if (!isString(val)) {
                    isValid = false;
                    errorMessage = 'Value is not string:' + key + '/' + val;
                    return;
                }

            }

            if (parameterOptions.type && parameterOptions.type === 'DECIMAL') {

                if (!validator.isDecimal(val)) {
                    isValid = false;
                    errorMessage = 'Value is not decimal:' + key + '/' + val;
                    return;
                }

            }

            if (parameterOptions.type && parameterOptions.type === 'INT' || parameterOptions.type === 'LONG') {

                if (!validator.isInt(val+'')) {
                    isValid = false;
                    errorMessage = 'Value is not int:' + key + '/' + val;
                    return;
                }

            }
        }

    });

    if(!isValid) {
        console.error(errorMessage);
    }
    return isValid;
};<commit_msg>fixing error type<commit_after>import validator from 'validator';
import Enums from './Enums';

const isString = function (stringValue) {
    return typeof stringValue === 'string';
}
const validateEnum = function (obj) {
    let isValid = false;
    Object.keys(Enums).forEach(function (key) {
        if((Enums[key])[obj]){
            isValid = true;
            return;
        }

    });

    return isValid;
}

module.exports = function (args, parameters) {

    let errorMessage = '';
    let isValid = true;
    if (typeof args === 'undefined') {
        args = {};
    }
    Object.keys(args).forEach(function (key) {
        const val = args[key];
        const parameterOptions = parameters[key];

        if (parameterOptions) {
            if (parameterOptions.isMandatory && !val) {
                isValid = false;
                errorMessage = 'Mandatory argument is missing:' + key;
                return;

            }

            if (parameterOptions.type && parameterOptions.type === 'ENUM') {

                if (!validateEnum(val)) {
                    isValid = false;
                    errorMessage = 'Enum doesnt exist:' + key + '/' + val;
                    return;
                }

            }

            if (parameterOptions.type && parameterOptions.type === 'STRING') {

                if (!isString(val)) {
                    isValid = false;
                    errorMessage = 'Value is not string:' + key + '/' + val;
                    return;
                }

            }

            if (parameterOptions.type && parameterOptions.type === 'DECIMAL') {

                if (!validator.isDecimal(val)) {
                    isValid = false;
                    errorMessage = 'Value is not decimal:' + key + '/' + val;
                    return;
                }

            }

            if (parameterOptions.type && parameterOptions.type === 'INT' || parameterOptions.type === 'LONG') {

                if (!validator.isInt(val+'')) {
                    isValid = false;
                    errorMessage = 'Value is not int:' + key + '/' + val;
                    return;
                }

            }
        }

    });

    if(!isValid) {
        throw new TypeError(errorMessage);
    }
    return isValid;
};<|endoftext|>


<commit_before>import { createSlice } from '@reduxjs/toolkit'

import boardInitialState from '../game_logic/board-init.js'
import { performMove } from '../game_logic/perform-move.js'
import { fromFen } from '../fen.js'
import { newGame } from './actions'

const board = createSlice({
  name: 'board',
  initialState: boardInitialState,
  reducers: {
    movePiece: (state, action) => {
      return performMove(state, action.payload)
    }
  },
  extraReducers: {
    [newGame]: (state, action) => {
      return fromFen(action.payload.fen) || boardInitialState
    }
  }
})

export const { movePiece } = board.actions

export default board.reducer
<commit_msg>Remove unused parameter<commit_after>import { createSlice } from '@reduxjs/toolkit'

import boardInitialState from '../game_logic/board-init.js'
import { performMove } from '../game_logic/perform-move.js'
import { fromFen } from '../fen.js'
import { newGame } from './actions'

const board = createSlice({
  name: 'board',
  initialState: boardInitialState,
  reducers: {
    movePiece: (state, action) => {
      return performMove(state, action.payload)
    }
  },
  extraReducers: {
    [newGame]: (_, action) => {
      return fromFen(action.payload.fen) || boardInitialState
    }
  }
})

export const { movePiece } = board.actions

export default board.reducer
<|endoftext|>


<commit_before>.pragma library

function func() {

}

<commit_msg>rip out accidentially commited file<commit_after><|endoftext|>