<commit_before>QUnit.module("capsule");

QUnit.test("capsule", function(assert) {
	assert.equal(typeof capsule, "object", "capsule object is defined.");
});

QUnit.module("capsule.math");

QUnit.test("Checking if it's defined", function(assert) {
	assert.equal(typeof capsule.math, "object", "capsule.math object is defined.");
});

QUnit.test("modulus", function(assert) {
	var modulus = capsule.math.modulus;

	assert.equal(modulus(10, 20),  10);
	assert.equal(modulus(10,  5),   0);
	assert.equal(modulus(5 ,  2),   1);
	assert.equal(modulus(-5,  2),   1);
	assert.equal(modulus(0 , 10),   0);

	assert.equal(isNaN(modulus(5, 0)), true);
});

QUnit.test("randomAngle", function(assert) {
	var i;
	var value;
	var randomAngle = capsule.math.randomAngle;

	for (i = 0; i < 100; i += 1) {
		value = randomAngle();
		assert.ok(value > 0 && value < 360, value + " is in the expected range.");
	}
});

QUnit.test("randomNumber", function(assert) {
	var i;
	var value;
	var randomNumber = capsule.math.randomNumber;
	var isBetween    = capsule.math.isBetween;

	for (i = 0; i < 100; i += 1) {
		value = randomNumber(0, i);
		assert.ok(isBetween(value, 0, i),
			value + " is in the expected range. Min: 0, Max: " + i);
		value = randomNumber(50 - i, i);
		assert.ok(isBetween(value, 50 - i, i),
			value + "is in the expected range. Min: " + (50 - i) + ", Max: " + i);
		value = randomNumber(-i, 0);
		assert.ok(isBetween(value, -i, 0),
			value + " is in the expected range. Min: " + -i + ", Max: 0");
	}
});

QUnit.test("randomInteger", function(assert) {
	var i;
	var value;
	var randomInteger = capsule.math.randomInteger;
	var isBetween     = capsule.math.isBetween;

	for (i = 0; i < 100; i += 1) {
		value = randomInteger(0, i);
		assert.equal(value, Math.floor(value), value + " is an integer.");
		assert.ok(isBetween(value, 0, i), value + " is in the expected range. Min: 0, Max: " + i);
		value = randomInteger(-i, 0);
		assert.ok(isBetween(value, -i, 0), value + " is in the expected range. Min: " + (-i) + " Max: 0");
	}
});

QUnit.test("constrain", function(assert) {
	var constrain = capsule.math.constrain;
	assert.equal(constrain( 50, 0, 100),  50);
	assert.equal(constrain(-50, 0, 100),   0);
	assert.equal(constrain(200, 0, 100), 100);
});

QUnit.test("isBetween", function(assert) {
	var isBetween = capsule.math.isBetween;
	assert.equal(isBetween( 50, 0, 100),  true);
	assert.equal(isBetween(-50, 0, 100), false);
	assert.equal(isBetween(200, 0, 100), false);
	assert.equal(isBetween(  0, 0, 100),  true);
	assert.equal(isBetween(100, 0, 100),  true);
});

QUnit.test("normalize", function(assert) {
	var normalize = capsule.math.normalize;
	assert.equal(normalize( 50, 0, 100),  0.50);
	assert.equal(normalize( 25, 0, 100),  0.25);
	assert.equal(normalize( 10, 0, 100),  0.10);
	assert.equal(normalize(-10, 0, 100), -0.10);
	assert.equal(normalize(-50, 0, 100), -0.50);
	assert.equal(normalize(200, 0, 100),  2.00);
});

QUnit.test("linearInterpolation", function(assert) {
	var lerp = capsule.math.linearInterpolation;
	assert.equal(lerp( 0.50,   0, 100),  50);
	assert.equal(lerp( 0.25,   0, 100),  25);
	assert.equal(lerp( 0.10,   0, 100),  10);
	assert.equal(lerp(-0.50,   0, 100), -50);
	assert.equal(lerp( 0.50, 100,   0),  50);
	assert.equal(lerp(-0.50, 100,   0), 150);
	assert.equal(lerp( 2.00,   0, 100), 200);
});

QUnit.test("map", function(assert) {
	var map = capsule.math.map;
	assert.equal(map(50,    0, 100,   0, 10), 5.0);
	assert.equal(map(50,    0, 100, -10, 10), 0.0);
	assert.equal(map(50, -100, 100,   0, 10), 7.5);
});

QUnit.test("toDegrees", function(assert) {
	var toDegrees = capsule.math.toDegrees;
	var TAU = capsule.math.TAU;
	assert.equal(toDegrees(Math.PI / 2), 90);
	assert.equal(toDegrees(0), 0);
	assert.equal(toDegrees(TAU), 360);
});

QUnit.test("toRadians", function(assert) {
	var toRadians = capsule.math.toRadians;
	var TAU = capsule.math.TAU;
	assert.equal(toRadians(90), Math.PI / 2);
	assert.equal(toRadians(0), 0);
	assert.equal(toRadians(360), TAU);
});

QUnit.test("Checking constant properties", function(assert) {
	[
		"TAU",
		"HALF_PI"
	].forEach(function(name) {
		var descriptor = Object.getOwnPropertyDescriptor(capsule.math, name);
		assert.equal(descriptor.writable, false, name + " property is read-only.");
	});
});

QUnit.test("Checking trigonometric functions are defined.", function(assert) {
	[
		"sin",
		"cos",
		"tan",
		"arcSin",
		"arcCos",
		"arcTan"
	].forEach(function(key) {
		assert.equal(typeof capsule.math[key], "function", key + " function is defined.");
	});
});

QUnit.test("min", function(assert) {
	var min = capsule.math.min;
	assert.equal(min(10, 20, 30), 10, "10 is min.");
	assert.equal(min(-50, 0, 50), -50, "-50 is min.");
	assert.equal(min(30, 10, 20), 10, "10 is min.");
});

QUnit.test("max", function(assert) {
	var max = capsule.math.max;
	assert.equal(max(10, 20, 30), 30, "30 is max.");
	assert.equal(max(-50, 0, 50), 50, "50 is max.");
	assert.equal(max(30, 10, 20), 30, "30 is max.");
});
<commit_msg>Improving trigonometric function tests.<commit_after>QUnit.module("capsule");

QUnit.test("capsule", function(assert) {
	assert.equal(typeof capsule, "object", "capsule object is defined.");
});

QUnit.module("capsule.math");

QUnit.test("Checking if it's defined", function(assert) {
	assert.equal(typeof capsule.math, "object", "capsule.math object is defined.");
});

QUnit.test("modulus", function(assert) {
	var modulus = capsule.math.modulus;

	assert.equal(modulus(10, 20),  10);
	assert.equal(modulus(10,  5),   0);
	assert.equal(modulus(5 ,  2),   1);
	assert.equal(modulus(-5,  2),   1);
	assert.equal(modulus(0 , 10),   0);

	assert.equal(isNaN(modulus(5, 0)), true);
});

QUnit.test("randomAngle", function(assert) {
	var i;
	var value;
	var randomAngle = capsule.math.randomAngle;

	for (i = 0; i < 100; i += 1) {
		value = randomAngle();
		assert.ok(value > 0 && value < 360, value + " is in the expected range.");
	}
});

QUnit.test("randomNumber", function(assert) {
	var i;
	var value;
	var randomNumber = capsule.math.randomNumber;
	var isBetween    = capsule.math.isBetween;

	for (i = 0; i < 100; i += 1) {
		value = randomNumber(0, i);
		assert.ok(isBetween(value, 0, i),
			value + " is in the expected range. Min: 0, Max: " + i);
		value = randomNumber(50 - i, i);
		assert.ok(isBetween(value, 50 - i, i),
			value + "is in the expected range. Min: " + (50 - i) + ", Max: " + i);
		value = randomNumber(-i, 0);
		assert.ok(isBetween(value, -i, 0),
			value + " is in the expected range. Min: " + -i + ", Max: 0");
	}
});

QUnit.test("randomInteger", function(assert) {
	var i;
	var value;
	var randomInteger = capsule.math.randomInteger;
	var isBetween     = capsule.math.isBetween;

	for (i = 0; i < 100; i += 1) {
		value = randomInteger(0, i);
		assert.equal(value, Math.floor(value), value + " is an integer.");
		assert.ok(isBetween(value, 0, i), value + " is in the expected range. Min: 0, Max: " + i);
		value = randomInteger(-i, 0);
		assert.ok(isBetween(value, -i, 0), value + " is in the expected range. Min: " + (-i) + " Max: 0");
	}
});

QUnit.test("constrain", function(assert) {
	var constrain = capsule.math.constrain;
	assert.equal(constrain( 50, 0, 100),  50);
	assert.equal(constrain(-50, 0, 100),   0);
	assert.equal(constrain(200, 0, 100), 100);
});

QUnit.test("isBetween", function(assert) {
	var isBetween = capsule.math.isBetween;
	assert.equal(isBetween( 50, 0, 100),  true);
	assert.equal(isBetween(-50, 0, 100), false);
	assert.equal(isBetween(200, 0, 100), false);
	assert.equal(isBetween(  0, 0, 100),  true);
	assert.equal(isBetween(100, 0, 100),  true);
});

QUnit.test("normalize", function(assert) {
	var normalize = capsule.math.normalize;
	assert.equal(normalize( 50, 0, 100),  0.50);
	assert.equal(normalize( 25, 0, 100),  0.25);
	assert.equal(normalize( 10, 0, 100),  0.10);
	assert.equal(normalize(-10, 0, 100), -0.10);
	assert.equal(normalize(-50, 0, 100), -0.50);
	assert.equal(normalize(200, 0, 100),  2.00);
});

QUnit.test("linearInterpolation", function(assert) {
	var lerp = capsule.math.linearInterpolation;
	assert.equal(lerp( 0.50,   0, 100),  50);
	assert.equal(lerp( 0.25,   0, 100),  25);
	assert.equal(lerp( 0.10,   0, 100),  10);
	assert.equal(lerp(-0.50,   0, 100), -50);
	assert.equal(lerp( 0.50, 100,   0),  50);
	assert.equal(lerp(-0.50, 100,   0), 150);
	assert.equal(lerp( 2.00,   0, 100), 200);
});

QUnit.test("map", function(assert) {
	var map = capsule.math.map;
	assert.equal(map(50,    0, 100,   0, 10), 5.0);
	assert.equal(map(50,    0, 100, -10, 10), 0.0);
	assert.equal(map(50, -100, 100,   0, 10), 7.5);
});

QUnit.test("toDegrees", function(assert) {
	var toDegrees = capsule.math.toDegrees;
	var TAU = capsule.math.TAU;
	assert.equal(toDegrees(Math.PI / 2), 90);
	assert.equal(toDegrees(0), 0);
	assert.equal(toDegrees(TAU), 360);
});

QUnit.test("toRadians", function(assert) {
	var toRadians = capsule.math.toRadians;
	var TAU = capsule.math.TAU;
	assert.equal(toRadians(90), Math.PI / 2);
	assert.equal(toRadians(0), 0);
	assert.equal(toRadians(360), TAU);
});

