<commit_before>var Template = require('./template'),
	api = require('./api'),
	Context = require('./context');
/**
 * use current customTag content
 * @return {[type]} [description]
 */
Template.prototype.__yield = function() {
	return this.exec({
		dom: function(context) {
			var templ = context.data.opts && context.data.opts.__yield;
			if (!templ)
				return;
			return templ.call(this, context);
		},
		string: function(context, descriptor) {
			var templ = context.data.opts && context.data.opts.__yield;
			if (!templ)
				return;
			descriptor.children += templ.toHTMLString(context);
		}
	});
};

var customTagEngine = {
	dom: function(context, args) {
		var ctx = new Context({
			opts: args[0]
		}, context);
		var ctr = args[1].toContainer(ctx).appendTo(this);
		ctr.context = ctx;
	},
	string: function(context, descriptor, args) {
		descriptor.children += args[1].toHTMLString(new Context({
			opts: args[0]
		}, context));
	},
	twopass: {
		first: function(context, args) {
			(context.children = context.children || []).push(new Context({
				opts: args[0]
			}, context));
		},
		second: function(context, descriptor, args) {
			descriptor.children += args[1].toHTMLString(context.children.shift());
		}
	}
};

/**
 * addCustomTag in specified api.
 * @param {[type]} apiName        [description]
 * @param {[type]} tagName        [description]
 * @param {[type]} defaultAttrMap [description]
 * @param {[type]} templ          [description]
 */
module.exports = function(apiName, tagName, defaultAttrMap, templ) {
	var space = api[apiName] = api[apiName] || {};
	space[tagName] = function(attrMap, __yield) {
		// copy default to attrMap
		for (var i in defaultAttrMap)
			if (typeof attrMap[i] === 'undefined')
				attrMap[i] = defaultAttrMap[i];
		attrMap.__yield = __yield;
		return this.exec(customTagEngine, [attrMap, templ]);
	}
	return this;
};
<commit_msg>correct comments in custom-tags<commit_after>var Template = require('./template'),
	api = require('./api'),
	Context = require('./context');
/**
 * use current customTag content
 * @return {Template} current template
 */
Template.prototype.__yield = function() {
	return this.exec({
		dom: function(context) {
			var templ = context.data.opts && context.data.opts.__yield;
			if (!templ)
				return;
			return templ.call(this, context);
		},
		string: function(context, descriptor) {
			var templ = context.data.opts && context.data.opts.__yield;
			if (!templ)
				return;
			descriptor.children += templ.toHTMLString(context);
		}
	});
};

var customTagEngine = {
	dom: function(context, args) {
		var ctx = new Context({
			opts: args[0]
		}, context);
		var ctr = args[1].toContainer(ctx).appendTo(this);
		ctr.context = ctx;
	},
	string: function(context, descriptor, args) {
		descriptor.children += args[1].toHTMLString(new Context({
			opts: args[0]
		}, context));
	},
	twopass: {
		first: function(context, args) {
			(context.children = context.children || []).push(new Context({
				opts: args[0]
			}, context));
		},
		second: function(context, descriptor, args) {
			descriptor.children += args[1].toHTMLString(context.children.shift());
		}
	}
};

/**
 * addCustomTag in specified api.
 * @param {[type]} apiName        [description]
 * @param {[type]} tagName        [description]
 * @param {[type]} defaultAttrMap [description]
 * @param {[type]} templ          [description]
 */
module.exports = function(apiName, tagName, defaultAttrMap, templ) {
	var space = api[apiName] = api[apiName] || {};
	space[tagName] = function(attrMap, __yield) {
		// copy default to attrMap
		for (var i in defaultAttrMap)
			if (typeof attrMap[i] === 'undefined')
				attrMap[i] = defaultAttrMap[i];
		attrMap.__yield = __yield;
		return this.exec(customTagEngine, [attrMap, templ]);
	}
	return this;
};
<|endoftext|>


<commit_before>/*
---
name: BehaviorAPI
description: HTML getters for Behavior's API model.
requires: [Core/Class, /Element.Data]
provides: [BehaviorAPI]
...
*/

(function(){
	//see Docs/BehaviorAPI.md for documentation of public methods.

	var reggy = /[^a-z0-9\-]/gi;

	window.BehaviorAPI = new Class({
		element: null,
		prefix: '',
		defaults: {},

		initialize: function(element, prefix){
			this.element = element;
			this.prefix = prefix.toLowerCase().replace('.', '-', 'g').replace(reggy, '');
		},

		/******************
		 * PUBLIC METHODS
		 ******************/

		get: function(/* name[, name, name, etc] */){
			if (arguments.length > 1) return this._getObj(Array.from(arguments));
			return this._getValue(arguments[0]);
		},

		getAs: function(/*returnType, name, defaultValue OR {name: returnType, name: returnType, etc}*/){
			if (typeOf(arguments[0]) == 'object') return this._getValuesAs.apply(this, arguments);
			return this._getValueAs.apply(this, arguments);
		},

		require: function(/* name[, name, name, etc] */){
			for (var i = 0; i < arguments.length; i++){
				if (this._getValue(arguments[i]) == undefined) throw new Error('Could not retrieve ' + this.prefix + '-' + arguments[i] + ' option from element.');
			}
			return this;
		},

		requireAs: function(returnType, name /* OR {name: returnType, name: returnType, etc}*/){
			var val;
			if (typeOf(arguments[0]) == 'object'){
				for (var objName in arguments[0]){
					val = this._getValueAs(arguments[0][objName], objName);
					if (val === undefined || val === null) throw new Error("Could not retrieve " + this.prefix + '-' + objName + " option from element.");
				}
			} else {
				val = this._getValueAs(returnType, name);
				if (val === undefined || val === null) throw new Error("Could not retrieve " + this.prefix + '-' + name + " option from element.");
			}
			return this;
		},

		setDefault: function(name, value /* OR {name: value, name: value, etc }*/){
			if (typeOf(arguments[0]) == 'object'){
				for (var objName in arguments[0]){
					this.setDefault(objName, arguments[0][objName]);
				}
				return;
			}
			name = name.camelCase();
			this.defaults[name] = value;
			if (this._getValue(name) == null){
				var options = this._getOptions();
				options[name] = value;
			}
			return this;
		},

		refreshAPI: function(){
			delete this.options;
			this.setDefault(this.defaults);
			return;
		},

		/******************
		 * PRIVATE METHODS
		 ******************/

		//given an array of names, returns an object of key/value pairs for each name
		_getObj: function(names){
			var obj = {};
			names.each(function(name){
				var value = this._getValue(name);
				if (value !== undefined) obj[name] = value;
			}, this);
			return obj;
		},
		//gets the data-behaviorname-options object and parses it as JSON
		_getOptions: function(){
			if (!this.options){
				var options = this.element.getData(this.prefix + '-options', '{}');
				if (options && options[0] != '{') options = '{' + options + '}';
				var isSecure = JSON.isSecure(options);
				if (!isSecure) throw new Error('warning, options value for element is not parsable, check your JSON format for quotes, etc.');
				this.options = isSecure ? JSON.decode(options) : {};
				for (option in this.options) {
					this.options[option.camelCase()] = this.options[option];
				}
			}
			return this.options;
		},
		//given a name (string) returns the value for it
		_getValue: function(name){
			name = name.camelCase();
			var options = this._getOptions();
			if (!options.hasOwnProperty(name)){
				var inline = this.element.getData(this.prefix + '-' + name.hyphenate());
				if (inline) options[name] = inline;
			}
			return options[name];
		},
		//given a Type and a name (string) returns the value for it coerced to that type if possible
		//else returns the defaultValue or null
		_getValueAs: function(returnType, name, defaultValue){
			var value = this._getValue(name);
			if (value == null || value == undefined) return defaultValue;
			var coerced = this._coerceFromString(returnType, value);
			if (coerced == null) throw new Error("Could not retrieve value '" + name + "' as the specified type. Its value is: " + value);
			return coerced;
		},
		//given an object of name/Type pairs, returns those as an object of name/value (as specified Type) pairs
		_getValuesAs: function(obj){
			var returnObj = {};
			for (var name in obj){
				returnObj[name] = this._getValueAs(obj[name], name);
			}
			return returnObj;
		},
		//attempts to run a value through the JSON parser. If the result is not of that type returns null.
		_coerceFromString: function(toType, value){
			if (typeOf(value) == 'string' && toType != String){
				if (JSON.isSecure(value)) value = JSON.decode(value);
			}
			if (instanceOf(value, toType)) return value;
			return null;
		}
	});

})();<commit_msg>Fixes #10<commit_after>/*
---
name: BehaviorAPI
description: HTML getters for Behavior's API model.
requires: [Core/Class, /Element.Data]
provides: [BehaviorAPI]
...
*/