QUnit.test("Checking constant properties", function(assert) {
	[
		"TAU",
		"HALF_PI"
	].forEach(function(name) {
		var descriptor = Object.getOwnPropertyDescriptor(capsule.math, name);
		assert.equal(descriptor.writable, false, name + " property is read-only.");
	});
});

// All trigonometric functions are tested together using a helper function.
(function() {
	var MAX_ERROR = 1e-4;

	var compare = function(a, b) {
		return Math.abs(a - b) < MAX_ERROR;
	};

	var createTest = function(functionName, assert) {
		var func = capsule.math[functionName];
		assert.ok(typeof func === "function", functionName + " is defined.");
		return function(input, expected) {
			var result = func(input);
			assert.ok(compare(func(input), expected),
				"{func}({input}) = {result} (Expected: {expected}; Diff: {diff})."
				.replace("{func}", functionName)
				.replace("{input}", input)
				.replace("{result}", result)
				.replace("{expected}", expected)
				.replace("{diff}", Math.abs(result - expected))
			);
		};
	};

	QUnit.test("sin", function(assert) {
		var test = createTest("sin", assert);
		test(0, 0);
		test(30, 0.5);
		test(45, 0.707106);
		test(60, 0.866025);
		test(90, 1);
		test(180, 0);
		test(270, -1);
		test(360, 0);
	});

	QUnit.test("cos", function(assert) {
		var test = createTest("cos", assert);
		test(0, 1);
		test(30, 0.866025);
		test(45, 0.707106);
		test(60, 0.5);
		test(90, 0);
		test(180, -1);
		test(270, 0);
		test(360, 1);
	});

	QUnit.test("tan", function(assert) {
		var test = createTest("tan", assert);
		test(0, 0);
		test(30, 0.577350);
		test(45, 1);
		test(60, 1.732050);
		test(180, 0);
	});

	QUnit.test("arcSin", function(assert) {
		var test = createTest("arcSin", assert);
		test(0, 0);
		test(0.5, 30);
		test(0.707106, 45);
		test(0.866025, 60);
		test(1, 90);
		test(-1, -90);
	});

	QUnit.test("arcCos", function(assert) {
		var test = createTest("arcCos", assert);
		test(1, 0);
		test(0.866025, 30);
		test(0.707106, 45);
		test(0.5, 60);
		test(0, 90);
		test(-1, 180);
	});

	QUnit.test("arcTan", function(assert) {
		var test = createTest("arcTan", assert);
		test(0, 0);
		test(0.577350, 30);
		test(1, 45);
		test(1.732050, 60);
	});
}());

QUnit.test("min", function(assert) {
	var min = capsule.math.min;
	assert.equal(min(10, 20, 30), 10, "10 is min.");
	assert.equal(min(-50, 0, 50), -50, "-50 is min.");
	assert.equal(min(30, 10, 20), 10, "10 is min.");
});

QUnit.test("max", function(assert) {
	var max = capsule.math.max;
	assert.equal(max(10, 20, 30), 30, "30 is max.");
	assert.equal(max(-50, 0, 50), 50, "50 is max.");
	assert.equal(max(30, 10, 20), 30, "30 is max.");
});
<|endoftext|>


<commit_before>/**
* Module that contains the data structure implementations.
* Depends on core.js
*/
(function($) {
  if (typeof JSAV === "undefined") { return; }

  // create a utility function as a jQuery "plugin"
  $.fn.getstyles = function() {
    // Returns the values of CSS properties that are given as
    // arguments. For example, $elem.getstyles("background-color", "color")
    // could return an object {"background-color" : "rgb(255, 120, 120)",
    //                         "color" : "rgb(0, 0, 0)"}
    var res = {},
      arg;
    for (var i = 0; i < arguments.length; i++) {
      arg = arguments[i];
      if ($.isArray(arg)) {
        for (var j = 0; j < arg.length; j++) {
          res[arg[j]] = this.css(arg[j]);
        }
      } else {
        res[arg] = this.css(arg);
      }
    }
    return res;
  };

  // helper functions we want to keep private
  var priv = {
    _hide: function() {
      $(this.element).fadeOut(this.jsav.SPEED);
    },
    // utility function that actually implements show
    _show: function() {
      $(this.element).fadeIn(this.jsav.SPEED);
    }
  };

  // common properties/functions for all data structures, these can be copied
  // to the prototype of a new DS using the addCommonProperties(prototype) function
  var common = {
      // gets or sets the id of the DS
      'id': function(newId) {
        if (newId) {
          this._id = newId;
          return this;
        } else {
          return this._id;
        }
      },
      // returns the position of the DS
      'position': function() {
        return JSAV.position(this.element);
      },
      // utility function that actually implements hide
      // animated show function
      show: JSAV.anim(function() { priv._show.apply(this); },
        function() { priv._hide.apply(this); }),
      // animated hide function
      hide: JSAV.anim(function() { priv._hide.apply(this); },
        function() { priv._show.apply(this); }),
      // dummy methods for initializing a DS, the DS should override these
      initialize: function() { },
      initializeFromElement: function() { },
      clone: function() {}
    },
    // initializes a data structure
    initDs = function(dstr, element, options) {
      dstr.options = $.extend(true, {}, options);
      if ($.isArray(element)) {
        dstr.initialize(element);
      } else if (element) { // assume it's a DOM element
        dstr.element = element;
        dstr.initializeFromElement();
      } else {
        // TODO: create an element for this data structure
      }
    };

  // function that selects elements from $elems that match the indices
  // filter (number, array of numbers, or filter function)
  var getIndices = function($elems, indices) {
    if (typeof indices === "undefined") { return $elems; } // use all if no restrictions are given
    if ($.isFunction(indices)) { // use a filter function..
      return $elems.filter(indices); // ..and let jQuery do the work
    } else if ($.isArray(indices)) {
      // return indices that are in the array
      return $elems.filter(function(index, item) {
        for (var i=0; i < indices.length; i++) {
          if (indices[i] == index) { return true; }
        }
        return false;
      });
    } else if (typeof indices === "number"){
      return $elems.eq(indices); // return the specific index
    } else {
      try { // last resort, try if the argument can be parsed into an int..
        return $elems.eq(parseInt(indices, 10));
      } catch (err) {
        return $({}); // ..if not, return an empty set
      }
    }
  };

  /* Array data structure for JSAV library. */
  var AVArray = function(jsav, element, options) {
    this.jsav = jsav;
    initDs(this, element, options);
  };
  var arrproto = AVArray.prototype;
  addCommonProperties(arrproto); // add functionality from common
  function setHighlight(indices, mode) {
    var testDiv = $('
' +
        '

'),
  	  styleDiv = (mode && mode === "add" ? testDiv.find(".jsavnode").filter(".jsavhighlight"):testDiv.find(".jsavnode").not(".jsavhighlight"));
  	// TODO: general way to get styles for the whole av system
  	$("body").append(testDiv);
    this.css(indices, {color: styleDiv.css("color"), "background-color": styleDiv.css("background-color")});
    testDiv.remove();
  }
  arrproto.highlight = function(indices, options) {
    setHighlight.call(this, indices, "add");
    return this;
  };

  arrproto.unhighlight = function(indices, options) {
    setHighlight.call(this, indices, "remove");
    return this;
  };
  arrproto._setcss = JSAV.anim(function(indices, cssprop) {
    var $elems = getIndices($(this.element).find("li"), indices);
    if (!this.jsav.RECORD || !$.fx.off) { // only animate when playing, not when recording
      // also animate the values due to a bug in webkit based browsers with inherited bg color not changing
      $elems.animate(cssprop, this.jsav.SPEED).find("span.jsavvalue").animate(cssprop, this.jsav.SPEED);
    } else {
      $elems.css(cssprop).find("span.jsavvalue").css(cssprop);
    }
    return this;
  });
  arrproto.css = function(indices, cssprop) {
    var $elems = getIndices($(this.element).find("li"), indices);
    if (typeof cssprop === "string") {
      return $elems.css(cssprop);
    } else {
      if ($.isFunction(indices)) { // if indices is a function, evaluate it right away and get a list of indices
        var all_elems = $(this.element).find("li"),
          sel_indices = []; // array of selected indices
        for (var i = 0; i < $elems.size(); i++) {
          sel_indices.push(all_elems.index($elems[i]));
        }
        indices = sel_indices;
      }
      return this._setcss(indices, cssprop);
    }
  };
  function realSwap(index1, index2, options) {
    var $pi1 = $(this.element).find("li:eq(" + index1 + ")"), // index
      $pi2 = $(this.element).find("li:eq(" + index2 + ")"),
      $i1 = $pi1.find("span.jsavvalue"),
      $i2 = $pi2.find("span.jsavvalue"),
      posdiff = JSAV.position($i1).left - JSAV.position($i2).left,
      indices = $($pi1).add($pi2),
      i1prevStyle = $pi1.getstyles("color", "background-color"),
      i2prevStyle = $pi2.getstyles("color", "background-color"),
      speed = this.jsav.SPEED/5,
      tmp = $pi1.html(),
      $ind1label, $ind2label;
    // first swap the contents of the elements..
    $pi1.html($pi2.html());
    $pi2.html(tmp);
    // swap the actual values in the array
    tmp = $pi1.attr("data-value");
    $pi1.attr("data-value", $pi2.attr("data-value"));
    $pi2.attr("data-value", tmp);
    // .. get the value elements again since the content swap lost the nodes ..
    $i1 = $pi1.find("span.jsavvalue");
    $i2 = $pi2.find("span.jsavvalue");
    // .. change back the index labels ..
    if (this.options.indexed) {
      $ind1label = $pi1.find("span.jsavindexlabel");
      $ind2label = $pi2.find("span.jsavindexlabel");
      tmp = $ind1label.html();
      $ind1label.html($ind2label.html());
      $ind2label.html(tmp);
    }
    if (!this.jsav.RECORD || !$.fx.off) {  // only animate when playing, not when recording
      // .. then set the position so that the array appears unchanged..
      $i2.css({"transform": "translateX(" + (posdiff) + "px)"});
      $i1.css({"transform": "translateX(" + (-posdiff) + "px)"});
      // .. animate the color ..
      indices.animate({"color": "red", "background-color": "pink"}, 3*speed, function() {
        // ..animate the translation to 0, so they'll be in their final positions..
        $i2.animate({"transform": "translateX(0px)"}, 7*speed, 'linear');
        $i1.animate({"transform": "translateX(0px)"}, 7*speed, 'linear',
          function() {
            // ..and finally animate to the original styles.
            $pi1.animate(i1prevStyle, speed);
            $pi2.animate(i2prevStyle, speed);
        });
      });
    }
  }
  arrproto.swap = JSAV.anim(function(index1, index2, options) {
    realSwap.apply(this, arguments);
    return this;
  }, realSwap
  );
  arrproto.clone = function() {
    // fetch all values
    var size = this.size(),
      vals = [];
    for (var i=0; i < size; i++) {
      vals[i] = this.value(i);
    }
    return new AVArray(this.jsav, vals, $.extend(true, {}, this.options, {display: false}));
  };
  arrproto.size = function() { return this.element.find("li").size(); };
  arrproto.value = function(index, newValue) {
    if (!newValue) {
      return this.element.find("li:eq(" + index + ")").attr("data-value");
    } else {
      return this.setvalue(index, newValue);
    }
  };
  arrproto.setvalue = JSAV.anim(function(index, newValue) {
    var $index = this.element.find("li:eq(" + index + ")");
    var oldVal = $index.attr("data-value") || undefined;
    $index.attr("data-value", newValue);
    $index.find(".jsavvalue").html("" + newValue);
    return oldVal;
  });
  arrproto.initialize = function(data) {
    var el = $("
"),
      liel;
    this.options = jQuery.extend({display: true}, this.options);
    $.each(data, function(index, item) {
      liel = $("
" + item + "
");
      // set the data attribute for the index
      liel.attr("data-value", item);
      el.append(liel);
    });
    $(this.jsav.container).append(el);
    this.element = el;
    this.layout();
    el.css("display", "none");
    var visible = (typeof this.options.display === "boolean" && this.options.display === true);
    if (visible) {
      if (this.jsav.currentStep() === 0) { // at beginning, just make it visible
        el.css("display", "block");
      } else { // add effect to show otherwise
        this.show();
      }
    }
  };
  arrproto.initializeFromElement = function() {
    // TODO: handle settings from data-attributes
    if (!this.element) { return; }
    var $elem = this.element,
      $elems = $elem.find("li");
    $elem.addClass("jsavarray");
    $elems.each(function(index, item) {
      var $this = $(this);
      if (!$this.attr("data-value")) {
        $this.attr("data-value", parseInt($this.html(), 10));
      }
      $this.addClass("jsavnode jsavindex").html("" + $this.html() + "");
    });
    this.layout();
  };
  arrproto.layout = function() {
    var layoutAlg = this.options.layout || "_default";
    this.element.removeClass("jsavbararray");
    this.jsav.layout.array[layoutAlg](this);
  };
  arrproto.state = function(newstate) {
    if (newstate) {
      $(this.element).html(newstate.html);
    } else {
      var sta = {
        html: $(this.element).html()
      };
      return sta;
    }
  };

  function addCommonProperties(dsPrototype, commonProps) {
    if (!commonProps) { commonProps = common; }
    for (var prop in commonProps) {
      if (commonProps.hasOwnProperty(prop)) {
        dsPrototype[prop] = commonProps[prop];
      }
    }
  }

  // expose the data structures for the JSAV
  JSAV.ext.ds = {
    array: function(element, options) {
      return new AVArray(this, element, options);
    }
  };
})(jQuery);
<commit_msg>Added compare function to array.<commit_after>/**
* Module that contains the data structure implementations.
* Depends on core.js
*/
(function($) {
  if (typeof JSAV === "undefined") { return; }

  // create a utility function as a jQuery "plugin"
  $.fn.getstyles = function() {
    // Returns the values of CSS properties that are given as
    // arguments. For example, $elem.getstyles("background-color", "color")
    // could return an object {"background-color" : "rgb(255, 120, 120)",
    //                         "color" : "rgb(0, 0, 0)"}
    var res = {},
      arg;
    for (var i = 0; i < arguments.length; i++) {
      arg = arguments[i];
      if ($.isArray(arg)) {
        for (var j = 0; j < arg.length; j++) {
          res[arg[j]] = this.css(arg[j]);
        }
      } else {
        res[arg] = this.css(arg);
      }
    }
    return res;
  };

  // helper functions we want to keep private
  var priv = {
    _hide: function() {
      $(this.element).fadeOut(this.jsav.SPEED);
    },
    // utility function that actually implements show
    _show: function() {
      $(this.element).fadeIn(this.jsav.SPEED);
    }
  };

  // common properties/functions for all data structures, these can be copied
  // to the prototype of a new DS using the addCommonProperties(prototype) function
  var common = {
      // gets or sets the id of the DS
      'id': function(newId) {
        if (newId) {
          this._id = newId;
          return this;
        } else {
          return this._id;
        }
      },
      // returns the position of the DS
      'position': function() {
        return JSAV.position(this.element);
      },
      // utility function that actually implements hide
      // animated show function
      show: JSAV.anim(function() { priv._show.apply(this); },
        function() { priv._hide.apply(this); }),
      // animated hide function
      hide: JSAV.anim(function() { priv._hide.apply(this); },
        function() { priv._show.apply(this); }),
      // dummy methods for initializing a DS, the DS should override these
      initialize: function() { },
      initializeFromElement: function() { },
      clone: function() {}
    },
    // initializes a data structure
    initDs = function(dstr, element, options) {
      dstr.options = $.extend(true, {}, options);
      if ($.isArray(element)) {
        dstr.initialize(element);
      } else if (element) { // assume it's a DOM element
        dstr.element = element;
        dstr.initializeFromElement();
      } else {
        // TODO: create an element for this data structure
      }
    };

  // function that selects elements from $elems that match the indices
  // filter (number, array of numbers, or filter function)
  var getIndices = function($elems, indices) {
    if (typeof indices === "undefined") { return $elems; } // use all if no restrictions are given
    if ($.isFunction(indices)) { // use a filter function..
      return $elems.filter(indices); // ..and let jQuery do the work
    } else if ($.isArray(indices)) {
      // return indices that are in the array
      return $elems.filter(function(index, item) {
        for (var i=0; i < indices.length; i++) {
          if (indices[i] == index) { return true; }
        }
        return false;
      });
    } else if (typeof indices === "number"){
      return $elems.eq(indices); // return the specific index
    } else {
      try { // last resort, try if the argument can be parsed into an int..
        return $elems.eq(parseInt(indices, 10));
      } catch (err) {
        return $({}); // ..if not, return an empty set
      }
    }
  };

  /* Array data structure for JSAV library. */
  var AVArray = function(jsav, element, options) {
    this.jsav = jsav;
    initDs(this, element, options);
  };
  var arrproto = AVArray.prototype;
  addCommonProperties(arrproto); // add functionality from common
  function setHighlight(indices, mode) {
    var testDiv = $('
' +
        '

'),
  	  styleDiv = (mode && mode === "add" ? testDiv.find(".jsavnode").filter(".jsavhighlight"):testDiv.find(".jsavnode").not(".jsavhighlight"));
  	// TODO: general way to get styles for the whole av system
  	$("body").append(testDiv);
    this.css(indices, {color: styleDiv.css("color"), "background-color": styleDiv.css("background-color")});
    testDiv.remove();
  }
  arrproto.highlight = function(indices, options) {
    setHighlight.call(this, indices, "add");
    return this;
  };

  arrproto.unhighlight = function(indices, options) {
    setHighlight.call(this, indices, "remove");
    return this;
  };
  arrproto._setcss = JSAV.anim(function(indices, cssprop) {
    var $elems = getIndices($(this.element).find("li"), indices);
    if (!this.jsav.RECORD || !$.fx.off) { // only animate when playing, not when recording
      // also animate the values due to a bug in webkit based browsers with inherited bg color not changing
      $elems.animate(cssprop, this.jsav.SPEED).find("span.jsavvalue").animate(cssprop, this.jsav.SPEED);
    } else {
      $elems.css(cssprop).find("span.jsavvalue").css(cssprop);
    }
    return this;
  });
  arrproto.css = function(indices, cssprop) {
    var $elems = getIndices($(this.element).find("li"), indices);
    if (typeof cssprop === "string") {
      return $elems.css(cssprop);
    } else {
      if ($.isFunction(indices)) { // if indices is a function, evaluate it right away and get a list of indices
        var all_elems = $(this.element).find("li"),
          sel_indices = []; // array of selected indices
        for (var i = 0; i < $elems.size(); i++) {
          sel_indices.push(all_elems.index($elems[i]));
        }
        indices = sel_indices;
      }
      return this._setcss(indices, cssprop);
    }
  };
  function realSwap(index1, index2, options) {
    var $pi1 = $(this.element).find("li:eq(" + index1 + ")"), // index
      $pi2 = $(this.element).find("li:eq(" + index2 + ")"),
      $i1 = $pi1.find("span.jsavvalue"),
      $i2 = $pi2.find("span.jsavvalue"),
      posdiff = JSAV.position($i1).left - JSAV.position($i2).left,
      indices = $($pi1).add($pi2),
      i1prevStyle = $pi1.getstyles("color", "background-color"),
      i2prevStyle = $pi2.getstyles("color", "background-color"),
      speed = this.jsav.SPEED/5,
      tmp = $pi1.html(),
      $ind1label, $ind2label;
    // first swap the contents of the elements..
    $pi1.html($pi2.html());
    $pi2.html(tmp);
    // swap the actual values in the array
    tmp = $pi1.attr("data-value");
    $pi1.attr("data-value", $pi2.attr("data-value"));
    $pi2.attr("data-value", tmp);
    // .. get the value elements again since the content swap lost the nodes ..
    $i1 = $pi1.find("span.jsavvalue");
    $i2 = $pi2.find("span.jsavvalue");
    // .. change back the index labels ..
    if (this.options.indexed) {
      $ind1label = $pi1.find("span.jsavindexlabel");
      $ind2label = $pi2.find("span.jsavindexlabel");
      tmp = $ind1label.html();
      $ind1label.html($ind2label.html());
      $ind2label.html(tmp);
    }
    if (!this.jsav.RECORD || !$.fx.off) {  // only animate when playing, not when recording
      // .. then set the position so that the array appears unchanged..
      $i2.css({"transform": "translateX(" + (posdiff) + "px)"});
      $i1.css({"transform": "translateX(" + (-posdiff) + "px)"});
      // .. animate the color ..
      indices.animate({"color": "red", "background-color": "pink"}, 3*speed, function() {
        // ..animate the translation to 0, so they'll be in their final positions..
        $i2.animate({"transform": "translateX(0px)"}, 7*speed, 'linear');
        $i1.animate({"transform": "translateX(0px)"}, 7*speed, 'linear',
          function() {
            // ..and finally animate to the original styles.
            $pi1.animate(i1prevStyle, speed);
            $pi2.animate(i2prevStyle, speed);
        });
      });
    }
  }
  arrproto.swap = JSAV.anim(function(index1, index2, options) {
    realSwap.apply(this, arguments);
    return this;
  }, realSwap
  );
  arrproto.clone = function() {
    // fetch all values
    var size = this.size(),
      vals = [];
    for (var i=0; i < size; i++) {
      vals[i] = this.value(i);
    }
    return new AVArray(this.jsav, vals, $.extend(true, {}, this.options, {display: false}));
  };
  arrproto.size = function() { return this.element.find("li").size(); };
  arrproto.value = function(index, newValue) {
    if (!newValue) {
      return this.element.find("li:eq(" + index + ")").attr("data-value");
    } else {
      return this.setvalue(index, newValue);
    }
  };
  arrproto.setvalue = JSAV.anim(function(index, newValue) {
    var $index = this.element.find("li:eq(" + index + ")");
    var oldVal = $index.attr("data-value") || undefined;
    $index.attr("data-value", newValue);
    $index.find(".jsavvalue").html("" + newValue);
    return oldVal;
  });
  arrproto.initialize = function(data) {
    var el = $("
"),
      liel;
    this.options = jQuery.extend({display: true}, this.options);
    $.each(data, function(index, item) {
      liel = $("
" + item + "
");
      // set the data attribute for the index
      liel.attr("data-value", item);
      el.append(liel);
    });
    $(this.jsav.container).append(el);
    this.element = el;
    this.layout();
    el.css("display", "none");
    var visible = (typeof this.options.display === "boolean" && this.options.display === true);
    if (visible) {
      if (this.jsav.currentStep() === 0) { // at beginning, just make it visible
        el.css("display", "block");
      } else { // add effect to show otherwise
        this.show();
      }
    }
  };
  arrproto.initializeFromElement = function() {
    // TODO: handle settings from data-attributes
    if (!this.element) { return; }
    var $elem = this.element,
      $elems = $elem.find("li");
    $elem.addClass("jsavarray");
    $elems.each(function(index, item) {
      var $this = $(this);
      if (!$this.attr("data-value")) {
        $this.attr("data-value", parseInt($this.html(), 10));
      }
      $this.addClass("jsavnode jsavindex").html("" + $this.html() + "");
    });
    this.layout();
  };
  arrproto.layout = function() {
    var layoutAlg = this.options.layout || "_default";
    this.element.removeClass("jsavbararray");
    this.jsav.layout.array[layoutAlg](this);
  };
  arrproto.state = function(newstate) {
    if (newstate) {
      $(this.element).html(newstate.html);
    } else {
      var sta = {
        html: $(this.element).html()
      };
      return sta;
    }
  };
  arrproto.compare = function(otherArray, options) {
    var opts = options || {},
      i, j,
      equal,
      cssprop,
      len;
    if ($.isArray(otherArray)) { // simple case of array values
      if (!options) { // if nothing in options is specified
        len = otherArray.length;
        if (this.size() !== len) { // don't compare arrays of different size
          return false;
        }
        for (i = 0; i < len; i++) { // are the values equal
          equal = this.value(i) == otherArray[i];
          if (!equal) { return false; }
        }
        return true; // if tests passed, arrays are equal
      } else { // if options
        if ('css' in opts) { // if css property given, compare given array to property
          cssprop = opts.css;
          for (i = 0; i < len; i++) {
            equal = this.css(i, cssprop) == otherArray[i];
            if (!equal) { return false; }
          }
          return true; // if tests passed, arrays are equal
        }
      }
    } else if (otherArray instanceof AVArray) { // JSAV array
      len = otherArray.size();
      if (this.size() !== len) { // size check
        return false;
      }
      if (!('value' in opts) || opts['value']) { // if comparing values
        for (i = 0; i < len; i++) {
          equal = this.value(i) == otherArray.value(i);
          if (!equal) { return false; }
        }
      }
      if ('css' in opts) { // if comparing css properties
        if ($.isArray(opts.css)) { // array of property names
          for (i = 0; i < opts.css.length; i++) {
            cssprop = opts.css[i];
            for (j = 0; j < len; j++) {
              equal = this.css(j, cssprop) == otherArray.css(j, cssprop);
              if (!equal) { return false; }
            }
          }
        } else { // if not array, expect it to be a property name string
          cssprop = opts.css;
          for (i = 0; i < len; i++) {
            equal = this.css(i, cssprop) == otherArray.css(i, cssprop);
            if (!equal) { return false; }
          }
        }
      }
      return true; // if tests passed, arrays are equal
    }

    // default: return false
    return false;
  };

  function addCommonProperties(dsPrototype, commonProps) {
    if (!commonProps) { commonProps = common; }
    for (var prop in commonProps) {
      if (commonProps.hasOwnProperty(prop)) {
        dsPrototype[prop] = commonProps[prop];
      }
    }
  }

  // expose the data structures for the JSAV
  JSAV.ext.ds = {
    array: function(element, options) {
      return new AVArray(this, element, options);
    }
  };
})(jQuery);
<|endoftext|>


<commit_before>require('../test_helper');

describe('Record', () => {
  describe('#soundcloud', () => {
    var hash = {
      title: 'Faut qu\'on rentre bosser',
      artwork_url: 'path/to/artwork-large',
      duration: 300000,
      tag_list: ['foo', 'bar'],
      permalink_url: 'http://foo/bar',
      user: {
        username: 'Casseurs Flowteurs'
      }
    };

    var record = Record.soundcloud(hash);

    it('should map SoundCloud fields to our own ones', () => {
      var record = Record.soundcloud(hash);

      assert.equal(hash.title, record.title);
      assert.equal(hash.user.username, record.artist);
      assert.equal(hash.tag_list, record.tags);
      assert.equal(hash.permalink_url, record.url);
    });

    it('should pick the right icon dimension', () => {
      assert.equal('path/to/artwork-t200x200', record.icon);
    });

    it('should convert the duration to seconds', () => {
      assert.equal(300, record.duration);
    });

    it('should compute the `human_time` field on demand', () => {
      assert.equal(false,  record.hasOwnProperty('human_time'))
      assert.equal('5:00', record.human_time);
    });

    it('should set the `service` field', () => {
      assert.equal('soundcloud', record.service);
    });

    it('should set a default icon', () => {
      var record = Record.soundcloud({
        user: { username: 'foo' }
      });

      assert.equal('assets/images/default_artwork.svg', record.icon);
    });
  });

  describe('#youtube', () => {
    var hash = {
      id: 'foobar',
      snippet: {
        title: 'Kaytranada - Drive Me Crazy (ft. Vic Mensa)',
        channelTitle: 'XL Recordings',
        tags: ['foo', 'bar'],
        thumbnails: {
          medium: { url: 'foo/bar' }
        }
      },
      contentDetails: {
        duration: '4M3S'
      }
    };

    var record = Record.youtube(hash);

    it('should map YouTube fields to our own ones', () => {
      assert.equal(hash.snippet.title, record.title);
      assert.equal(hash.snippet.channelTitle, record.artist);
      assert.equal(hash.snippet.thumbnails.medium.url, record.icon);
      assert.equal(hash.snippet.tags, record.tags);
    });

    it('should convert the duration to seconds', () => {
      assert.equal(243, record.duration);
    });

    it('should compute the `human_time` field on demand', () => {
      assert.equal(false,  record.hasOwnProperty('human_time'))
      assert.equal('4:03', record.human_time);
    });

    it('should set the `service` field', () => {
      assert.equal('youtube', record.service);
    });
  });

  describe('#local', () => {
    var hash = {
      title: 'Maliblue',
      artist: 'Darius',
      genre: 'French House',
      album: 'Velour',
      track: 4,
      duration: 259
    };

    var record = Record.local(hash);

    it('should copy fields verbatim', () => {
      for (key in hash)
        assert.equal(hash[key], record[key]);
    });

    it('should compute the `human_time` field on demand', () => {
      assert.equal(false,  record.hasOwnProperty('human_time'))
      assert.equal('4:19', record.human_time);
    });

    it('should set the `service` field', () => {
      assert.equal('local', record.service);
    });

    it('should set the `file://` protocol for non-default icons', () => {
      var record = Record.local({
        icon: 'path/to/icon'
      });

      assert.equal('file://path/to/icon', record.icon);
    });
  });
});
<commit_msg>Add some missing tests for the Record class<commit_after>require('../test_helper');

describe('Record', () => {
  describe('#soundcloud', () => {
    var hash = {
      title: 'Faut qu\'on rentre bosser',
      artwork_url: 'path/to/artwork-large',
      duration: 300000,
      tag_list: ['foo', 'bar'],
      permalink_url: 'http://foo/bar',
      user: {
        username: 'Casseurs Flowteurs'
      }
    };

    var record = Record.soundcloud(hash);

    it('should map SoundCloud fields to our own ones', () => {
      var record = Record.soundcloud(hash);

      assert.equal(hash.title, record.title);
      assert.equal(hash.user.username, record.artist);
      assert.equal(hash.tag_list, record.tags);
      assert.equal(hash.permalink_url, record.url);
    });

    it('should pick the right icon dimension', () => {
      assert.equal('path/to/artwork-t200x200', record.icon);
    });

    it('should convert the duration to seconds', () => {
      assert.equal(300, record.duration);
    });

    it('should not set the `human_time` field', () => {
      assert.equal(false,  record.hasOwnProperty('human_time'))
      assert.equal('5:00', record.human_time);
    });

    it('should set the `service` field', () => {
      assert.equal('soundcloud', record.service);
    });

    it('should set a default icon', () => {
      var record = Record.soundcloud({
        user: { username: 'foo' }
      });

      assert.equal('assets/images/default_artwork.svg', record.icon);
    });
  });

  describe('#youtube', () => {
    var hash = {
      id: 'foobar',
      snippet: {
        title: 'Kaytranada - Drive Me Crazy (ft. Vic Mensa)',
        channelTitle: 'XL Recordings',
        tags: ['foo', 'bar'],
        thumbnails: {
          medium: { url: 'foo/bar' }
        }
      },
      contentDetails: {
        duration: '4M3S'
      }
    };

    var record = Record.youtube(hash);

    it('should map YouTube fields to our own ones', () => {
      assert.equal(hash.snippet.title, record.title);
      assert.equal(hash.snippet.channelTitle, record.artist);
      assert.equal(hash.snippet.thumbnails.medium.url, record.icon);
      assert.equal(hash.snippet.tags, record.tags);
    });

    it('should convert the duration to seconds', () => {
      assert.equal(243, record.duration);
    });

    it('should compute the `human_time` field on demand', () => {
      assert.equal(false,  record.hasOwnProperty('human_time'))
      assert.equal('4:03', record.human_time);
    });

    it('should set the `service` field', () => {
      assert.equal('youtube', record.service);
    });
  });

  describe('#local', () => {
    var hash = {
      title: 'Maliblue',
      artist: 'Darius',
      genre: 'French House',
      album: 'Velour',
      track: 4,
      duration: 259
    };

    var record = Record.local(hash);

    it('should copy fields verbatim', () => {
      for (key in hash)
        assert.equal(hash[key], record[key]);
    });

    it('should not set `human_time` field', () => {
      assert.equal(false,  record.hasOwnProperty('human_time'))
      assert.equal('4:19', record.human_time);
    });

    it('should set the `service` field', () => {
      assert.equal('local', record.service);
    });

    it('should set the `file://` protocol for non-default icons', () => {
      var record = Record.local({
        icon: 'path/to/icon'
      });

      assert.equal('file://path/to/icon', record.icon);
    });
  });

  describe('#JSPF', () => {
    var hash = {
      title: 'Best of Gojira',
      track: [{
        location: '/path/to/mp3',
        title:    'Born in Winter',
        image:    'foo.png',
        creator:  'Gojira',
        duration: 231
      }]
    };

    var record = Record.JSPF(hash);

    it('should map JSPF fields to our ones', () => {
      var item  = record.items.first();
      var track = hash.track.first();

      assert.equal(record.title, hash.title);

      assert.equal(item.id,       track.location);
      assert.equal(item.title,    track.title);
      assert.equal(item.artist,   track.creator);
      assert.equal(item.icon,     track.image);
      assert.equal(item.duration, track.duration);
    });

    it('should set a default id based on the title', () => {
      assert.equal('best-of-gojira', record.id);
    })

    it('should set a default icon when there are no tracks', () => {
      assert.equal(Record.JSPF({title: 'Foo', track: []}).icon, Paths.default_artwork);
    });

    it('should not set `human_time` field', () => {
      var item = record.items.first();

      assert.equal(false,  item.hasOwnProperty('human_time'))
      assert.equal('3:51', item.human_time);
    });
  });

  describe('#toJSPF', () => {
    var item = Record.raw({
      id:       '/path/to/mp3',
      title:    'Surfacing',
      artist:   'Slipknot',
      icon:     'foo.png',
      duration: 218
    });

    var record = Record.raw({
      title: 'Best of Slipknot',
      items: [item]
    });

    var track    = Record.toJSPF(item);
    var playlist = Record.toJSPF(record);

    it('should map our fields to the JSPF ones', () => {
      assert.equal(playlist.title, record.title);
      assert.deepEqual(playlist.track.first(), track);

      assert.equal(track.location, item.id);
      assert.equal(track.title,    item.title);
      assert.equal(track.creator,  item.artist);
      assert.equal(track.image,    item.icon);
      assert.equal(track.duration, item.duration);
    });
  });

  describe('#raw', () => {
    var hash = {
      id:  'foo',
      foo: 'bar',
      baz: 'quux'
    };

    var record = Record.raw(hash);

    it('should return an instance of Record', () => {
      assert(record instanceof Record);
    });

    it('should copy fields verbatim', () => {
      assert.equal(record.id,  hash.id);
      assert.equal(record.foo, hash.foo);
      assert.equal(record.baz, hash.baz);
    });
  });

  describe('#link', () => {
    it('should set the `previous` and `next` attributes of the given record', () => {
      var record = {};

      Record.link(record, 1, [1, null, 2]);

      assert.equal(record.previous, 1);
      assert.equal(record.next, 2);
    });

    it('should not set the `previous` field for the first record', () => {
      var record = {};

      Record.link(record, 0, [record]);

      assert.equal(record.previous, null);
    });

    it('should not set the `next` field for the last record', () => {
      var record = {};

      Record.link(record, 0, [record]);

      assert.equal(record.next, null);
    });
  });
});
<|endoftext|>


<commit_before>var util = require('../util.test');
var config = require('../config.test');

module.exports = function() {
  util.request('https://https.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('https://https1.w2.org:' + config.httpsPort + '/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://https1.w2.org:' + config.serverPort + '/index.html', function(res, data) {
    data.type.should.be.equal('server');
  });

  util.request('https://https2.w2.org:' + config.httpsPort + '/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://https2.w2.org/index.html', function(res, data) {
    data.type.should.be.equal('server');
  });

  util.request('http://https3.w2.org:5566/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://whistle-ssl.https.w2.org:' + config.httpsPort + '/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });
};
<commit_msg>test: proxy agent<commit_after>var util = require('../util.test');
var config = require('../config.test');

module.exports = function() {
  util.request('https://https.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('https://https1.w2.org:' + config.httpsPort + '/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://https1.w2.org:' + config.serverPort + '/index.html', function(res, data) {
    data.type.should.be.equal('server');
  });

  util.request('https://https2.w2.org:' + config.httpsPort + '/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://https2.w2.org/index.html', function(res, data) {
    data.type.should.be.equal('server');
  });

  util.request('https://https3.w2.org:5566/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://whistle-ssl.https.w2.org:' + config.httpsPort + '/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });
};
<|endoftext|>


<commit_before>exports.onClientEntry = () => {
  (() => {
    function OptanonWrapper() { } // eslint-disable-line no-unused-vars
  })();
};

// Always start at the top of the page on a route change.
exports.onRouteUpdate = () => {
  if (typeof window !== `undefined`) { window.scrollTo(0, 0)}
}

exports.shouldUpdateScroll = args => {
   return false;
};<commit_msg>[MARKENG-156] Remove scrollTo function in gatsby-browser causing double click issues<commit_after>exports.onClientEntry = () => {
  (() => {
    function OptanonWrapper() { } // eslint-disable-line no-unused-vars
  })();
};
<|endoftext|>


<commit_before>var util = require('../util.test');

module.exports = function() {
  // socks5模块的server在Node10上无法启动
  if (process.versions.modules >= 64) {
    return;
  }
  util.request('http://socks1.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1080);
  });
  util.request('https://socks1.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks2.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1118);
  });
  util.request('https://socks2.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks3.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1080);
  });
  util.request('https://socks3.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks4.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1118);
  });
  util.request('https://socks4.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks5.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1080);
  });
  util.request('https://socks5.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks6.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1118);
  });
  util.request('https://socks6.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks7.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1080);
  });
  util.request('https://socks7.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks8.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1118);
  });
  util.request('https://socks8.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });
};
<commit_msg>test: socksv5 -> sockx<commit_after>var util = require('../util.test');