(function(){
	//see Docs/BehaviorAPI.md for documentation of public methods.

	var reggy = /[^a-z0-9\-]/gi;

	window.BehaviorAPI = new Class({
		element: null,
		prefix: '',
		defaults: {},

		initialize: function(element, prefix){
			this.element = element;
			this.prefix = prefix.toLowerCase().replace('.', '-', 'g').replace(reggy, '');
		},

		/******************
		 * PUBLIC METHODS
		 ******************/

		get: function(/* name[, name, name, etc] */){
			if (arguments.length > 1) return this._getObj(Array.from(arguments));
			return this._getValue(arguments[0]);
		},

		getAs: function(/*returnType, name, defaultValue OR {name: returnType, name: returnType, etc}*/){
			if (typeOf(arguments[0]) == 'object') return this._getValuesAs.apply(this, arguments);
			return this._getValueAs.apply(this, arguments);
		},

		require: function(/* name[, name, name, etc] */){
			for (var i = 0; i < arguments.length; i++){
				if (this._getValue(arguments[i]) == undefined) throw new Error('Could not retrieve ' + this.prefix + '-' + arguments[i] + ' option from element.');
			}
			return this;
		},

		requireAs: function(returnType, name /* OR {name: returnType, name: returnType, etc}*/){
			var val;
			if (typeOf(arguments[0]) == 'object'){
				for (var objName in arguments[0]){
					val = this._getValueAs(arguments[0][objName], objName);
					if (val === undefined || val === null) throw new Error("Could not retrieve " + this.prefix + '-' + objName + " option from element.");
				}
			} else {
				val = this._getValueAs(returnType, name);
				if (val === undefined || val === null) throw new Error("Could not retrieve " + this.prefix + '-' + name + " option from element.");
			}
			return this;
		},

		setDefault: function(name, value /* OR {name: value, name: value, etc }*/){
			if (typeOf(arguments[0]) == 'object'){
				for (var objName in arguments[0]){
					this.setDefault(objName, arguments[0][objName]);
				}
				return;
			}
			name = name.camelCase();
			this.defaults[name] = value;
			if (this._getValue(name) == null){
				var options = this._getOptions();
				options[name] = value;
			}
			return this;
		},

		refreshAPI: function(){
			delete this.options;
			this.setDefault(this.defaults);
			return;
		},

		/******************
		 * PRIVATE METHODS
		 ******************/

		//given an array of names, returns an object of key/value pairs for each name
		_getObj: function(names){
			var obj = {};
			names.each(function(name){
				var value = this._getValue(name);
				if (value !== undefined) obj[name] = value;
			}, this);
			return obj;
		},
		//gets the data-behaviorname-options object and parses it as JSON
		_getOptions: function(){
			if (!this.options){
				var options = this.element.getData(this.prefix + '-options', '{}');
				if (options && options.substring(0,1) != '{') options = '{' + options + '}';
				var isSecure = JSON.isSecure(options);
				if (!isSecure) throw new Error('warning, options value for element is not parsable, check your JSON format for quotes, etc.');
				this.options = isSecure ? JSON.decode(options) : {};
				for (option in this.options) {
					this.options[option.camelCase()] = this.options[option];
				}
			}
			return this.options;
		},
		//given a name (string) returns the value for it
		_getValue: function(name){
			name = name.camelCase();
			var options = this._getOptions();
			if (!options.hasOwnProperty(name)){
				var inline = this.element.getData(this.prefix + '-' + name.hyphenate());
				if (inline) options[name] = inline;
			}
			return options[name];
		},
		//given a Type and a name (string) returns the value for it coerced to that type if possible
		//else returns the defaultValue or null
		_getValueAs: function(returnType, name, defaultValue){
			var value = this._getValue(name);
			if (value == null || value == undefined) return defaultValue;
			var coerced = this._coerceFromString(returnType, value);
			if (coerced == null) throw new Error("Could not retrieve value '" + name + "' as the specified type. Its value is: " + value);
			return coerced;
		},
		//given an object of name/Type pairs, returns those as an object of name/value (as specified Type) pairs
		_getValuesAs: function(obj){
			var returnObj = {};
			for (var name in obj){
				returnObj[name] = this._getValueAs(obj[name], name);
			}
			return returnObj;
		},
		//attempts to run a value through the JSON parser. If the result is not of that type returns null.
		_coerceFromString: function(toType, value){
			if (typeOf(value) == 'string' && toType != String){
				if (JSON.isSecure(value)) value = JSON.decode(value);
			}
			if (instanceOf(value, toType)) return value;
			return null;
		}
	});

})();<|endoftext|>


<commit_before>/*global QUnit, canPolyfill, _currentEvaluatingScript */
/*jshint maxstatements:false */

(function(module, test, skip) {
  "use strict";

  var hasNativeSupport = "currentScript" in document && canPolyfill;

  // Synchronous execution required here outside of the test callback context
  var polyfillResultSync;
  try {
    polyfillResultSync = _currentEvaluatingScript();
  }
  catch (e) {
    // Oh well....
  }

  var nativeResultSync;
  if (hasNativeSupport) {
    try {
      nativeResultSync = document.currentScript;
    }
    catch (e) {
      // Oh well....
    }
  }

  module("`_currentEvaluatingScript`");

  test("Is defined", function(assert) {
    assert.expect(1);
    assert.strictEqual(typeof _currentEvaluatingScript, "function", "Should be an exposed function");
  });

  module("`_currentEvaluatingScript()` follows the spec");

  (canPolyfill ? test : skip)("1 - When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(1);

    var polyfillResultIsNonNullObject = polyfillResultSync != null && typeof polyfillResultSync === "object";

    assert.strictEqual(polyfillResultIsNonNullObject, true, "`_currentEvaluatingScript()` should return a non-`null` object");
  });

  (canPolyfill ? test : skip)("2 - When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(2);

    var polyfillResultIsNonNullObject = polyfillResultSync != null && typeof polyfillResultSync === "object";
    var polyfillResultNodeName = polyfillResultIsNonNullObject ? polyfillResultSync.nodeName : undefined;

    assert.strictEqual(polyfillResultIsNonNullObject, true, "`_currentEvaluatingScript()` should return a non-`null` object");
    assert.strictEqual(polyfillResultNodeName, "SCRIPT", "`_currentEvaluatingScript()` should return a `script` node");
  });

  (canPolyfill ? test : skip)("3 - When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(3);

    var polyfillResultIsNonNullObject = polyfillResultSync != null && typeof polyfillResultSync === "object";
    var polyfillResultNodeName = polyfillResultIsNonNullObject ? polyfillResultSync.nodeName : undefined;
    var polyfillResultHasSrcAttr = polyfillResultIsNonNullObject && !!polyfillResultSync.hasAttribute ? polyfillResultSync.hasAttribute("src") : false;

    assert.strictEqual(polyfillResultIsNonNullObject, true, "`_currentEvaluatingScript()` should return a non-`null` object");
    assert.strictEqual(polyfillResultNodeName, "SCRIPT", "`_currentEvaluatingScript()` should return a `script` node");
    assert.strictEqual(polyfillResultHasSrcAttr, true, "`_currentEvaluatingScript()` should return a `script` node with a `src` attribute");
  });

  (canPolyfill ? test : skip)("3.1 - When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(3);

    var polyfillResultIsNonNullObject = polyfillResultSync != null && typeof polyfillResultSync === "object";
    var polyfillResultNodeName = polyfillResultIsNonNullObject ? polyfillResultSync.nodeName : undefined;

    assert.strictEqual(polyfillResultIsNonNullObject, true, "`_currentEvaluatingScript()` should return a non-`null` object");
    assert.strictEqual(polyfillResultNodeName, "SCRIPT", "`_currentEvaluatingScript()` should return a `script` node");
    assert.strictEqual(polyfillResultSync.outerHTML, "<script></script>", "`_currentEvaluatingScript()` should return a `script` node with some outer HTML");
  });

  (canPolyfill ? test : skip)("3.2 - When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(3);

    var polyfillResultIsNonNullObject = polyfillResultSync != null && typeof polyfillResultSync === "object";
    var polyfillResultNodeName = polyfillResultIsNonNullObject ? polyfillResultSync.nodeName : undefined;

    assert.strictEqual(polyfillResultIsNonNullObject, true, "`_currentEvaluatingScript()` should return a non-`null` object");
    assert.strictEqual(polyfillResultNodeName, "SCRIPT", "`_currentEvaluatingScript()` should return a `script` node");
    assert.strictEqual(polyfillResultSync.text, "Script inner text", "`_currentEvaluatingScript()` should return a `script` node with some inner text");
  });

  (canPolyfill ? test : skip)("4 - When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(4);

    var polyfillResultIsNonNullObject = polyfillResultSync != null && typeof polyfillResultSync === "object";
    var polyfillResultNodeName = polyfillResultIsNonNullObject ? polyfillResultSync.nodeName : undefined;
    var polyfillResultHasSrcAttr = polyfillResultIsNonNullObject && !!polyfillResultSync.hasAttribute ? polyfillResultSync.hasAttribute("src") : false;
    var polyfillResultSrc = polyfillResultIsNonNullObject ? (polyfillResultHasSrcAttr ? polyfillResultSync.src : null) : undefined;
    var polyfillResultSrcSuffix = polyfillResultSrc ? polyfillResultSrc.replace(/\?.*$/, "").slice(-9).toLowerCase() : polyfillResultSrc;

    assert.strictEqual(polyfillResultIsNonNullObject, true, "`_currentEvaluatingScript()` should return a non-`null` object");
    assert.strictEqual(polyfillResultNodeName, "SCRIPT", "`_currentEvaluatingScript()` should return a `script` node");
    assert.strictEqual(polyfillResultHasSrcAttr, true, "`_currentEvaluatingScript()` should return a `script` node with a `src` attribute");
    assert.strictEqual(polyfillResultSrcSuffix, "/tests.js", "`_currentEvaluatingScript().src` should return the test script's path");
  });

  (canPolyfill ? test : skip)("When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(4);

    var polyfillResultIsNonNullObject = polyfillResultSync != null && typeof polyfillResultSync === "object";
    var polyfillResultNodeName = polyfillResultIsNonNullObject ? polyfillResultSync.nodeName : undefined;
    var polyfillResultHasSrcAttr = polyfillResultIsNonNullObject && !!polyfillResultSync.hasAttribute ? polyfillResultSync.hasAttribute("src") : false;
    var polyfillResultSrc = polyfillResultIsNonNullObject ? (polyfillResultHasSrcAttr ? polyfillResultSync.src : null) : undefined;
    var polyfillResultSrcSuffix = polyfillResultSrc ? polyfillResultSrc.replace(/\?.*$/, "").slice(-9).toLowerCase() : polyfillResultSrc;

    assert.strictEqual(polyfillResultIsNonNullObject, true, "`_currentEvaluatingScript()` should return a non-`null` object");
    assert.strictEqual(polyfillResultNodeName, "SCRIPT", "`_currentEvaluatingScript()` should return a `script` node");
    assert.strictEqual(polyfillResultHasSrcAttr, true, "`_currentEvaluatingScript()` should return a `script` node with a `src` attribute");
    assert.strictEqual(polyfillResultSrcSuffix, "/tests.js", "`_currentEvaluatingScript().src` should return the test script's path");
  });

  (canPolyfill ? test : skip)("When invoked outside of a script's synchronous evaluation (so, asynchronously)", function(assert) {
    assert.expect(1);

    // While QUnit currently invokes these test callback functions asynchronously,
    // I want to guarantee the parameters of this test setup even if that fact
    // changes in the future. As such, let's force asynchrony here.
    var done = assert.async();

    setTimeout(function() {
      assert.strictEqual(_currentEvaluatingScript(), null, "`_currentEvaluatingScript()` should return `null`");
      done();
    }, 13);
  });

  module("Native `document.currentScript` follows the spec");

  (hasNativeSupport ? test : skip)("When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(4);

    var nativeResultIsNonNullObject = nativeResultSync != null && typeof nativeResultSync === "object";
    var nativeResultNodeName = nativeResultIsNonNullObject ? nativeResultSync.nodeName : undefined;
    var nativeResultHasSrcAttr = nativeResultIsNonNullObject && !!nativeResultSync.hasAttribute ? nativeResultSync.hasAttribute("src") : false;
    var nativeResultSrc = nativeResultIsNonNullObject ? (nativeResultHasSrcAttr ? nativeResultSync.src : null) : undefined;
    var nativeResultSrcSuffix = nativeResultSrc ? nativeResultSrc.replace(/\?.*$/, "").slice(-9).toLowerCase() : nativeResultSrc;

    assert.strictEqual(nativeResultIsNonNullObject, true, "`document.currentScript` should return a non-`null` object");
    assert.strictEqual(nativeResultNodeName, "SCRIPT", "`document.currentScript` should return a `script` node");
    assert.strictEqual(nativeResultHasSrcAttr, true, "`document.currentScript` should return a `script` node with a `src` attribute");
    assert.strictEqual(nativeResultSrcSuffix, "/tests.js", "`document.currentScript.src` should return the test script's path");
  });

  (hasNativeSupport ? test : skip)("When invoked outside of a script's synchronous evaluation (so, asynchronously)", function(assert) {
    assert.expect(1);

    // While QUnit currently invokes these test callback functions asynchronously,
    // I want to guarantee the parameters of this test setup even if that fact
    // changes in the future. As such, let's force asynchrony here.
    var done = assert.async();

    setTimeout(function() {
      assert.strictEqual(document.currentScript, null, "`document.currentScript` should return `null`");
      done();
    }, 13);
  });

  module("`_currentEvaluatingScript()` and native `document.currentScript` results match");

  (hasNativeSupport ? test : skip)("When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(1);
    assert.strictEqual(polyfillResultSync, nativeResultSync, "Results should match");
  });

  (hasNativeSupport ? test : skip)("When invoked outside of a script's synchronous evaluation (so, asynchronously)", function(assert) {
    assert.expect(1);
    assert.strictEqual(_currentEvaluatingScript(), document.currentScript, "Results should match");
  });

})(QUnit.module, QUnit.test, QUnit.skip);
<commit_msg>Add '_hasAttribute' helper method to tests to resolve IE7 failures<commit_after>/*global QUnit, canPolyfill, _currentEvaluatingScript */
/*jshint maxstatements:false */