module.exports = function() {
  util.request('http://socks1.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1080);
  });
  util.request('https://socks1.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks2.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1118);
  });
  util.request('https://socks2.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks3.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1080);
  });
  util.request('https://socks3.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks4.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1118);
  });
  util.request('https://socks4.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks5.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1080);
  });
  util.request('https://socks5.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks6.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1118);
  });
  util.request('https://socks6.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks7.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1080);
  });
  util.request('https://socks7.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });

  util.request('http://socks8.w2.org/index.html', function(res, data) {
    data.port.should.be.equal(1118);
  });
  util.request('https://socks8.w2.org/index.html', function(res, data) {
    data.body.should.be.equal('test');
  });
};
<|endoftext|>


<commit_before>var config = {
  sauceUser: process.env.SAUCE_USERNAME,
  sauceKey: process.env.SAUCE_ACCESS_KEY,

  capabilities: {
    name: 'Browser Test for FluxEx',
    public: 'public',
    tags: [process.env.TRAVIS_JOB_ID, process.env.TRAVIS_COMMIT, 'fluxex']
  },

  multiCapabilities: [
    {browserName: 'chrome'},
    {browserName: 'firefox'},
    {browserName: 'safari', version: 7, platform: 'OS X 10.9'},
    {browserName: 'safari', version: 6, platform: 'OS X 10.8'},
    {browserName: 'internet explorer', version: 11, platform: 'Windows 8.1'},
    {browserName: 'internet explorer', version: 10, platform: 'Windows 8'},
    {browserName: 'internet explorer', version: 9, platform: 'Windows 7'},
    {browserName: 'iphone', version:'7.1', platform: 'OS X 10.9'},
    {browserName: 'iphone', version:'7.0', platform: 'OS X 10.9'},
    {browserName: 'iphone', version:'6.1', platform: 'OS X 10.8'},
    {browserName: 'ipad', version:'7.1', platform: 'OS X 10.9'},
    {browserName: 'ipad', version:'7.0', platform: 'OS X 10.9'},
    {browserName: 'ipad', version:'6.1', platform: 'OS X 10.8'}
  ],

  specs: ['spec.js'],

  // This enable testing on none angular pages without test code change.
  onPrepare: function () {
    return augmentBrowser(browser, config).then(function(newBrowser) {
      browser = newBrowser;
      element = browser.element;
      browser.ignoreSynchronization = true;
      return true;
    });
  },

  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000
  }
};