(function(module, test, skip) {
  "use strict";

  var hasNativeSupport = "currentScript" in document && canPolyfill;

  // Synchronous execution required here outside of the test callback context
  var polyfillResultSync;
  try {
    polyfillResultSync = _currentEvaluatingScript();
  }
  catch (e) {
    // Oh well....
  }

  var nativeResultSync;
  if (hasNativeSupport) {
    try {
      nativeResultSync = document.currentScript;
    }
    catch (e) {
      // Oh well....
    }
  }

  // IE<8 does not have the `HTMLElement.prototype.hasAttribute` method
  function _hasAttribute(node, attrName) {
    var mayHaveAttr = (
      node &&
      node.nodeType === 1 &&
      typeof node[attrName] !== "undefined"
    );
    if (mayHaveAttr) {
      if (node.hasAttribute) {
        return node.hasAttribute(attrName);
      }
      return node.getAttribute(attrName) === node[attrName];
    }
    return false;
  }

  module("`_currentEvaluatingScript`");

  test("Is defined", function(assert) {
    assert.expect(1);
    assert.strictEqual(typeof _currentEvaluatingScript, "function", "Should be an exposed function");
  });

  module("`_currentEvaluatingScript()` follows the spec");

  (canPolyfill ? test : skip)("When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(4);

    var polyfillResultIsNonNullObject = polyfillResultSync != null && typeof polyfillResultSync === "object";
    var polyfillResultNodeName = polyfillResultIsNonNullObject ? polyfillResultSync.nodeName : undefined;
    var polyfillResultHasSrcAttr = polyfillResultIsNonNullObject ? _hasAttribute(polyfillResultSync, "src") : false;
    var polyfillResultSrc = polyfillResultIsNonNullObject ? (polyfillResultHasSrcAttr ? polyfillResultSync.src : null) : undefined;
    var polyfillResultSrcSuffix = polyfillResultSrc ? polyfillResultSrc.replace(/\?.*$/, "").slice(-9).toLowerCase() : polyfillResultSrc;

    assert.strictEqual(polyfillResultIsNonNullObject, true, "`_currentEvaluatingScript()` should return a non-`null` object");
    assert.strictEqual(polyfillResultNodeName, "SCRIPT", "`_currentEvaluatingScript()` should return a `script` node");
    assert.strictEqual(polyfillResultHasSrcAttr, true, "`_currentEvaluatingScript()` should return a `script` node with a `src` attribute");
    assert.strictEqual(polyfillResultSrcSuffix, "/tests.js", "`_currentEvaluatingScript().src` should return the test script's path");
  });

  (canPolyfill ? test : skip)("When invoked outside of a script's synchronous evaluation (so, asynchronously)", function(assert) {
    assert.expect(1);

    // While QUnit currently invokes these test callback functions asynchronously,
    // I want to guarantee the parameters of this test setup even if that fact
    // changes in the future. As such, let's force asynchrony here.
    var done = assert.async();

    setTimeout(function() {
      assert.strictEqual(_currentEvaluatingScript(), null, "`_currentEvaluatingScript()` should return `null`");
      done();
    }, 13);
  });

  module("Native `document.currentScript` follows the spec");

  (hasNativeSupport ? test : skip)("When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(4);

    var nativeResultIsNonNullObject = nativeResultSync != null && typeof nativeResultSync === "object";
    var nativeResultNodeName = nativeResultIsNonNullObject ? nativeResultSync.nodeName : undefined;
    var nativeResultHasSrcAttr = nativeResultIsNonNullObject ? _hasAttribute(nativeResultSync, "src") : false;
    var nativeResultSrc = nativeResultIsNonNullObject ? (nativeResultHasSrcAttr ? nativeResultSync.src : null) : undefined;
    var nativeResultSrcSuffix = nativeResultSrc ? nativeResultSrc.replace(/\?.*$/, "").slice(-9).toLowerCase() : nativeResultSrc;

    assert.strictEqual(nativeResultIsNonNullObject, true, "`document.currentScript` should return a non-`null` object");
    assert.strictEqual(nativeResultNodeName, "SCRIPT", "`document.currentScript` should return a `script` node");
    assert.strictEqual(nativeResultHasSrcAttr, true, "`document.currentScript` should return a `script` node with a `src` attribute");
    assert.strictEqual(nativeResultSrcSuffix, "/tests.js", "`document.currentScript.src` should return the test script's path");
  });

  (hasNativeSupport ? test : skip)("When invoked outside of a script's synchronous evaluation (so, asynchronously)", function(assert) {
    assert.expect(1);

    // While QUnit currently invokes these test callback functions asynchronously,
    // I want to guarantee the parameters of this test setup even if that fact
    // changes in the future. As such, let's force asynchrony here.
    var done = assert.async();

    setTimeout(function() {
      assert.strictEqual(document.currentScript, null, "`document.currentScript` should return `null`");
      done();
    }, 13);
  });

  module("`_currentEvaluatingScript()` and native `document.currentScript` results match");

  (hasNativeSupport ? test : skip)("When invoked during a script's synchronous evaluation", function(assert) {
    assert.expect(1);
    assert.strictEqual(polyfillResultSync, nativeResultSync, "Results should match");
  });

  (hasNativeSupport ? test : skip)("When invoked outside of a script's synchronous evaluation (so, asynchronously)", function(assert) {
    assert.expect(1);
    assert.strictEqual(_currentEvaluatingScript(), document.currentScript, "Results should match");
  });

})(QUnit.module, QUnit.test, QUnit.skip);
<|endoftext|>