module.exports.config = config;<commit_msg>remove augmentBrowser<commit_after>var config = {
  sauceUser: process.env.SAUCE_USERNAME,
  sauceKey: process.env.SAUCE_ACCESS_KEY,

  capabilities: {
    name: 'Browser Test for FluxEx',
    public: 'public',
    tags: [process.env.TRAVIS_JOB_ID, process.env.TRAVIS_COMMIT, 'fluxex']
  },

  multiCapabilities: [
    {browserName: 'chrome'},
    {browserName: 'firefox'},
    {browserName: 'safari', version: 7, platform: 'OS X 10.9'},
    {browserName: 'safari', version: 6, platform: 'OS X 10.8'},
    {browserName: 'internet explorer', version: 11, platform: 'Windows 8.1'},
    {browserName: 'internet explorer', version: 10, platform: 'Windows 8'},
    {browserName: 'internet explorer', version: 9, platform: 'Windows 7'},
    {browserName: 'iphone', version:'7.1', platform: 'OS X 10.9'},
    {browserName: 'iphone', version:'7.0', platform: 'OS X 10.9'},
    {browserName: 'iphone', version:'6.1', platform: 'OS X 10.8'},
    {browserName: 'ipad', version:'7.1', platform: 'OS X 10.9'},
    {browserName: 'ipad', version:'7.0', platform: 'OS X 10.9'},
    {browserName: 'ipad', version:'6.1', platform: 'OS X 10.8'}
  ],

  specs: ['spec.js'],

  // This enable testing on none angular pages without test code change.
  onPrepare: function () {
    element = browser.element;
    browser.ignoreSynchronization = true;
  },

  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000
  }
};

module.exports.config = config;<|endoftext|>


<commit_before>'use strict';

const type = require('./lib/typeValidation.js');
const isString = type.isString;
const isObject = type.isObject;
const isArray = type.isArray;

var EscapeJS = {};

EscapeJS.str = function(param) {
    if(!param) {
        param = '';
    }

    if(!isString(param)) {
        throw new Error('[ERROR] param must be from string type');
    }

    return escape(param);
};

EscapeJS.json = function(param) {
    if(!param) {
        param = {};
    }

    if(!isObject(param)) {
        throw new Error('[ERROR] param must be from object type');
    }

	var tmp;
    var isArr;

	for(var attr in param) {
		tmp = param[attr];
		isArr = false;

		// STRING
	 	if (param.hasOwnProperty(attr)) {
			isArr = isArray(tmp);

			if(isString(tmp)) {
				param[attr] = EscapeJS.str(tmp);
			}

			if(isArr) {
				EscapeJS.array(tmp);
			}

			if(!isArr && isObject(tmp)) {
				EscapeJS.json(tmp);
			}
	  	}
	}

    return param;
};

EscapeJS.array = function(param) {
	if(!param) {
		param = [];
	}

	if(!isArray(param)) {
        throw new Error('[ERROR] param must be from array type');
    }

    var tmp;
	var countList = param.length;
	var isArr = false;

	for(var i = 0; i < countList; i++) {
		tmp = param[i];
		isArr = isArray(tmp);

		if(isString(tmp)) {
			param[i] = EscapeJS.str(tmp);
		}

		if(tmp && isArr) {
			EscapeJS.array(tmp);
		}

		if(tmp && !isArr && isObject(tmp)) {
			EscapeJS.json(tmp);
		}
	}

	return param;
};

EscapeJS.escape = function(param){
	if(!param){
		throw new Error('[ERROR] param has no type');
	}
	var tmp = param;
	if(isString(tmp)){
		param = EscapeJS.str(tmp)
	}
	if(isArray(tmp)){
		EscapeJS.array(tmp)
	}
	if(isObject(tmp)){
		EscapeJS.json(tmp);
	}
	return param;
};

module.exports = EscapeJS;
<commit_msg>[ * ] identity and improve algorithm<commit_after>'use strict';

const type = require('./lib/typeValidation.js');
const isString = type.isString;
const isObject = type.isObject;
const isArray = type.isArray;

var EscapeJS = {};

EscapeJS.str = function(param) {
	if(!param) {
		param = '';
	}

	if(!isString(param)) {
		throw new Error('[ERROR] param must be from string type');
	}

	return escape(param);
};

EscapeJS.json = function(param) {
	if(!param) {
		param = {};
	}

	if(!isObject(param)) {
		throw new Error('[ERROR] param must be from object type');
	}

	var tmp;
	var isArr;

	for(var attr in param) {
		tmp = param[attr];
		isArr = false;

		// STRING
		if (param.hasOwnProperty(attr)) {
			isArr = isArray(tmp);

			if(isString(tmp)) {
				param[attr] = EscapeJS.str(tmp);
			}

			if(isArr) {
				EscapeJS.array(tmp);
			}

			if(!isArr && isObject(tmp)) {
				EscapeJS.json(tmp);
			}
		}
	}

	return param;
};

EscapeJS.array = function(param) {
	if(!param) {
		param = [];
	}

	if(!isArray(param)) {
		throw new Error('[ERROR] param must be from array type');
	}

	var tmp;
	var countList = param.length;
	var isArr = false;

	for(var i = 0; i < countList; i++) {
		tmp = param[i];
		isArr = isArray(tmp);

		if(isString(tmp)) {
			param[i] = EscapeJS.str(tmp);
		}

		if(tmp && isArr) {
			EscapeJS.array(tmp);
		}

		if(tmp && !isArr && isObject(tmp)) {
			EscapeJS.json(tmp);
		}
	}

	return param;
};

EscapeJS.escape = function(param){
	if(!param){
		throw new Error('[ERROR] param has no type');
	}
	var tmp = param;
	if(isString(tmp)){
		param = EscapeJS.str(tmp)
	}
	if(isArray(tmp)){
		EscapeJS.array(tmp)
	}
	if(isObject(tmp)){
		EscapeJS.json(tmp);
	}
	return param;
};

module.exports = EscapeJS;<|endoftext|>


<commit_before>import React from "react-native";
import Colors from "../../colors.json";
import ModalSheet from "./modal-sheet";
import TouchFeedback from "./touch-feedback";
import KeyboardSpacer from "./keyboard-spacer";
import VersionCodes from "../../modules/version-codes";

const {
	StyleSheet,
	Platform,
	Dimensions,
	TouchableWithoutFeedback,
	Animated,
	PixelRatio,
	View,
	Text
} = React;

const styles = StyleSheet.create({
	container: {
		flex: 1,
		position: "absolute",
		top: 0,
		left: 0
	},
	overlay: {
		flex: 1,
		alignItems: "stretch",
		justifyContent: "flex-end",
		backgroundColor: Colors.fadedBlack
	},
	menuItem: {
		borderColor: Colors.separator,
		borderTopWidth: 1 / PixelRatio.get()
	},
	menuItemFirst: {
		borderTopWidth: 0
	},
	menuItemText: {
		fontSize: 16,
		color: Colors.darkGrey,
		margin: 20,
		paddingHorizontal: 4
	}
});

let _renderComponent, _isShown;

export default class Modal extends React.Component {
	constructor(props) {
		super(props);

		this.state = {
			component: null
		};
	}

	componentDidMount() {
		_renderComponent = this._renderComponent.bind(this);
		_isShown = this._isShown.bind(this);
	}

	componentWillUnmount() {
		_renderComponent = null;
		_isShown = null;
	}

	_renderComponent(component) {
		if (component === this.state.component) {
			return;
		}

		if (component) {
			this.setState({
				component,
				fadeAnim: new Animated.Value(0)
			}, () => Animated.timing(this.state.fadeAnim, {
				toValue: 1,
				duration: 300
			}).start());
		} else {
			Animated.timing(this.state.fadeAnim, {
				toValue: 0,
				duration: 300
			}).start(() => this.setState({ component: null }));
		}
	}

	_isShown() {
		return !!this.state.component;
	}

	render() {
		if (!this.state.component) {
			return null;
		}

		const win = Dimensions.get("window");

		return (
			<Animated.View style={[ styles.container, { height: win.height, width: win.width, opacity: this.state.fadeAnim } ]}>
				{this.state.component}

				<KeyboardSpacer />
			</Animated.View>
		);
	}
}

Modal.isShown = () => {
	if (_isShown) {
		return _isShown();
	}

	return false;
};

Modal.renderComponent = component => {
	if (_renderComponent) {
		_renderComponent(component);

		return true;
	}

	return false;
};

Modal.renderModal = component => {
	return Modal.renderComponent((
		<TouchableWithoutFeedback onPress={() => Modal.renderComponent(null)}>
			<View style={styles.overlay}>
				<ModalSheet style={Platform.OS === "android" && Platform.Version <= VersionCodes.KITKAT ? { marginBottom: 25 } : null}>
					{component}
				</ModalSheet>
			</View>
		</TouchableWithoutFeedback>
	));
};

Modal.showActionSheetWithOptions = (options, callback) => {
	return Modal.renderModal(options.options.map((item, index) =>
		(
			<TouchFeedback
				key={index}
				onPress={() =>
					global.requestAnimationFrame(() => {
						callback(index);

						Modal.renderComponent(null);
					}
				)}
			>
				<View style={[ styles.menuItem, index === 0 ? styles.menuItemFirst : null ]}>
					<Text style={styles.menuItemText}>{item}</Text>
				</View>
			</TouchFeedback>
		)
	));
};

Modal.showActionSheetWithItems = (items, callback) => {
	const options = [];
	const actions = [];

	for (const k in items) {
		options.push(k);
		actions.push(items[k]);
	}

	Modal.showActionSheetWithOptions({ options }, index => actions[index](), callback);
};
<commit_msg>Add a padding only below Kitkat<commit_after>import React from "react-native";
import Colors from "../../colors.json";
import ModalSheet from "./modal-sheet";
import TouchFeedback from "./touch-feedback";
import KeyboardSpacer from "./keyboard-spacer";
import VersionCodes from "../../modules/version-codes";

const {
	StyleSheet,
	Platform,
	Dimensions,
	TouchableWithoutFeedback,
	Animated,
	PixelRatio,
	View,
	Text
} = React;

const styles = StyleSheet.create({
	container: {
		flex: 1,
		position: "absolute",
		top: 0,
		left: 0
	},
	overlay: {
		flex: 1,
		alignItems: "stretch",
		justifyContent: "flex-end",
		backgroundColor: Colors.fadedBlack
	},
	menuItem: {
		borderColor: Colors.separator,
		borderTopWidth: 1 / PixelRatio.get()
	},
	menuItemFirst: {
		borderTopWidth: 0
	},
	menuItemText: {
		fontSize: 16,
		color: Colors.darkGrey,
		margin: 20,
		paddingHorizontal: 4
	}
});

let _renderComponent, _isShown;

export default class Modal extends React.Component {
	constructor(props) {
		super(props);

		this.state = {
			component: null
		};
	}

	componentDidMount() {
		_renderComponent = this._renderComponent.bind(this);
		_isShown = this._isShown.bind(this);
	}

	componentWillUnmount() {
		_renderComponent = null;
		_isShown = null;
	}

	_renderComponent(component) {
		if (component === this.state.component) {
			return;
		}

		if (component) {
			this.setState({
				component,
				fadeAnim: new Animated.Value(0)
			}, () => Animated.timing(this.state.fadeAnim, {
				toValue: 1,
				duration: 300
			}).start());
		} else {
			Animated.timing(this.state.fadeAnim, {
				toValue: 0,
				duration: 300
			}).start(() => this.setState({ component: null }));
		}
	}

	_isShown() {
		return !!this.state.component;
	}

	render() {
		if (!this.state.component) {
			return null;
		}

		const win = Dimensions.get("window");

		return (
			<Animated.View style={[ styles.container, { height: win.height, width: win.width, opacity: this.state.fadeAnim } ]}>
				{this.state.component}

				<KeyboardSpacer />
			</Animated.View>
		);
	}
}

Modal.isShown = () => {
	if (_isShown) {
		return _isShown();
	}

	return false;
};

Modal.renderComponent = component => {
	if (_renderComponent) {
		_renderComponent(component);

		return true;
	}

	return false;
};

Modal.renderModal = component => {
	return Modal.renderComponent((
		<TouchableWithoutFeedback onPress={() => Modal.renderComponent(null)}>
			<View style={styles.overlay}>
				<ModalSheet style={Platform.OS === "android" && Platform.Version < VersionCodes.KITKAT ? { marginBottom: 25 } : null}>
					{component}
				</ModalSheet>
			</View>
		</TouchableWithoutFeedback>
	));
};

Modal.showActionSheetWithOptions = (options, callback) => {
	return Modal.renderModal(options.options.map((item, index) =>
		(
			<TouchFeedback
				key={index}
				onPress={() =>
					global.requestAnimationFrame(() => {
						callback(index);

						Modal.renderComponent(null);
					}
				)}
			>
				<View style={[ styles.menuItem, index === 0 ? styles.menuItemFirst : null ]}>
					<Text style={styles.menuItemText}>{item}</Text>
				</View>
			</TouchFeedback>
		)
	));
};

Modal.showActionSheetWithItems = (items, callback) => {
	const options = [];
	const actions = [];

	for (const k in items) {
		options.push(k);
		actions.push(items[k]);
	}

	Modal.showActionSheetWithOptions({ options }, index => actions[index](), callback);
};
<|endoftext|>


<commit_before>class SchemaValidatorError extends Error {
  constructor(message) {
    super();
    this.message = message;
  }
}

class Reject {
  constructor(message, name, value) {
    this.message = message;
    this.name = name || [];
    this.value = value || [];
  }
  withMoreInfo(name, value) {
    return new Reject(this.message, [name].concat(this.name), this.value.length ? this.value : [value]);
  }
  toError() {
    let name = this.name.filter(n => !!n).join('');
    if (!this.name[0]) {
      name = 'value' + name;
    }
    const stringValue = JSON.stringify(this.value[0]);
    return new SchemaValidatorError(`${name} ${this.message}, but got ${stringValue}`);
  }
}

class Break {
  constructor(value) {
    this.value = value;
  }
}