<commit_before>define([
  "dojo",
  "dijit",
  "dojox",
  "dojox/mobile/_ItemBase"], function(dojo, dijit, dojox){
	// module:
	//		dojox/mobile/ListItem
	// summary:
	//		TODOC

dojo.declare(
	"dojox.mobile.ListItem",
	dojox.mobile._ItemBase,
{
	rightText: "",
	btnClass: "",
	btnClass2: "",
	anchorLabel: false,
	noArrow: false,
	selected: false,
	checked: false,
	rightIconClass: "",
	arrowClass: "mblDomButtonArrow",
	checkClass: "mblDomButtonCheck",

	buildRendering: function(){
		var a = this.anchorNode = dojo.create("A");
		a.className = "mblListItemAnchor";
		var box = this.box = dojo.create("DIV");
		box.className = "mblListItemTextBox";
		if(this.anchorLabel){
			box.style.cursor = "pointer";
		}
		var r = this.srcNodeRef;
		if(r && !this.label){
			this.label = "";
			for(var i = 0, len = r.childNodes.length; i < len; i++){
				var n = r.firstChild;
				if(n.nodeType === 3 && dojo.trim(n.nodeValue) !== ""){
					n.nodeValue = this._cv(n.nodeValue);
					this.labelNode = dojo.create("SPAN");
					this.labelNode.appendChild(n);
					n = this.labelNode;
				}
				box.appendChild(n);
			}
		}
		if(this.label){
			this.labelNode = dojo.create("SPAN", null, box);
		}
		a.appendChild(box);
		if(this.anchorLabel){
			box.style.display = "inline"; // to narrow the text region
		}
		var li = this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("LI");
		li.className = "mblListItem" + (this.selected ? " mblItemSelected" : "");
		li.appendChild(a);
	},

	startup: function(){
		if(this._started){ return; }
		this.inheritParams();
		var parent = this.getParent();
		if(this.moveTo || this.href || this.url || this.clickable){
			if(!this.noArrow && !(parent && parent.stateful)){
				this._setBtnClassAttr(this.arrowClass);
			}
			this.connect(this.anchorNode, "onclick", "onClick");
		}
		if(parent && parent.select){
			this.connect(this.anchorNode, "onclick", "onClick");
		}
		this.set("icon", this.icon);
		this.inherited(arguments);
	},

	onClick: function(e){
		var a = e.currentTarget;
		var li = a.parentNode;
		if(dojo.hasClass(li, "mblItemSelected")){ return; } // already selected
		if(this.anchorLabel){
			for(var p = e.target; p.tagName != "LI"; p = p.parentNode){
				if(p.className == "mblListItemTextBox"){
					dojo.addClass(p, "mblListItemTextBoxSelected");
					setTimeout(function(){
						dojo.removeClass(p, "mblListItemTextBoxSelected");
					}, 1000);
					this.onAnchorLabelClicked(e);
					return;
				}
			}
		}
		var parent = this.getParent();
		if(parent.stateful){
			for(var i = 0, c = li.parentNode.childNodes; i < c.length; i++){
				dojo.removeClass(c[i], "mblItemSelected");
			}
		}else{
			setTimeout(function(){
				dojo.removeClass(li, "mblItemSelected");
			}, 1000);
		}
		if(parent.select){
			if(parent.select === "single"){
				if(!this.checked){
					this.set("checked", true);
				}
			}else if(parent.select === "multiple"){
				this.set("checked", !this.checked);
			}
		}
		dojo.addClass(li, "mblItemSelected");
		this.setTransitionPos(e);
		this.transitionTo(this.moveTo, this.href, this.url, this.scene);
	},

	onAnchorLabelClicked: function(e){
		// Stub function to connect to from your application.
	},

	_setIconAttr: function(icon){
		this.icon = icon;
		var a = this.anchorNode;
		if(this.icon && this.icon.indexOf("mblDomButton") === 0){
			if(!this.iconNode){
				this.iconNode = dojo.create("DIV");
				this.domNode.insertBefore(this.iconNode, a);
			}
			this.iconNode.className = this.icon + " mblLeftButton";
			dojox.mobile.createDomButton(this.iconNode);
			dojo.removeClass(a, "mblListItemAnchorNoIcon");
			a.style.paddingLeft = (this.iconNode.offsetWidth + 11) + "px";
		}else if(this.icon && this.icon != "none"){
			if(!this.iconNode){
				this.iconNode = dojo.create("IMG", {
					className: "mblListItemIcon",
					alt: this.alt
				});
				this.domNode.insertBefore(this.iconNode, a);
			}
			this.iconNode.src = this.icon;
			dojox.mobile.setupIcon(this.iconNode, this.iconPos);
			dojo.removeClass(a, "mblListItemAnchorNoIcon");
		}else{
			dojo.addClass(a, "mblListItemAnchorNoIcon");
		}
	},

	_setBtnClass: function(/*String*/btnClass, /*DomNode*/node, /*String*/className){
		var div;
		if(node){
			if(node.className.match(/(mblDomButton\w+)/)){
				dojo.removeClass(node, RegExp.$1);
			}
			dojo.addClass(node, btnClass);
			div = node;
		}else{
			div = dojo.create("DIV", {className:btnClass+" "+className}, this.anchorNode);
		}
		dojox.mobile.createDomButton(div);
		return div;
	},

	_setBtnClassAttr: function(/*String*/rightIconClass){
		this.rightIconNode = this._setBtnClass(rightIconClass, this.rightIconNode, "mblRightButton");
		this._layoutRightText();
	},

	_setBtnClass2Attr: function(/*String*/rightIconClass){
		this.rightIconNode2 = this._setBtnClass(rightIconClass, this.rightIconNode2, "mblRightButton mblRightButton2");
		dojo.addClass(this.box, "mblListItemTextBox2");
		this._layoutRightText();
	},

	_setCheckedAttr: function(/*Boolean*/checked){
		var parent = this.getParent();
		if(parent.select === "single" && !this.checked && checked){
			dojo.forEach(parent.getChildren(), function(child){
				child.set("checked", false);
			});
		}
		if(!this.checkNode){
			this._setBtnClassAttr(this.checkClass);
			this.checkNode = this.rightIconNode;
		}
		this.checkNode.style.display = checked ? "" : "none";
		dojo.toggleClass(this.domNode, "mblItemChecked", checked);
		if(this.checked !== checked){
			this.getParent().onCheckStateChanged(this, checked);
		}
		this.checked = checked;
		this._layoutRightText();
	},

	_setRightTextAttr: function(/*String*/text){
		this.rightText = text;
		if(!this._rightTextNode){
			this._rightTextNode = dojo.create("DIV", {className:"mblRightText"}, this.anchorNode);
		}
		this._rightTextNode.innerHTML = this._cv(text);
		this._layoutRightText();
	},

	_setLabelAttr: function(/*String*/text){
		this.label = text;
		this.labelNode.innerHTML = this._cv(text);
	},

	_layoutRightText: function(){
		if(this._rightTextNode){
			var w = (this.rightIconNode ? this.rightIconNode.offsetWidth : 0) +
				(this.rightIconNode2 ? this.rightIconNode2.offsetWidth : 0);
			this._rightTextNode.style.right = w + 11 + "px";
		}
	}
});

return dojox.mobile.ListItem;
});
<commit_msg>Fixes #12771 !strict. Added support for programmatic instantiation.<commit_after>define([
  "dojo",
  "dijit",
  "dojox",
  "dojox/mobile/_ItemBase"], function(dojo, dijit, dojox){
	// module:
	//		dojox/mobile/ListItem
	// summary:
	//		TODOC

dojo.declare(
	"dojox.mobile.ListItem",
	dojox.mobile._ItemBase,
{
	rightText: "",
	btnClass: "",
	btnClass2: "",
	anchorLabel: false,
	noArrow: false,
	selected: false,
	checked: false,
	rightIconClass: "",
	arrowClass: "mblDomButtonArrow",
	checkClass: "mblDomButtonCheck",

	buildRendering: function(){
		var a = this.anchorNode = dojo.create("A");
		a.className = "mblListItemAnchor";
		var box = this.box = dojo.create("DIV");
		box.className = "mblListItemTextBox";
		if(this.anchorLabel){
			box.style.cursor = "pointer";
		}
		var r = this.srcNodeRef;
		if(r && !this.label){
			this.label = "";
			for(var i = 0, len = r.childNodes.length; i < len; i++){
				var n = r.firstChild;
				if(n.nodeType === 3 && dojo.trim(n.nodeValue) !== ""){
					n.nodeValue = this._cv(n.nodeValue);
					this.labelNode = dojo.create("SPAN");
					this.labelNode.appendChild(n);
					n = this.labelNode;
				}
				box.appendChild(n);
			}
		}
		if(this.label){
			this.labelNode = dojo.create("SPAN", null, box);
		}
		a.appendChild(box);
		if(this.anchorLabel){
			box.style.display = "inline"; // to narrow the text region
		}
		var li = this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("LI");
		li.className = "mblListItem" + (this.selected ? " mblItemSelected" : "");
		li.appendChild(a);
	},

	startup: function(){
		if(this._started){ return; }
		this.inheritParams();
		var parent = this.getParent();
		if(this.moveTo || this.href || this.url || this.clickable){
			this.connect(this.anchorNode, "onclick", "onClick");
		}
		this.setArrow();
		if(parent && parent.select){
			this.connect(this.anchorNode, "onclick", "onClick");
		}
		this.set("icon", this.icon);
		this.inherited(arguments);
	},

	onClick: function(e){
		var a = e.currentTarget;
		var li = a.parentNode;
		if(dojo.hasClass(li, "mblItemSelected")){ return; } // already selected
		if(this.anchorLabel){
			for(var p = e.target; p.tagName != "LI"; p = p.parentNode){
				if(p.className == "mblListItemTextBox"){
					dojo.addClass(p, "mblListItemTextBoxSelected");
					setTimeout(function(){
						dojo.removeClass(p, "mblListItemTextBoxSelected");
					}, 1000);
					this.onAnchorLabelClicked(e);
					return;
				}
			}
		}
		var parent = this.getParent();
		if(parent.select){
			if(parent.select === "single"){
				if(!this.checked){
					this.set("checked", true);
				}
			}else if(parent.select === "multiple"){
				this.set("checked", !this.checked);
			}
		}
		this.select();
		this.setTransitionPos(e);
		this.transitionTo(this.moveTo, this.href, this.url, this.scene);
	},

	deselect: function(){
		dojo.removeClass(this.domNode, "mblItemSelected");
	},

	select: function(){
		var parent = this.getParent();
		if(parent.stateful){
			parent.deselectAll();
		}else{
			var _this = this;
			setTimeout(function(){
				_this.deselect();
			}, 1000);
		}
		dojo.addClass(this.domNode, "mblItemSelected");
	},

	onAnchorLabelClicked: function(e){
		// Stub function to connect to from your application.
	},

	setArrow: function(){
		if(this.checked){ return; }
		var c = "";
		var parent = this.getParent();
		if(this.moveTo || this.href || this.url || this.clickable){
			if(!this.noArrow && !(parent && parent.stateful)){
				c = this.arrowClass;
			}
		}
		this._setBtnClassAttr(c);
	},

	_setIconAttr: function(icon){
		this.icon = icon;
		var a = this.anchorNode;
		if(this.icon && this.icon.indexOf("mblDomButton") === 0){
			if(!this.iconNode){
				this.iconNode = dojo.create("DIV");
				this.domNode.insertBefore(this.iconNode, a);
			}
			this.iconNode.className = this.icon + " mblLeftButton";
			dojox.mobile.createDomButton(this.iconNode);
			dojo.removeClass(a, "mblListItemAnchorNoIcon");
			a.style.paddingLeft = (this.iconNode.offsetWidth + 11) + "px";
		}else if(this.icon && this.icon != "none"){
			if(!this.iconNode){
				this.iconNode = dojo.create("IMG", {
					className: "mblListItemIcon",
					alt: this.alt
				});
				this.domNode.insertBefore(this.iconNode, a);
			}
			this.iconNode.src = this.icon;
			dojox.mobile.setupIcon(this.iconNode, this.iconPos);
			dojo.removeClass(a, "mblListItemAnchorNoIcon");
		}else{
			dojo.addClass(a, "mblListItemAnchorNoIcon");
		}
	},

	_setBtnClass: function(/*String*/btnClass, /*DomNode*/node, /*String*/className){
		var div;
		if(node){
			if(node.className.match(/(mblDomButton\w+)/)){
				dojo.removeClass(node, RegExp.$1);
			}
			dojo.addClass(node, btnClass);
			div = node;
		}else{
			div = dojo.create("DIV", {className:btnClass+" "+className}, this.anchorNode);
		}
		dojox.mobile.createDomButton(div);
		return div;
	},

	_setBtnClassAttr: function(/*String*/rightIconClass){
		this.rightIconNode = this._setBtnClass(rightIconClass, this.rightIconNode, "mblRightButton");
		this._layoutRightText();
	},

	_setBtnClass2Attr: function(/*String*/rightIconClass){
		this.rightIconNode2 = this._setBtnClass(rightIconClass, this.rightIconNode2, "mblRightButton mblRightButton2");
		dojo.addClass(this.box, "mblListItemTextBox2");
		this._layoutRightText();
	},

	_setCheckedAttr: function(/*Boolean*/checked){
		var parent = this.getParent();
		if(parent.select === "single" && checked){
			dojo.forEach(parent.getChildren(), function(child){
				child.set("checked", false);
			});
		}
		if(!this.checkNode){
			this._setBtnClassAttr(this.checkClass);
			this.checkNode = this.rightIconNode;
		}
		this.checkNode.style.display = checked ? "" : "none";
		dojo.toggleClass(this.domNode, "mblItemChecked", checked);
		if(this.checked !== checked){
			this.getParent().onCheckStateChanged(this, checked);
		}
		this.checked = checked;
		this._layoutRightText();
	},

	_setRightTextAttr: function(/*String*/text){
		this.rightText = text;
		if(!this._rightTextNode){
			this._rightTextNode = dojo.create("DIV", {className:"mblRightText"}, this.anchorNode);
		}
		this._rightTextNode.innerHTML = this._cv(text);
		this._layoutRightText();
	},

	_setLabelAttr: function(/*String*/text){
		this.label = text;
		this.labelNode.innerHTML = this._cv(text);
	},

	_layoutRightText: function(){
		if(this._rightTextNode){
			var w = (this.rightIconNode ? this.rightIconNode.offsetWidth : 0) +
				(this.rightIconNode2 ? this.rightIconNode2.offsetWidth : 0);
			this._rightTextNode.style.right = w + 11 + "px";
		}
	}
});

return dojox.mobile.ListItem;
});
<|endoftext|>