// schema object
const create = plugins => {
  class Schema {
    constructor(validators) {
      this._validators = validators || [];
    }
    extend(plugin) {
      return create(plugins.concat([plugin]));
    }
    reject(message) {
      return new Reject(message);
    }
    break_(value) {
      return new Break(value);
    }
    _first(validator) {
      return new Schema([validator].concat(this._validators));
    }
    _last(validator) {
      return new Schema(this._validators.concat([validator]));
    }
    first(f) {
      return this._first({
        f: wrapValidate(f)
      });
    }
    then(f) {
      return this._last({
        f: wrapValidate(f)
      });
    }
    _satisfy(message, isValid) {
      return this._when2(isValid, null, _ => sv.reject(message));
    }
    map(f) {
      return this._when2(_ => true, f);
    }
    _when2(isValid, then, else_) {
      return this._last({
        if_: isValid,
        then: then,
        else_: else_
      });
    }
    _when(schema, onSuccess, onError) {
      return this.then(value => {
        const result = schema._validate(value);
        if (result instanceof Reject) {
          return onError ? onError(value) : result;
        }
        return onSuccess ? onSuccess(result, value) : result;
      });
    }
    when(checkerSchema, thenSchema, elseSchema) {
      return this._when(checkerSchema, (result, original) => {
        return thenSchema;
      }, original => {
        return elseSchema || original;
      });
    }
    check(schema) {
      return this._when(schema, (result, original) => {
        return original;
      });
    }
    try_(schema, catchSchema) {
      return this._when(schema, null, original => {
        return catchSchema || original;
      });
    }
    _validate(value, name) {
      const result = validateHelp(this._validators, 0, value);
      if (result instanceof Reject) {
        return result.withMoreInfo(name, value);
      }
      if (result instanceof Break) {
        return newValue.value;
      }
      return result;
    }
    validate(value, name) {
      const newValue = this._validate(value, name);
      if (newValue instanceof Reject) {
        throw newValue.toError();
      }
      return newValue;
    }
    key(key, valueSchema) {
      const name = (typeof key === 'number') ? `[${key}]` : `.${key}`;
      return sv._last({
        f: value => {
          const child = value[key];
          return valueSchema._validate(child, name);
        }
      });
    }
    flatten(toKeySchemas) {
      return this.then(value => {
        const newItems = [];
        for (let schema of toKeySchemas(value)) {
          const result = schema._validate(value);
          if (result instanceof Reject) {
            return result;
          }
          newItems.push(result);
        }
        return newItems;
      });
    }
  }

  function wrapValidate(f) {
    return value => {
      const newValue = f(value);
      if (newValue instanceof Schema) {
        return newValue._validate(value);
      }
      return newValue;
    };
  }
  plugins.forEach(plugin => addPlugin(Schema.prototype, plugin));
  // empty schema instance
  const sv = new Schema();
  return sv;
}

function validateHelp(validators, i, value) {
  if (i >= validators.length) {
    return value;
  }
  const validator = validators[i];
  if (validator.if_) {
    const isValid = validator.if_(value);
    if (isValid) {
      const newValue = validator.then ? validator.then(value) : value;
      return validateHelp(validators, i + 1, newValue);
    } else {
      return validator.else_(value);
    }
  }
  const newValue = validator.f(value);
  if (newValue instanceof Reject) {
    return newValue;
  } else if (newValue instanceof Break) {
    return newValue.value;
  }
  return validateHelp(validators, i + 1, newValue);
}

function addPlugin(prototype, plugin) {
  Object.keys(plugin).forEach(key => {
    if (prototype[key]) {
      throw new Error(`PluginError: Function ${key} is already defined.`);
    }
    const f = plugin[key];
    if (typeof f !== 'function') {
      throw new Error(`PluginError: Plugin ${key} is mulformed. Value should be a function.`);
    }
    prototype[key] = f;
  });
}

module.exports = {
  create: create,
  SchemaValidatorError: SchemaValidatorError,
};
<commit_msg>then() implemented by type:'if'<commit_after>class SchemaValidatorError extends Error {
  constructor(message) {
    super();
    this.message = message;
  }
}

class Reject {
  constructor(message, name, value) {
    this.message = message;
    this.name = name || [];
    this.value = value || [];
  }
  withMoreInfo(name, value) {
    return new Reject(this.message, [name].concat(this.name), this.value.length ? this.value : [value]);
  }
  toError() {
    let name = this.name.filter(n => !!n).join('');
    if (!this.name[0]) {
      name = 'value' + name;
    }
    const stringValue = JSON.stringify(this.value[0]);
    return new SchemaValidatorError(`${name} ${this.message}, but got ${stringValue}`);
  }
}

class Break {
  constructor(value) {
    this.value = value;
  }
}

// schema object
const create = plugins => {
  class Schema {
    constructor(validators) {
      this._validators = validators || [];
    }
    extend(plugin) {
      return create(plugins.concat([plugin]));
    }
    reject(message) {
      return new Reject(message);
    }
    break_(value) {
      return new Break(value);
    }
    _first(validator) {
      return new Schema([validator].concat(this._validators));
    }
    _last(validator) {
      return new Schema(this._validators.concat([validator]));
    }
    first(f) {
      return this._first({
        type: 'if',
        then: f
      });
    }
    then(f) {
      return this._when2(null, f);
    }
    _satisfy(message, isValid) {
      return this._when2(isValid, null, _ => sv.reject(message));
    }
    map(f) {
      return this._when2(null, f);
    }
    _when2(isValid, then, else_) {
      return this._last({
        type: 'if',
        if_: isValid,
        then: then,
        else_: else_
      });
    }
    _when(schema, onSuccess, onError) {
      return this.then(value => {
        const result = schema._validate(value);
        if (result instanceof Reject) {
          return onError ? onError(value) : result;
        }
        return onSuccess ? onSuccess(result, value) : result;
      });
    }
    when(checkerSchema, thenSchema, elseSchema) {
      return this._when(checkerSchema, (result, original) => {
        return thenSchema;
      }, original => {
        return elseSchema || original;
      });
    }
    check(schema) {
      return this._when(schema, (result, original) => {
        return original;
      });
    }
    try_(schema, catchSchema) {
      return this._when(schema, null, original => {
        return catchSchema || original;
      });
    }
    _validate(value, name) {
      const result = validateHelp(this._validators, 0, value, Schema);
      if (result instanceof Reject) {
        return result.withMoreInfo(name, value);
      }
      if (result instanceof Break) {
        return newValue.value;
      }
      return result;
    }
    validate(value, name) {
      const newValue = this._validate(value, name);
      if (newValue instanceof Reject) {
        throw newValue.toError();
      }
      return newValue;
    }
    key(key, valueSchema) {
      const name = (typeof key === 'number') ? `[${key}]` : `.${key}`;
      return sv._last({
        type: 'if',
        then: value => {
          const child = value[key];
          return valueSchema._validate(child, name);
        }
      });
    }
    flatten(toKeySchemas) {
      return this.map(value => {
        const newItems = [];
        for (let schema of toKeySchemas(value)) {
          const result = schema._validate(value);
          if (result instanceof Reject) {
            return result;
          }
          newItems.push(result);
        }
        return newItems;
      });
    }
  }

  plugins.forEach(plugin => addPlugin(Schema.prototype, plugin));
  // empty schema instance
  const sv = new Schema();
  return sv;
}

function wrapValidate(f, Schema) {
  if (!Schema) {
    throw new Error('Schema not found');
  }
  return value => {
    const newValue = f(value);
    if (newValue instanceof Schema) {
      return newValue._validate(value);
    }
    return newValue;
  };
}

function validateHelp(validators, i, value, Schema) {
  if (i >= validators.length) {
    return value;
  }
  const validator = validators[i];
  if (validator.type === 'if') {
    const valid = validator.if_ ? validator.if_(value) : true;
    if (valid) {
      const newValue = wrapValidate(validator.then || (value => value), Schema)(value);
      if (newValue instanceof Reject) {
        return newValue;
      } else if (newValue instanceof Break) {
        return newValue.value;
      }
      return validateHelp(validators, i + 1, newValue, Schema);
    } else {
      return validator.else_(value);
    }
  }
  throw 'unexpected type';
}

function addPlugin(prototype, plugin) {
  Object.keys(plugin).forEach(key => {
    if (prototype[key]) {
      throw new Error(`PluginError: Function ${key} is already defined.`);
    }
    const f = plugin[key];
    if (typeof f !== 'function') {
      throw new Error(`PluginError: Plugin ${key} is mulformed. Value should be a function.`);
    }
    prototype[key] = f;
  });
}

module.exports = {
  create: create,
  SchemaValidatorError: SchemaValidatorError,
};
<|endoftext|>


<commit_before>import {Matrix, WrapperMatrix2D} from './index';

import LuDecomposition from './dc/lu';
import QrDecomposition from './dc/qr';
import SingularValueDecomposition from './dc/svd';

/**
 * Computes the inverse of a Matrix
 * @param {Matrix} matrix
 * @param {boolean} [useSVD=false]
 * @return {Matrix}
 */
export function inverse(matrix, useSVD = false) {
    matrix = WrapperMatrix2D.checkMatrix(matrix);
    if (useSVD) {
        return SingularValueDecomposition(matrix).inverse();
    } else {
        return solve(matrix, Matrix.eye(matrix.rows));
    }
}

/**
 *
 * @param {Matrix} leftHandSide
 * @param {Matrix} rightHandSide
 * @param {boolean} [useSVD = false]
 * @return {Matrix}
 */
export function solve(leftHandSide, rightHandSide, useSVD = false) {
    leftHandSide = WrapperMatrix2D.checkMatrix(leftHandSide);
    rightHandSide = WrapperMatrix2D.checkMatrix(rightHandSide);
    if (useSVD) {
        return SingularValueDecomposition(leftHandSide).solve(rightHandSide);
    } else {
        return leftHandSide.isSquare() ? new LuDecomposition(leftHandSide).solve(rightHandSide) : new QrDecomposition(leftHandSide).solve(rightHandSide);
    }
}
<commit_msg>fix: bug with SVD<commit_after>import {Matrix, WrapperMatrix2D} from './index';

import LuDecomposition from './dc/lu';
import QrDecomposition from './dc/qr';
import SingularValueDecomposition from './dc/svd';

/**
 * Computes the inverse of a Matrix
 * @param {Matrix} matrix
 * @param {boolean} [useSVD=false]
 * @return {Matrix}
 */
export function inverse(matrix, useSVD = false) {
    matrix = WrapperMatrix2D.checkMatrix(matrix);
    if (useSVD) {
        return new SingularValueDecomposition(matrix).inverse();
    } else {
        return solve(matrix, Matrix.eye(matrix.rows));
    }
}

/**
 *
 * @param {Matrix} leftHandSide
 * @param {Matrix} rightHandSide
 * @param {boolean} [useSVD = false]
 * @return {Matrix}
 */
export function solve(leftHandSide, rightHandSide, useSVD = false) {
    leftHandSide = WrapperMatrix2D.checkMatrix(leftHandSide);
    rightHandSide = WrapperMatrix2D.checkMatrix(rightHandSide);
    if (useSVD) {
        return new SingularValueDecomposition(leftHandSide).solve(rightHandSide);
    } else {
        return leftHandSide.isSquare() ? new LuDecomposition(leftHandSide).solve(rightHandSide) : new QrDecomposition(leftHandSide).solve(rightHandSide);
    }
}
<|endoftext|>


<commit_before>'use strict';
var Promise = require('promise');
var animationFramePolyFill = require('./utils/request-anim-polyfill');
/**
 * Scroll class.
 * @class Scroll
 * @param {object} options - Options to pass
 * @param {HTMLElement} options.el - The element to apply scroll to
 */
var Scroll = function (options) {
    this.initialize(options);
};
Scroll.prototype = {

    /**
     * When the scroll is instantiated.
     * @memberOf Scroll
     */
    initialize: function (options) {

        this.options = options;

        if (!options.el) {
            console.error('Scroll error: element passed to Scroll constructor is ' + options.el + '! Bailing...');
        }

        this.setup();
    },

    /**
     * Sets up the polyfill for requestAnimationFrame/cancelAnimationFrame.
     * @memberOf Scroll
     */
    setup: function () {
        animationFramePolyFill();
    },

    /**
     * Scrolls the element until it's scroll properties match the coordinates provided.
     * @param {Number} x - The pixel along the horizontal axis of the element that you want displayed in the upper left.
     * @param {Number} y - The pixel along the vertical axis of the element that you want displayed in the upper left.
     * @param {Object} [options] - Scroll options
     * @param {Number} [options.duration]- The amount of time for the animation
     * @param {string} [options.easing] - The easing function to use
     * @memberOf Scroll
     * @return {Promise}
     */
    to: function (x, y, options) {
        var elem = this.options.el,
            fromY = elem.scrollTop,
            fromX = elem.scrollLeft;
        // defaults
        options = options || {};
        options.duration = options.duration || 400;

        return new Promise(function (resolve) {
            this._scroll(elem, fromY, y, 'scrollTop', Date.now(), options.duration, this._getEasing(options.easing), resolve);
        }.bind(this));
    },

    /**
     * Scroll to an element.
     * @param {HTMLElement} el - The element to scroll to.
     * @param {Object} [options] - The scroll options
     */
    toElement: function (el, options) {
        var container = this.options.el,
            currentContainerScrollYPos = 0,
            elementScrollYPos =  el ? el.offsetTop : 0,
            errorMsg;

        // if the container is the document body or document itself, we'll
        // need a different set of coordinates for accuracy
        if (container === document.body) {
            // using pageYOffset for cross-browser compatibility
            currentContainerScrollYPos = window.pageYOffset;
            // must add containers scroll y position to ensure an absolute value that does not change
            elementScrollYPos = el.getBoundingClientRect().top + currentContainerScrollYPos;
        }
        if (!el) {
            errorMsg = 'The element passed to Scroll.toElement() was undefined';
            console.error(errorMsg);
            return Promise.reject(new Error(errorMsg));
        } else if (!container.contains(el)) {
            errorMsg = 'Scroll.toElement() was passed an element that does not exist inside the scroll container';
            console.warn(errorMsg);
            return Promise.reject(new Error(errorMsg));
        } else {
            return this.to(0, elementScrollYPos, options);
        }
    },

    /**
     * Does a bit of calculating and scrolls an element.
     * @param {HTMLElement} el - The element to be scrolled
     * @param {Number} from - The number of where to scroll from
     * @param {Number} to - The number of where to scroll to
     * @param {string} prop - The property to animate
     * @param {Number} startTime - The timestamp of when the animation should start
     * @param {Number} duration - The amount of time for the animation
     * @param {Function} easeFunc - The easing function to use
     * @param [callback]
     * @private
     * @memberOf Scroll
     */
    _scroll: function (el, from, to, prop, startTime, duration, easeFunc, callback) {
        requestAnimationFrame(function () {
            var currentTime = Date.now(),
                time = Math.min(1, ((currentTime - startTime) / duration));

            if (from === to) {
                return callback ? callback() : null;
            }

            this._moveElement(prop, (easeFunc(time) * (to - from)) + from);

            /* prevent scrolling, if already there, or at end */
            if (time < 1) {
                this._scroll(el, el[prop], to, prop, startTime, duration, easeFunc, callback);
            } else if (callback) {
                callback();
            }
        }.bind(this));
    },

    /**
     * Sets element's property to a value.
     * @param prop
     * @param value
     * @private
     */
    _moveElement: function (prop, value) {
        var el = this.options.el;

        el[prop] = value;

        // scroll the html element also for cross-browser compatibility
        // (ie. silly browsers like IE who need the html element to scroll too)
        if (el === document.body) {
            document.documentElement[prop] = value;
        }
    },

    /**
     * Gets an easing function based on supplied easing string.
     * @param {String} easing - The easing id
     * @returns {Function} - Returns the easing function
     * @private
     * @memberOf Scroll
     */
    _getEasing: function (easing) {
        var defaultEasing = 'linear',
            easeFunc = this._easing[easing || defaultEasing];
        if (!easeFunc) {
            console.warn('Scroll error: scroller does not support an easing option of ' + easing + '. Using "' + defaultEasing + '" instead');
            easeFunc = this._easing[easing];
        }
        return easeFunc;
    },

    /**
     * Use this to clean up the DOM when done.
     * @memberOf Scroll
     */
    destroy: function () {},

    /**
     * Easing functions.
     */
    _easing: {
        linear: function (t) { return t },
        easeInQuad: function (t) { return t*t },
        easeOutQuad: function (t) { return t*(2-t) },
        easeInOutQuad: function (t) { return t<.5 ? 2*t*t : -1+(4-2*t)*t },
        easeInCubic: function (t) { return t*t*t },
        easeOutCubic: function (t) { return (--t)*t*t+1 },
        easeInOutCubic: function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 },
        easeInQuart: function (t) { return t*t*t*t },
        easeOutQuart: function (t) { return 1-(--t)*t*t*t },
        easeInOutQuart: function (t) { return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t },
        easeInQuint: function (t) { return t*t*t*t*t },
        easeOutQuint: function (t) { return 1+(--t)*t*t*t*t },
        easeInOutQuint: function (t) { return t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t }
    }

};

module.exports = Scroll;<commit_msg>add getDocumentElement method<commit_after>'use strict';
var Promise = require('promise');
var animationFramePolyFill = require('./utils/request-anim-polyfill');
/**
 * Scroll class.
 * @class Scroll
 * @param {object} options - Options to pass
 * @param {HTMLElement} options.el - The element to apply scroll to
 */
var Scroll = function (options) {
    this.initialize(options);
};
Scroll.prototype = {

    /**
     * When the scroll is instantiated.
     * @memberOf Scroll
     */
    initialize: function (options) {

        this.options = options;

        if (!options.el) {
            console.error('Scroll error: element passed to Scroll constructor is ' + options.el + '! Bailing...');
        }

        this.setup();
    },

    /**
     * Sets up the polyfill for requestAnimationFrame/cancelAnimationFrame.
     * @memberOf Scroll
     */
    setup: function () {
        animationFramePolyFill();
    },

    /**
     * Scrolls the element until it's scroll properties match the coordinates provided.
     * @param {Number} x - The pixel along the horizontal axis of the element that you want displayed in the upper left.
     * @param {Number} y - The pixel along the vertical axis of the element that you want displayed in the upper left.
     * @param {Object} [options] - Scroll options
     * @param {Number} [options.duration]- The amount of time for the animation
     * @param {string} [options.easing] - The easing function to use
     * @memberOf Scroll
     * @return {Promise}
     */
    to: function (x, y, options) {
        var elem = this.options.el,
            fromY = elem.scrollTop,
            fromX = elem.scrollLeft;
        // defaults
        options = options || {};
        options.duration = options.duration || 400;

        return new Promise(function (resolve) {
            this._scroll(elem, fromY, y, 'scrollTop', Date.now(), options.duration, this._getEasing(options.easing), resolve);
        }.bind(this));
    },

    /**
     * Returns document element
     * @returns {HTMLDocument}
     */
    getDocumentElement: function () {
        return document;
    },

    /**
     * Scroll to an element.
     * @param {HTMLElement} el - The element to scroll to.
     * @param {Object} [options] - The scroll options
     */
    toElement: function (el, options) {
        var container = this.options.el,
            currentContainerScrollYPos = 0,
            elementScrollYPos =  el ? el.offsetTop : 0,
            errorMsg;

        // if the container is the document body or document itself, we'll
        // need a different set of coordinates for accuracy
        if (container === document.body) {
            // using pageYOffset for cross-browser compatibility
            currentContainerScrollYPos = window.pageYOffset;
            // must add containers scroll y position to ensure an absolute value that does not change
            elementScrollYPos = el.getBoundingClientRect().top + currentContainerScrollYPos;
        }
        if (!el) {
            errorMsg = 'The element passed to Scroll.toElement() was undefined';
            console.error(errorMsg);
            return Promise.reject(new Error(errorMsg));
        } else if (!container.contains(el)) {
            errorMsg = 'Scroll.toElement() was passed an element that does not exist inside the scroll container';
            console.warn(errorMsg);
            return Promise.reject(new Error(errorMsg));
        } else {
            return this.to(0, elementScrollYPos, options);
        }
    },

    /**
     * Does a bit of calculating and scrolls an element.
     * @param {HTMLElement} el - The element to be scrolled
     * @param {Number} from - The number of where to scroll from
     * @param {Number} to - The number of where to scroll to
     * @param {string} prop - The property to animate
     * @param {Number} startTime - The timestamp of when the animation should start
     * @param {Number} duration - The amount of time for the animation
     * @param {Function} easeFunc - The easing function to use
     * @param [callback]
     * @private
     * @memberOf Scroll
     */
    _scroll: function (el, from, to, prop, startTime, duration, easeFunc, callback) {
        requestAnimationFrame(function () {
            var currentTime = Date.now(),
                time = Math.min(1, ((currentTime - startTime) / duration));

            if (from === to) {
                return callback ? callback() : null;
            }

            this._moveElement(prop, (easeFunc(time) * (to - from)) + from);

            /* prevent scrolling, if already there, or at end */
            if (time < 1) {
                this._scroll(el, el[prop], to, prop, startTime, duration, easeFunc, callback);
            } else if (callback) {
                callback();
            }
        }.bind(this));
    },

    /**
     * Sets element's property to a value.
     * @param prop
     * @param value
     * @private
     */
    _moveElement: function (prop, value) {
        var el = this.options.el;

        el[prop] = value;

        // scroll the html element also for cross-browser compatibility
        // (ie. silly browsers like IE who need the html element to scroll too)
        if (el === document.body) {
            this.getDocumentElement().documentElement[prop] = value;
        }
    },

    /**
     * Gets an easing function based on supplied easing string.
     * @param {String} easing - The easing id
     * @returns {Function} - Returns the easing function
     * @private
     * @memberOf Scroll
     */
    _getEasing: function (easing) {
        var defaultEasing = 'linear',
            easeFunc = this._easing[easing || defaultEasing];
        if (!easeFunc) {
            console.warn('Scroll error: scroller does not support an easing option of ' + easing + '. Using "' + defaultEasing + '" instead');
            easeFunc = this._easing[easing];
        }
        return easeFunc;
    },

    /**
     * Use this to clean up the DOM when done.
     * @memberOf Scroll
     */
    destroy: function () {},

    /**
     * Easing functions.
     */
    _easing: {
        linear: function (t) { return t },
        easeInQuad: function (t) { return t*t },
        easeOutQuad: function (t) { return t*(2-t) },
        easeInOutQuad: function (t) { return t<.5 ? 2*t*t : -1+(4-2*t)*t },
        easeInCubic: function (t) { return t*t*t },
        easeOutCubic: function (t) { return (--t)*t*t+1 },
        easeInOutCubic: function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 },
        easeInQuart: function (t) { return t*t*t*t },
        easeOutQuart: function (t) { return 1-(--t)*t*t*t },
        easeInOutQuart: function (t) { return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t },
        easeInQuint: function (t) { return t*t*t*t*t },
        easeOutQuint: function (t) { return 1+(--t)*t*t*t*t },
        easeInOutQuint: function (t) { return t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t }
    }

};

module.exports = Scroll;<|endoftext|>