<commit_before>/**
 * Creates data series.
 * @constructor
 * @param {Object} params Parameters to initialize series with.
 * @param {Array} params.values The data set to visualize.
 * @param {String} params.attribute Numberic or color attribute to use for data visualization. This could be: fill, stroke, fill-opacity, stroke-opacity for markers and regions and r (radius) for markers only.
 * @param {Array} params.scale Values used to map a dimension of data to a visual representation. The first value sets visualization for minimum value from the data set and the last value sets visualization for the maximum value. There also could be intermidiate values. Default value is ['#C8EEFF', '#0071A4']
 * @param {Function|String} params.normalizeFunction The function used to map input values to the provided scale. This parameter could be provided as function or one of the strings: 'linear' or 'polynomial', while 'linear' is used by default. The function provided takes value from the data set as an input and returns corresponding value from the scale.
 * @param {Number} params.min Minimum value of the data set. Could be calculated automatically if not provided.
 * @param {Number} params.min Maximum value of the data set. Could be calculated automatically if not provided.
 */
jvm.DataSeries = function(params, elements) {
  var scaleConstructor;

  params = params || {};
  params.attribute = params.attribute || 'fill';

  this.elements = elements;
  this.params = params;

  if (params.attributes) {
    this.setAttributes(params.attributes);
  }

  if (jvm.$.isArray(params.scale)) {
    scaleConstructor = (params.attribute === 'fill' || params.attribute === 'stroke') ? jvm.ColorScale : jvm.NumericScale;
    this.scale = new scaleConstructor(params.scale, params.normalizeFunction, params.min, params.max);
  } else if (params.scale) {
    this.scale = new jvm.OrdinalScale(params.scale);
  } else {
    this.scale = new jvm.SimpleScale(params.scale);
  }

  this.values = params.values || {};
  this.setValues(this.values);
};

jvm.DataSeries.prototype = {
  setAttributes: function(key, attr){
    var attrs = key,
        code;

    if (typeof key == 'string') {
      if (this.elements[key]) {
        this.elements[key].setStyle(this.params.attribute, attr);
      }
    } else {
      for (code in attrs) {
        if (this.elements[code]) {
          this.elements[code].element.setStyle(this.params.attribute, attrs[code]);
        }
      }
    }
  },

  /**
   * Set values for the data set.
   * @param {Object} values Object which maps codes of regions or markers to values.
   */
  setValues: function(values) {
    var max = Number.MIN_VALUE,
        min = Number.MAX_VALUE,
        val,
        cc,
        attrs = {};

    if (!(this.scale instanceof jvm.OrdinalScale) && !(this.scale instanceof jvm.SimpleScale)) {
      if (!this.params.min || !this.params.max) {
        for (cc in values) {
          val = parseFloat(values[cc]);
          if (val > max) max = values[cc];
          if (val < min) min = val;
        }
        if (!this.params.min) {
          this.scale.setMin(min);
        }
        if (!this.params.max) {
          this.scale.setMax(max);
        }
        this.params.min = min;
        this.params.max = max;
      }
      for (cc in values) {
        val = parseFloat(values[cc]);
        if (!isNaN(val)) {
          attrs[cc] = this.scale.getValue(val);
        } else {
          attrs[cc] = this.elements[cc].element.style.initial[this.params.attribute];
        }
      }
    } else {
      for (cc in values) {
        if (values[cc]) {
          attrs[cc] = this.scale.getValue(values[cc]);
        } else {
          attrs[cc] = this.elements[cc].element.style.initial[this.params.attribute];
        }
      }
    }

    this.setAttributes(attrs);
    jvm.$.extend(this.values, values);
  },

  clear: function(){
    var key,
        attrs = {};

    for (key in this.values) {
      if (this.elements[key]) {
        attrs[key] = this.elements[key].element.style.initial[this.params.attribute];
      }
    }
    this.setAttributes(attrs);
    this.values = {};
  },

  /**
   * Set scale of the data series.
   * @param {Array} scale Values representing scale.
   */
  setScale: function(scale) {
    this.scale.setScale(scale);
    if (this.values) {
      this.setValues(this.values);
    }
  },

  /**
   * Set normalize function of the data series.
   * @param {Function|String} normilizeFunction.
   */
  setNormalizeFunction: function(f) {
    this.scale.setNormalizeFunction(f);
    if (this.values) {
      this.setValues(this.values);
    }
  }
};<commit_msg>#172 #192 #207 #221 Fixed issues with min=0 or max=0<commit_after>/**
 * Creates data series.
 * @constructor
 * @param {Object} params Parameters to initialize series with.
 * @param {Array} params.values The data set to visualize.
 * @param {String} params.attribute Numberic or color attribute to use for data visualization. This could be: fill, stroke, fill-opacity, stroke-opacity for markers and regions and r (radius) for markers only.
 * @param {Array} params.scale Values used to map a dimension of data to a visual representation. The first value sets visualization for minimum value from the data set and the last value sets visualization for the maximum value. There also could be intermidiate values. Default value is ['#C8EEFF', '#0071A4']
 * @param {Function|String} params.normalizeFunction The function used to map input values to the provided scale. This parameter could be provided as function or one of the strings: 'linear' or 'polynomial', while 'linear' is used by default. The function provided takes value from the data set as an input and returns corresponding value from the scale.
 * @param {Number} params.min Minimum value of the data set. Could be calculated automatically if not provided.
 * @param {Number} params.min Maximum value of the data set. Could be calculated automatically if not provided.
 */
jvm.DataSeries = function(params, elements) {
  var scaleConstructor;

  params = params || {};
  params.attribute = params.attribute || 'fill';

  this.elements = elements;
  this.params = params;

  if (params.attributes) {
    this.setAttributes(params.attributes);
  }

  if (jvm.$.isArray(params.scale)) {
    scaleConstructor = (params.attribute === 'fill' || params.attribute === 'stroke') ? jvm.ColorScale : jvm.NumericScale;
    this.scale = new scaleConstructor(params.scale, params.normalizeFunction, params.min, params.max);
  } else if (params.scale) {
    this.scale = new jvm.OrdinalScale(params.scale);
  } else {
    this.scale = new jvm.SimpleScale(params.scale);
  }

  this.values = params.values || {};
  this.setValues(this.values);
};

jvm.DataSeries.prototype = {
  setAttributes: function(key, attr){
    var attrs = key,
        code;

    if (typeof key == 'string') {
      if (this.elements[key]) {
        this.elements[key].setStyle(this.params.attribute, attr);
      }
    } else {
      for (code in attrs) {
        if (this.elements[code]) {
          this.elements[code].element.setStyle(this.params.attribute, attrs[code]);
        }
      }
    }
  },

  /**
   * Set values for the data set.
   * @param {Object} values Object which maps codes of regions or markers to values.
   */
  setValues: function(values) {
    var max = -Number.MAX_VALUE,
        min = Number.MAX_VALUE,
        val,
        cc,
        attrs = {};

    if (!(this.scale instanceof jvm.OrdinalScale) && !(this.scale instanceof jvm.SimpleScale)) {
      // we have a color scale as an array
      if (this.params.min === undefined || this.params.max === undefined) {
        // min and/or max are not defined, so calculate them
        for (cc in values) {
          val = parseFloat(values[cc]);
          if (val > max) max = val;
          if (val < min) min = val;
        }
      }

      if (this.params.min === undefined) {
        this.scale.setMin(min);
        this.params.min = min;
      } else {
        this.scale.setMin(this.params.min);
      }

      if (this.params.max === undefined) {
        this.scale.setMax(max);
        this.params.max = max;
      } else {
        this.scale.setMax(this.params.max);
      }

      for (cc in values) {
        val = parseFloat(values[cc]);
        if (!isNaN(val)) {
          attrs[cc] = this.scale.getValue(val);
        } else {
          attrs[cc] = this.elements[cc].element.style.initial[this.params.attribute];
        }
      }
    } else {
      for (cc in values) {
        if (values[cc]) {
          attrs[cc] = this.scale.getValue(values[cc]);
        } else {
          attrs[cc] = this.elements[cc].element.style.initial[this.params.attribute];
        }
      }
    }

    this.setAttributes(attrs);
    jvm.$.extend(this.values, values);
  },

  clear: function(){
    var key,
        attrs = {};

    for (key in this.values) {
      if (this.elements[key]) {
        attrs[key] = this.elements[key].element.style.initial[this.params.attribute];
      }
    }
    this.setAttributes(attrs);
    this.values = {};
  },

  /**
   * Set scale of the data series.
   * @param {Array} scale Values representing scale.
   */
  setScale: function(scale) {
    this.scale.setScale(scale);
    if (this.values) {
      this.setValues(this.values);
    }
  },

  /**
   * Set normalize function of the data series.
   * @param {Function|String} normilizeFunction.
   */
  setNormalizeFunction: function(f) {
    this.scale.setNormalizeFunction(f);
    if (this.values) {
      this.setValues(this.values);
    }
  }
};
<|endoftext|>


<commit_before>SQLite = {} //Global handle

SQLite.Collection = class SQLiteCollection extends Mongo.Collection {
  constructor(name, options) {
    super(name, options);
    if (Meteor.isClient) {
      this.ready = ReactiveVar(true);
      this.status = ReactiveVar({
        ready: true,
        count: 0,
        total: 0
      });
    }
    if (Meteor.server) {
      var self = this;
      methods = {}
      methods[`/${name}/batchInsert`] = function (docs) {
        if (!docs || !docs.length) { return 0; }
        var userId = this.userId;

        docs.forEach(function (doc) {
          // call user validators.
          // Any deny returns true means denied.
          if (_.any(self._validators.insert.deny, function(validator) {
            return validator(userId, doc);
          })) {
            throw new Meteor.Error(403, "Access denied");
          }
          // Any allow returns true means proceed. Throw error if they all fail.
          if (_.all(self._validators.insert.allow, function(validator) {
            return !validator(userId, doc);
          })) {
            throw new Meteor.Error(403, "Access denied");
          }
          try { self.insert(doc); } catch (e) {} //there may be cases of duplicate _ids, just move on
        });
        return docs.length;
      }
      Meteor.methods(methods);
    }
  }
  addFilter() {
    return new Promise( (resolve, reject) => { resolve() });
  }
  removeFilter() {
    return new Promise( (resolve, reject) => { resolve() });
  }
  count(filter) {
    //we could fake this for real...
    //run every doc in the db over the filter function and count them
    return new Promise( (resolve, reject) => { resolve(0) });
  }
}

<commit_msg>speed up uploads! Like by 100x<commit_after>SQLite = {} //Global handle

SQLite.Collection = class SQLiteCollection extends Mongo.Collection {
  constructor(name, options) {
    super(name, options);
    if (Meteor.isClient) {
      this.ready = ReactiveVar(true);
      this.status = ReactiveVar({
        ready: true,
        count: 0,
        total: 0
      });
    }
    if (Meteor.server) {
      var self = this;
      self.batchInsert = {}
      methods = {}
      methods[`/${name}/batchInsert`] = function (docs) {
        if (!docs || !docs.length) { return 0; }
        var userId = this.userId
        , user = Meteor.users.findOne(userId)
        docs.forEach(function (doc) {
          // Any allow returns true means proceed. Throw error if they all fail.
          if (self.batchInsert.allow) {
            if (!self.batchInsert.allow(user, doc)) {
              throw new Meteor.Error(403, "Access denied");
            }
          }
          try { self.insert(doc); } catch (e) {} //there may be cases of duplicate _ids, drop and just move on
        });
        return docs.length;
      }
      Meteor.methods(methods);
    }
  }
  addFilter() {
    return new Promise( (resolve, reject) => { resolve() });
  }
  removeFilter() {
    return new Promise( (resolve, reject) => { resolve() });
  }
  count(filter) {
    //we could fake this for real...
    //run every doc in the db over the filter function and count them
    return new Promise( (resolve, reject) => { resolve(0) });
  }
}

<|endoftext|>


<commit_before>/* eslint require-jsdoc: 0 */

import test from 'ava';
import VerEx from '../dist/verbalexpressions';

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test#Using_test()_on_a_regex_with_the_global_flag
function resetLastIndex(regex) {
    regex.lastIndex = 0;
}

test('constructor', (t) => {
    const testRegex = VerEx();

    t.true(testRegex instanceof RegExp, 'Extends RegExp');
    t.is(testRegex.toString(), '/(?:)/gm', 'Is empty regex with global, multiline matching');
});

// Utility //

test('add', (t) => {
    const testString = '$a^b\\c|d(e)f[g]h{i}j.k*l+m?n:o=p[q]';
    const testRegex = VerEx().startOfLine().then(testString).endOfLine();

    t.true(testRegex.test(testString), 'Special character sanitization');
});

// Rules //

test('startOfLine', (t) => {
    let testRegex = VerEx().startOfLine().then('a');
    let testString = 'a';

    t.true(testRegex.test(testString), 'Starts with an a');

    resetLastIndex(testRegex);
    testString = 'ba';
    t.false(testRegex.test(testString), 'Doesn\'t start with an a');

    testRegex = testRegex.startOfLine(false); // start of line is no longer necessary
    testString = 'ba';
    t.true(testRegex.test(testString), 'Has an a');
});

test('endOfLine', (t) => {
    let testRegex = VerEx().find('a').endOfLine();
    let testString = 'a';

    t.true(testRegex.test(testString), 'Ends with an a');

    resetLastIndex(testRegex);
    testString = 'ab';
    t.false(testRegex.test(testString), 'Doesn\'t end with an a');

    testRegex = testRegex.endOfLine(false); // end of line is no longer necessary
    testString = 'ab';
    t.true(testRegex.test(testString), 'Has an a');
});

function then(name, t) {
    let testRegex = VerEx()[name]('a');
    let testString = 'a';

    t.true(testRegex.test(testString), 'Is "a"');

    resetLastIndex(testRegex);
    testString = 'b';
    t.false(testRegex.test(testString), 'Is not "a"');

    resetLastIndex(testRegex);
    testString = '';
    t.false(testRegex.test(testString), 'Does not have "a"');

    testRegex = VerEx()[name]('a')[name]('b');
    testString = 'ab';
    t.true(testRegex.test(testString), 'Is "ab"');

    resetLastIndex(testRegex);
    testString = 'ac';
    t.false(testRegex.test(testString), 'Is not "ab"');
}

test('then', (t) => {
    then('then', t);
});

test('find', (t) => {
    then('find', t);
});

test('maybe', (t) => {
    const testRegex = VerEx().startOfLine().then('a').maybe('b');
    let testString = 'acb';

    t.true(testRegex.test(testString), 'Maybe has a b after an a');

    resetLastIndex(testRegex);
    testString = 'abc';
    t.true(testRegex.test(testString), 'Maybe has a b after an a');
});

test('or', (t) => {
    const testRegex = VerEx().startOfLine().then('abc').or('def');
    let testString = 'defzzz';

    t.true(testRegex.test(testString), 'Starts with an abc or a def');

    resetLastIndex(testRegex);
    testString = 'xyzabc';
    t.false(testRegex.test(testString), 'Doesn\'t start with an abc or a def');
});

test('anything', (t) => {
    const testRegex = VerEx().startOfLine().anything();
    let testString = 'foo';

    t.true(testRegex.test(testString));

    resetLastIndex(testRegex);
    testString = '';
    t.true(testRegex.test(testString));
});

test('anythingBut', (t) => {
    let testRegex = VerEx().startOfLine().anythingBut('br').endOfLine();
    let testString = 'foobar';

    t.false(testRegex.test(testString));

    resetLastIndex(testRegex);
    testString = 'foo_a_';
    t.true(testRegex.test(testString));

    testRegex = VerEx().startOfLine().anythingBut('br');
    testString = 'bar';
    t.true(testRegex.test(testString), 'May match zero characters');
});

test('something', (t) => {
    const testRegex = VerEx().something();
    let testString = '';

    t.false(testRegex.test(testString), 'Empty string doesn\'t have something');

    resetLastIndex(testRegex);
    testString = 'a';
    t.true(testRegex.test(testString), 'a is something');
});

test('somethingBut', (t) => {
    const testRegex = VerEx().somethingBut('a');
    let testString = '';

    t.false(testRegex.test(testString), 'Empty string doesn\'t have something');

    resetLastIndex(testRegex);
    testString = 'b';
    t.true(testRegex.test(testString), 'Doesn\'t start with an a');

    resetLastIndex(testRegex);
    testString = 'a';
    t.false(testRegex.test(testString), 'Starts with an a');
});

function anyOf(name, t) {
    const testRegex = VerEx().startOfLine().then('a')[name]('xyz');
    let testString = 'ay';

    t.true(testRegex.test(testString), 'Has an x, y, or z after an a');

    resetLastIndex(testRegex);
    testString = 'abc';
    t.false(testRegex.test(testString), 'Doesn\'t have an x, y, or z after an a');
}

test('anyOf', (t) => {
    anyOf('anyOf', t);
});

test('any', (t) => {
    anyOf('any', t);
});

test('range', (t) => {
    const testRegex = VerEx().startOfLine().range('a', 'z', '0', '9').oneOrMore().endOfLine();
    let testString = 'foobarbaz123';

    t.true(testRegex.test(testString), 'Has all characters within defined range');

    resetLastIndex(testRegex);
    testString = 'fooBarBaz_123';
    t.false(testRegex.test(testString), 'Has some characters out of defined range');
});

// Special characters //

function lineBreak(name, t) {
    const testRegex = VerEx().startOfLine().then('abc')[name]().then('def');
    let testString = 'abc\r\ndef';

    t.true(testRegex.test(testString), 'abc,then a line break and then def');

    resetLastIndex(testRegex);
    testString = 'abc\ndef';
    t.true(testRegex.test(testString), 'abc, then a line break and then def');

    resetLastIndex(testRegex);
    testString = 'abc\r\n def';
    t.false(testRegex.test(testString), 'abc, then a line break, then a space and then def');
}

test('lineBreak', (t) => {
    lineBreak('lineBreak', t);
});

test('br', (t) => {
    lineBreak('br', t);
});

test('tab', (t) => {
    const testRegex = VerEx().startOfLine().tab().then('abc');
    let testString = '\tabc';

    t.true(testRegex.test(testString), 'tab then abc');

    resetLastIndex(testRegex);
    testString = 'abc';
    t.false(testRegex.test(testString), 'No tab then abc');
});

test('word', (t) => {
    const testRegex = VerEx().word().endOfLine();
    let testString = 'azertyuiopqsdfghjklmwxcvbn0123456789_';

    t.true(testRegex.test(testString), 'Should match word');

    testString = '. @[]|,&~-';
    for (const char of testString) {
        t.false(testRegex.test(char), `Should not match word (${char})`);
    }
});

test('digit', (t) => {
    const testRegex = VerEx().digit();
    let testString = '0123456789';

    t.true(testRegex.test(testString), 'Should match digit');

    testString = '-.azertyuiopqsdfghjklmwxcvbn @[]|,_&~';
    for (const char of testString) {
        t.false(testRegex.test(char), `Should not match digit (${char})`);
    }
});

test('whitespace', (t) => {
    const testRegex = VerEx().startOfLine().then('a').whitespace().then('z');
    let testString = 'a z';

    t.true(testRegex.test(testString), 'a, then a space and then z');

    resetLastIndex(testRegex);
    testString = 'a_z';
    t.false(testRegex.test(testString), 'a, then no whitespace and then z');
});

// Modifiers //

test('addModifier', (t) => {
    const testRegex = VerEx().addModifier('y');
    t.true(testRegex.flags.includes('y'));
});

test('removeModifier', (t) => {
    const testRegex = VerEx().removeModifier('g');
    t.false(testRegex.flags.includes('g'));
});

test('withAnyCase', (t) => {
    let testRegex = VerEx().startOfLine().then('a');
    let testString = 'A';

    t.false(testRegex.test(testString), 'Not case-insensitive');

    testRegex = VerEx().startOfLine().then('a').withAnyCase();
    testString = 'A';
    t.true(testRegex.test(testString), 'Case-insensitive');

    resetLastIndex(testRegex);
    testString = 'a';
    t.true(testRegex.test(testString), 'Case-insensitive');

    testRegex = VerEx().startOfLine().then('a').withAnyCase(false);
    testString = 'A';
    t.false(testRegex.test(testString), 'Not case-insensitive');
});

test('stopAtFirst', (t) => {
    let testRegex = VerEx().find('foo');
    const testString = 'foofoofoo';

    t.is(testString.match(testRegex).length, 3, 'Matches all "foo"s');

    testRegex = VerEx().find('foo').stopAtFirst();
    t.is(testString.match(testRegex).length, 1, 'Matches one "foo"');

    testRegex = VerEx().find('foo').stopAtFirst(false);
    t.is(testString.match(testRegex).length, 3, 'Matches all "foo"s');
});

test('searchOneLine', (t) => {
    let testRegex = VerEx().startOfLine().then('b').endOfLine();
    const testString = 'a\nb\nc';

    t.true(testRegex.test(testString), '"b" is at the end of it\'s own line');

    testRegex = VerEx().startOfLine().then('b').endOfLine().searchOneLine();
    t.false(testRegex.test(testString), '"c" is at the end of the string');

    testRegex = VerEx().startOfLine().then('b').endOfLine().searchOneLine(false);
    t.true(testRegex.test(testString), '"b" is at the end of it\'s own line');
});

// Loops //

test('repeatPrevious', (t) => {
    let testRegex = VerEx().startOfLine().find('foo').repeatPrevious(3).endOfLine();
    let testString = 'foofoofoo';

    t.true(testRegex.test(testString), 'Has exactly 3 "foo"s');

    resetLastIndex(testRegex);
    testString = 'foofoo';
    t.false(testRegex.test(testString), 'Does not have exactly 3 "foo"s');

    resetLastIndex(testRegex);
    testString = 'bar';
    t.false(testRegex.test(testString), 'Does not have exactly 3 "foo"s');

    testRegex = VerEx().startOfLine().find('foo').repeatPrevious(1, 3).endOfLine();
    testString = 'foo';
    t.true(testRegex.test(testString), 'Has between 1 and 3 (inclusive) "foo"s');

    resetLastIndex(testRegex);
    testString = 'foofoo';
    t.true(testRegex.test(testString), 'Has between 1 and 3 (inclusive) "foo"s');

    resetLastIndex(testRegex);
    testString = 'foofoofoo';
    t.true(testRegex.test(testString), 'Has between 1 and 3 (inclusive) "foo"s');

    resetLastIndex(testRegex);
    testString = 'foofoofoofoo';
    t.false(testRegex.test(testString), 'Does not have between 1 and 3 (inclusive) "foo"s');
});

test('oneOrMore', (t) => {
    const testRegex = VerEx().startOfLine().then('foo').oneOrMore().endOfLine();
    let testString = 'foo';

    t.true(testRegex.test(testString), 'Contains \'foo\' at least once ');

    resetLastIndex(testRegex);
    testString = 'foofoo';
    t.true(testRegex.test(testString), 'Contains \'foo\' at least once in \'foofoo\'');

    resetLastIndex(testRegex);
    testString = 'bar';
    t.false(testRegex.test(testString), 'Contains \'foo\' at least once');
});

test('multiple', (t) => {
    let testRegex = VerEx().startOfLine().multiple('foo').endOfLine();
    let testString = 'foo';

    t.true(testRegex.test(testString), 'Contains \'foo\' at least once');

    testRegex = VerEx().startOfLine().multiple('foo', 2).endOfLine();
    testString = 'foo';
    t.false(testRegex.test(testString), 'Should contain \'foo\' at least twice');

    testRegex = VerEx().startOfLine().multiple('foo', 2).endOfLine();
    testString = 'foofoo';
    t.true(testRegex.test(testString), 'Should contain \'foo\' at least twice');

    testRegex = VerEx().startOfLine().multiple('foo', 2, 5).endOfLine();
    testString = 'foofoofoofoo';
    t.true(testRegex.test(testString), 'Should be \'foo\' repeated two to five times');

    testRegex = VerEx().startOfLine().multiple('foo', 2, 5).endOfLine();
    testString = 'foo';
    t.false(testRegex.test(testString), 'Should be \'foo\' repeated two to five times');
});

// Capture groups //

test('capture groups', (t) => {
    let testRegex = VerEx().find('foo').beginCapture().then('bar');
    let testString = 'foobar';

    t.true(testRegex.test(testString), 'Expressions with incomplete capture groups work');

    testRegex = testRegex.endCapture().then('baz');
    testString = 'foobarbaz';
    t.true(testRegex.test(testString), 'Has "foobarbaz"');

    resetLastIndex(testRegex);
    const matches = testRegex.exec(testString);
    t.is(matches[1], 'bar', 'Captured string is "bar"');
});

// Miscellaneous //

test('replace', (t) => {
    const testRegex = VerEx().find(' ');
    const testString = 'foo bar baz';

    t.is(testRegex.replace(testString, '_'), 'foo_bar_baz', 'Spaces are replaced with underscores');
});

test('toRegExp', (t) => {
    const testRegex = VerEx().anything();
    const converted = testRegex.toRegExp();

    t.is(converted.toString(), testRegex.toString(), 'Converted regex has same behaviour');
});
<commit_msg>Fix test for `multiple`<commit_after>/* eslint require-jsdoc: 0 */

import test from 'ava';
import VerEx from '../dist/verbalexpressions';

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test#Using_test()_on_a_regex_with_the_global_flag
function resetLastIndex(regex) {
    regex.lastIndex = 0;
}

test('constructor', (t) => {
    const testRegex = VerEx();

    t.true(testRegex instanceof RegExp, 'Extends RegExp');
    t.is(testRegex.toString(), '/(?:)/gm', 'Is empty regex with global, multiline matching');
});

// Utility //

test('add', (t) => {
    const testString = '$a^b\\c|d(e)f[g]h{i}j.k*l+m?n:o=p[q]';
    const testRegex = VerEx().startOfLine().then(testString).endOfLine();

    t.true(testRegex.test(testString), 'Special character sanitization');
});

// Rules //

test('startOfLine', (t) => {
    let testRegex = VerEx().startOfLine().then('a');
    let testString = 'a';

    t.true(testRegex.test(testString), 'Starts with an a');

    resetLastIndex(testRegex);
    testString = 'ba';
    t.false(testRegex.test(testString), 'Doesn\'t start with an a');

    testRegex = testRegex.startOfLine(false); // start of line is no longer necessary
    testString = 'ba';
    t.true(testRegex.test(testString), 'Has an a');
});

test('endOfLine', (t) => {
    let testRegex = VerEx().find('a').endOfLine();
    let testString = 'a';

    t.true(testRegex.test(testString), 'Ends with an a');

    resetLastIndex(testRegex);
    testString = 'ab';
    t.false(testRegex.test(testString), 'Doesn\'t end with an a');

    testRegex = testRegex.endOfLine(false); // end of line is no longer necessary
    testString = 'ab';
    t.true(testRegex.test(testString), 'Has an a');
});

function then(name, t) {
    let testRegex = VerEx()[name]('a');
    let testString = 'a';

    t.true(testRegex.test(testString), 'Is "a"');

    resetLastIndex(testRegex);
    testString = 'b';
    t.false(testRegex.test(testString), 'Is not "a"');

    resetLastIndex(testRegex);
    testString = '';
    t.false(testRegex.test(testString), 'Does not have "a"');

    testRegex = VerEx()[name]('a')[name]('b');
    testString = 'ab';
    t.true(testRegex.test(testString), 'Is "ab"');

    resetLastIndex(testRegex);
    testString = 'ac';
    t.false(testRegex.test(testString), 'Is not "ab"');
}

test('then', (t) => {
    then('then', t);
});

test('find', (t) => {
    then('find', t);
});

test('maybe', (t) => {
    const testRegex = VerEx().startOfLine().then('a').maybe('b');
    let testString = 'acb';

    t.true(testRegex.test(testString), 'Maybe has a b after an a');

    resetLastIndex(testRegex);
    testString = 'abc';
    t.true(testRegex.test(testString), 'Maybe has a b after an a');
});

test('or', (t) => {
    const testRegex = VerEx().startOfLine().then('abc').or('def');
    let testString = 'defzzz';

    t.true(testRegex.test(testString), 'Starts with an abc or a def');

    resetLastIndex(testRegex);
    testString = 'xyzabc';
    t.false(testRegex.test(testString), 'Doesn\'t start with an abc or a def');
});

test('anything', (t) => {
    const testRegex = VerEx().startOfLine().anything();
    let testString = 'foo';

    t.true(testRegex.test(testString));

    resetLastIndex(testRegex);
    testString = '';
    t.true(testRegex.test(testString));
});

test('anythingBut', (t) => {
    let testRegex = VerEx().startOfLine().anythingBut('br').endOfLine();
    let testString = 'foobar';

    t.false(testRegex.test(testString));

    resetLastIndex(testRegex);
    testString = 'foo_a_';
    t.true(testRegex.test(testString));

    testRegex = VerEx().startOfLine().anythingBut('br');
    testString = 'bar';
    t.true(testRegex.test(testString), 'May match zero characters');
});

test('something', (t) => {
    const testRegex = VerEx().something();
    let testString = '';

    t.false(testRegex.test(testString), 'Empty string doesn\'t have something');

    resetLastIndex(testRegex);
    testString = 'a';
    t.true(testRegex.test(testString), 'a is something');
});

test('somethingBut', (t) => {
    const testRegex = VerEx().somethingBut('a');
    let testString = '';

    t.false(testRegex.test(testString), 'Empty string doesn\'t have something');

    resetLastIndex(testRegex);
    testString = 'b';
    t.true(testRegex.test(testString), 'Doesn\'t start with an a');

    resetLastIndex(testRegex);
    testString = 'a';
    t.false(testRegex.test(testString), 'Starts with an a');
});

function anyOf(name, t) {
    const testRegex = VerEx().startOfLine().then('a')[name]('xyz');
    let testString = 'ay';

    t.true(testRegex.test(testString), 'Has an x, y, or z after an a');

    resetLastIndex(testRegex);
    testString = 'abc';
    t.false(testRegex.test(testString), 'Doesn\'t have an x, y, or z after an a');
}

test('anyOf', (t) => {
    anyOf('anyOf', t);
});

test('any', (t) => {
    anyOf('any', t);
});

test('range', (t) => {
    const testRegex = VerEx().startOfLine().range('a', 'z', '0', '9').oneOrMore().endOfLine();
    let testString = 'foobarbaz123';

    t.true(testRegex.test(testString), 'Has all characters within defined range');

    resetLastIndex(testRegex);
    testString = 'fooBarBaz_123';
    t.false(testRegex.test(testString), 'Has some characters out of defined range');
});

// Special characters //

function lineBreak(name, t) {
    const testRegex = VerEx().startOfLine().then('abc')[name]().then('def');
    let testString = 'abc\r\ndef';

    t.true(testRegex.test(testString), 'abc,then a line break and then def');

    resetLastIndex(testRegex);
    testString = 'abc\ndef';
    t.true(testRegex.test(testString), 'abc, then a line break and then def');

    resetLastIndex(testRegex);
    testString = 'abc\r\n def';
    t.false(testRegex.test(testString), 'abc, then a line break, then a space and then def');
}

test('lineBreak', (t) => {
    lineBreak('lineBreak', t);
});

test('br', (t) => {
    lineBreak('br', t);
});

test('tab', (t) => {
    const testRegex = VerEx().startOfLine().tab().then('abc');
    let testString = '\tabc';

    t.true(testRegex.test(testString), 'tab then abc');

    resetLastIndex(testRegex);
    testString = 'abc';
    t.false(testRegex.test(testString), 'No tab then abc');
});

test('word', (t) => {
    const testRegex = VerEx().word().endOfLine();
    let testString = 'azertyuiopqsdfghjklmwxcvbn0123456789_';

    t.true(testRegex.test(testString), 'Should match word');

    testString = '. @[]|,&~-';
    for (const char of testString) {
        t.false(testRegex.test(char), `Should not match word (${char})`);
    }
});

test('digit', (t) => {
    const testRegex = VerEx().digit();
    let testString = '0123456789';

    t.true(testRegex.test(testString), 'Should match digit');

    testString = '-.azertyuiopqsdfghjklmwxcvbn @[]|,_&~';
    for (const char of testString) {
        t.false(testRegex.test(char), `Should not match digit (${char})`);
    }
});

test('whitespace', (t) => {
    const testRegex = VerEx().startOfLine().then('a').whitespace().then('z');
    let testString = 'a z';

    t.true(testRegex.test(testString), 'a, then a space and then z');

    resetLastIndex(testRegex);
    testString = 'a_z';
    t.false(testRegex.test(testString), 'a, then no whitespace and then z');
});

// Modifiers //

test('addModifier', (t) => {
    const testRegex = VerEx().addModifier('y');
    t.true(testRegex.flags.includes('y'));
});

test('removeModifier', (t) => {
    const testRegex = VerEx().removeModifier('g');
    t.false(testRegex.flags.includes('g'));
});

test('withAnyCase', (t) => {
    let testRegex = VerEx().startOfLine().then('a');
    let testString = 'A';

    t.false(testRegex.test(testString), 'Not case-insensitive');

    testRegex = VerEx().startOfLine().then('a').withAnyCase();
    testString = 'A';
    t.true(testRegex.test(testString), 'Case-insensitive');

    resetLastIndex(testRegex);
    testString = 'a';
    t.true(testRegex.test(testString), 'Case-insensitive');

    testRegex = VerEx().startOfLine().then('a').withAnyCase(false);
    testString = 'A';
    t.false(testRegex.test(testString), 'Not case-insensitive');
});

test('stopAtFirst', (t) => {
    let testRegex = VerEx().find('foo');
    const testString = 'foofoofoo';

    t.is(testString.match(testRegex).length, 3, 'Matches all "foo"s');

    testRegex = VerEx().find('foo').stopAtFirst();
    t.is(testString.match(testRegex).length, 1, 'Matches one "foo"');

    testRegex = VerEx().find('foo').stopAtFirst(false);
    t.is(testString.match(testRegex).length, 3, 'Matches all "foo"s');
});

test('searchOneLine', (t) => {
    let testRegex = VerEx().startOfLine().then('b').endOfLine();
    const testString = 'a\nb\nc';

    t.true(testRegex.test(testString), '"b" is at the end of it\'s own line');

    testRegex = VerEx().startOfLine().then('b').endOfLine().searchOneLine();
    t.false(testRegex.test(testString), '"c" is at the end of the string');

    testRegex = VerEx().startOfLine().then('b').endOfLine().searchOneLine(false);
    t.true(testRegex.test(testString), '"b" is at the end of it\'s own line');
});

// Loops //

test('repeatPrevious', (t) => {
    let testRegex = VerEx().startOfLine().find('foo').repeatPrevious(3).endOfLine();
    let testString = 'foofoofoo';

    t.true(testRegex.test(testString), 'Has exactly 3 "foo"s');

    resetLastIndex(testRegex);
    testString = 'foofoo';
    t.false(testRegex.test(testString), 'Does not have exactly 3 "foo"s');

    resetLastIndex(testRegex);
    testString = 'bar';
    t.false(testRegex.test(testString), 'Does not have exactly 3 "foo"s');

    testRegex = VerEx().startOfLine().find('foo').repeatPrevious(1, 3).endOfLine();
    testString = 'foo';
    t.true(testRegex.test(testString), 'Has between 1 and 3 (inclusive) "foo"s');

    resetLastIndex(testRegex);
    testString = 'foofoo';
    t.true(testRegex.test(testString), 'Has between 1 and 3 (inclusive) "foo"s');

    resetLastIndex(testRegex);
    testString = 'foofoofoo';
    t.true(testRegex.test(testString), 'Has between 1 and 3 (inclusive) "foo"s');

    resetLastIndex(testRegex);
    testString = 'foofoofoofoo';
    t.false(testRegex.test(testString), 'Does not have between 1 and 3 (inclusive) "foo"s');
});

test('oneOrMore', (t) => {
    const testRegex = VerEx().startOfLine().then('foo').oneOrMore().endOfLine();
    let testString = 'foo';

    t.true(testRegex.test(testString), 'Contains \'foo\' at least once ');

    resetLastIndex(testRegex);
    testString = 'foofoo';
    t.true(testRegex.test(testString), 'Contains \'foo\' at least once in \'foofoo\'');

    resetLastIndex(testRegex);
    testString = 'bar';
    t.false(testRegex.test(testString), 'Contains \'foo\' at least once');
});

test('multiple', (t) => {
    let testRegex = VerEx().startOfLine().multiple('foo').endOfLine();
    let testString = 'foo';

    t.true(testRegex.test(testString), 'Contains \'foo\' at least once');

    testRegex = VerEx().startOfLine().multiple('foo', 2).endOfLine();
    testString = 'foo';
    t.false(testRegex.test(testString), 'Should contain \'foo\' at least twice');

    testRegex = VerEx().startOfLine().multiple('foo', 2).endOfLine();
    testString = 'foofoo';
    t.true(testRegex.test(testString), 'Should contain \'foo\' at least twice');

    testRegex = VerEx().startOfLine().multiple('foo', 2).endOfLine();
    testString = 'foofoofoo';
    t.true(testRegex.test(testString), 'Should contain \'foo\' at least twice');

    testRegex = VerEx().startOfLine().multiple('foo', 2, 5).endOfLine();
    testString = 'foofoofoofoo';
    t.true(testRegex.test(testString), 'Should be \'foo\' repeated two to five times');

    testRegex = VerEx().startOfLine().multiple('foo', 2, 5).endOfLine();
    testString = 'foo';
    t.false(testRegex.test(testString), 'Should be \'foo\' repeated two to five times');
});

// Capture groups //

test('capture groups', (t) => {
    let testRegex = VerEx().find('foo').beginCapture().then('bar');
    let testString = 'foobar';

    t.true(testRegex.test(testString), 'Expressions with incomplete capture groups work');

    testRegex = testRegex.endCapture().then('baz');
    testString = 'foobarbaz';
    t.true(testRegex.test(testString), 'Has "foobarbaz"');

    resetLastIndex(testRegex);
    const matches = testRegex.exec(testString);
    t.is(matches[1], 'bar', 'Captured string is "bar"');
});

// Miscellaneous //

test('replace', (t) => {
    const testRegex = VerEx().find(' ');
    const testString = 'foo bar baz';

    t.is(testRegex.replace(testString, '_'), 'foo_bar_baz', 'Spaces are replaced with underscores');
});

test('toRegExp', (t) => {
    const testRegex = VerEx().anything();
    const converted = testRegex.toRegExp();

    t.is(converted.toString(), testRegex.toString(), 'Converted regex has same behaviour');
});
<|endoftext|>