<commit_before>(function (enyo, scope) {
	/**
	* Fires immediately when the text changes.
	*
	* @event enyo.Input#oninput
	* @type {Object}
	* @property {Object} sender - The [component]{@link enyo.Component} that most recently
	*	propagated the {@glossary event}.
	* @property {Object} event - An [object]{@glossary Object} containing event information.
	* @public
	*/

	/**
	* Fires when the text has changed and the [input]{@link enyo.Input} subsequently loses
	* focus.
	*
	* @event enyo.Input#onchange
	* @type {Object}
	* @property {Object} sender - The [component]{@link enyo.Component} that most recently
	*	propagated the {@glossary event}.
	* @property {Object} event - An [object]{@glossary Object} containing event information.
	* @public
	*/

	/**
	* Fires when the [input]{@link enyo.Input} is disabled or enabled.
	*
	* @event enyo.Input#onDisabledChange
	* @type {Object}
	* @property {Object} sender - The [component]{@link enyo.Component} that most recently
	*	propagated the {@glossary event}.
	* @property {Object} event - An [object]{@glossary Object} containing event information.
	* @public
	*/

	/**
	* {@link enyo.Input} implements an HTML [<input>]{@glossary input} element
	* with cross-platform support for change [events]{@glossary event}.
	*
	* You may listen for [oninput]{@link enyo.Input#oninput} and
	* [onchange]{@link enyo.Input#onchange} [DOM events]{@glossary DOMEvent} from
	* this [control]{@link enyo.Control} to know when the text inside has been modified.
	*
	* For more information, see the documentation on
	* [Text Fields]{@linkplain docs/building-apps/controls/text-fields.html} in the
	* Enyo Developer Guide.
	*
	* @class enyo.Input
	* @extends enyo.Control
	* @ui
	* @public
	*/
	enyo.kind(
		/** @lends enyo.Input.prototype */ {

		/**
		* @private
		*/
		name: 'enyo.Input',

		/**
		* @private
		*/
		kind: 'enyo.Control',

		/**
		* @private
		*/
		published:
			/** @lends enyo.Input.prototype */ {

			/**
			* Value of the [input]{@link enyo.Input}. Use this property only to initialize the
			* value. Call `getValue()` and `setValue()` to manipulate the value at runtime.
			*
			* @type {String}
			* @default ''
			* @public
			*/
			value: '',

			/**
			* Text to display when the [input]{@link enyo.Input} is empty
			*
			* @type {String}
			* @default ''
			* @public
			*/
			placeholder: '',

			/**
			* Type of [input]{@link enyo.Input}; if not specified, it's treated as `'text'`.
			* This may be anything specified for the `type` attribute in the HTML
			* specification, including `'url'`, `'email'`, `'search'`, or `'number'`.
			*
			* @type {String}
			* @default ''
			* @public
			*/
			type: '',

			/**
			* When `true`, prevents input into the [control]{@link enyo.Control}. This maps
			* to the `disabled` DOM attribute.
			*
			* @type {Boolean}
			* @default false
			* @public
			*/
			disabled: false,

			/**
			* When `true`, the contents of the [input]{@link enyo.Input} will be selected
			* when the input gains focus.
			*
			* @type {Boolean}
			* @default false
			* @public
			*/
			selectOnFocus: false
		},

		/**
		* @private
		*/
		events: {
			onDisabledChange: ''
		},

		/**
		* Set to `true` to focus this [control]{@link enyo.Control} when it is rendered.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		defaultFocus: false,

		/**
		* @private
		*/
		tag: 'input',

		/**
		* @private
		*/
		classes: 'enyo-input',

		/**
		* @private
		*/
		handlers: {
			onfocus: 'focused',
			oninput: 'input',
			onclear: 'clear',
			ondragstart: 'dragstart'
		},

		/**
		* @method
		* @private
		*/
		create: enyo.inherit(function (sup) {
			return function() {
				if (enyo.platform.ie) {
					this.handlers.onkeyup = 'iekeyup';
				}
				if (enyo.platform.windowsPhone) {
					this.handlers.onkeydown = 'iekeydown';
				}
				sup.apply(this, arguments);
				this.placeholderChanged();
				// prevent overriding a custom attribute with null
				if (this.type) {
					this.typeChanged();
				}
				this.valueChanged();
			};
		}),

		/**
		* @method
		* @private
		*/
		rendered: enyo.inherit(function (sup) {
			return function() {
				sup.apply(this, arguments);

				enyo.makeBubble(this, 'focus', 'blur');

				//Force onchange event to be bubbled inside Enyo for IE8
				if(enyo.platform.ie == 8){
					this.setAttribute('onchange', enyo.bubbler);
				}

				this.disabledChanged();
				if (this.defaultFocus) {
					this.focus();
				}
			};
		}),

		/**
		* @private
		*/
		typeChanged: function () {
			this.setAttribute('type', this.type);
		},

		/**
		* @private
		*/
		placeholderChanged: function () {
			this.setAttribute('placeholder', this.placeholder);
		},

		/**
		* @fires enyo.Input#onDisabledChange
		* @private
		*/
		disabledChanged: function () {
			this.setAttribute('disabled', this.disabled);
			this.bubble('onDisabledChange');
		},

		/**
		* @private
		*/
		valueChanged: function () {
			var node = this.hasNode(),
				attrs = this.attributes;
			if (node) {
				if (node.value !== this.value) {
					node.value = this.value;
				}
				// we manually update the cached value so that the next time the
				// attribute is requested or the control is re-rendered it will
				// have the correct value - this is because calling setAttribute()
				// in some cases does not receive an appropriate response from the
				// browser
				attrs.value = this.value;
			} else {
				this.setAttribute('value', this.value);
			}
		},

		/**
		* @private
		*/
		iekeyup: function (sender, e) {
			var ie = enyo.platform.ie, kc = e.keyCode;
			// input event missing on ie 8, fails to fire on backspace and delete keys in ie 9
			if (ie <= 8 || (ie == 9 && (kc == 8 || kc == 46))) {
				this.bubble('oninput', e);
			}
		},

		/**
		* @private
		*/
		iekeydown: function (sender, e) {
			var wp = enyo.platform.windowsPhone, kc = e.keyCode, dt = e.dispatchTarget;
			// onchange event fails to fire on enter key for Windows Phone 8, so we force blur
			if (wp <= 8 && kc == 13 && this.tag == 'input' && dt.hasNode()) {
				dt.node.blur();
			}
		},

		/**
		* @private
		*/
		clear: function () {
			this.setValue('');
		},

		// note: we disallow dragging of an input to allow text selection on all platforms
		/**
		* @private
		*/
		dragstart: function () {
			return this.hasFocus();
		},

		/**
		* @private
		*/
		focused: function () {
			if (this.selectOnFocus) {
				enyo.asyncMethod(this, 'selectContents');
			}
		},

		/**
		* @private
		*/
		selectContents: function () {
			var n = this.hasNode();

			if (n && n.setSelectionRange) {
				n.setSelectionRange(0, n.value.length);
			} else if (n && n.createTextRange) {
				var r = n.createTextRange();
				r.expand('textedit');
				r.select();
			}
		},

		/**
		* @private
		*/
		input: function () {
			var val = this.getNodeProperty('value');
			this.setValue(val);
		}
	});

})(enyo, this);
<commit_msg>BHV-17152: Changing functionality in Input.js file for making the behavioral same between Input and InputHeader when RTL is true.<commit_after>(function (enyo, scope) {
	/**
	* Fires immediately when the text changes.
	*
	* @event enyo.Input#oninput
	* @type {Object}
	* @property {Object} sender - The [component]{@link enyo.Component} that most recently
	*	propagated the {@glossary event}.
	* @property {Object} event - An [object]{@glossary Object} containing event information.
	* @public
	*/

	/**
	* Fires when the text has changed and the [input]{@link enyo.Input} subsequently loses
	* focus.
	*
	* @event enyo.Input#onchange
	* @type {Object}
	* @property {Object} sender - The [component]{@link enyo.Component} that most recently
	*	propagated the {@glossary event}.
	* @property {Object} event - An [object]{@glossary Object} containing event information.
	* @public
	*/

	/**
	* Fires when the [input]{@link enyo.Input} is disabled or enabled.
	*
	* @event enyo.Input#onDisabledChange
	* @type {Object}
	* @property {Object} sender - The [component]{@link enyo.Component} that most recently
	*	propagated the {@glossary event}.
	* @property {Object} event - An [object]{@glossary Object} containing event information.
	* @public
	*/

	/**
	* {@link enyo.Input} implements an HTML [<input>]{@glossary input} element
	* with cross-platform support for change [events]{@glossary event}.
	*
	* You may listen for [oninput]{@link enyo.Input#oninput} and
	* [onchange]{@link enyo.Input#onchange} [DOM events]{@glossary DOMEvent} from
	* this [control]{@link enyo.Control} to know when the text inside has been modified.
	*
	* For more information, see the documentation on
	* [Text Fields]{@linkplain docs/building-apps/controls/text-fields.html} in the
	* Enyo Developer Guide.
	*
	* @class enyo.Input
	* @extends enyo.Control
	* @ui
	* @public
	*/
	enyo.kind(
		/** @lends enyo.Input.prototype */ {

		/**
		* @private
		*/
		name: 'enyo.Input',

		/**
		* @private
		*/
		kind: 'enyo.Control',

		/**
		* @private
		*/
		published:
			/** @lends enyo.Input.prototype */ {

			/**
			* Value of the [input]{@link enyo.Input}. Use this property only to initialize the
			* value. Call `getValue()` and `setValue()` to manipulate the value at runtime.
			*
			* @type {String}
			* @default ''
			* @public
			*/
			value: '',

			/**
			* Text to display when the [input]{@link enyo.Input} is empty
			*
			* @type {String}
			* @default ''
			* @public
			*/
			placeholder: '',

			/**
			* Type of [input]{@link enyo.Input}; if not specified, it's treated as `'text'`.
			* This may be anything specified for the `type` attribute in the HTML
			* specification, including `'url'`, `'email'`, `'search'`, or `'number'`.
			*
			* @type {String}
			* @default ''
			* @public
			*/
			type: '',

			/**
			* When `true`, prevents input into the [control]{@link enyo.Control}. This maps
			* to the `disabled` DOM attribute.
			*
			* @type {Boolean}
			* @default false
			* @public
			*/
			disabled: false,

			/**
			* When `true`, the contents of the [input]{@link enyo.Input} will be selected
			* when the input gains focus.
			*
			* @type {Boolean}
			* @default false
			* @public
			*/
			selectOnFocus: false
		},

		/**
		* @private
		*/
		events: {
			onDisabledChange: ''
		},

		/**
		* Set to `true` to focus this [control]{@link enyo.Control} when it is rendered.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		defaultFocus: false,

		/**
		* @private
		*/
		tag: 'input',

		/**
		* @private
		*/
		classes: 'enyo-input',

		/**
		* @private
		*/
		handlers: {
			onfocus: 'focused',
			oninput: 'input',
			onclear: 'clear',
			ondragstart: 'dragstart'
		},

		/**
		* @method
		* @private
		*/
		create: enyo.inherit(function (sup) {
			return function() {
				if (enyo.platform.ie) {
					this.handlers.onkeyup = 'iekeyup';
				}
				if (enyo.platform.windowsPhone) {
					this.handlers.onkeydown = 'iekeydown';
				}
				sup.apply(this, arguments);
				this.placeholderChanged();
				// prevent overriding a custom attribute with null
				if (this.type) {
					this.typeChanged();
				}
				this.valueChanged();
			};
		}),

		/**
		* @method
		* @private
		*/
		rendered: enyo.inherit(function (sup) {
			return function() {
				sup.apply(this, arguments);

				enyo.makeBubble(this, 'focus', 'blur');

				//Force onchange event to be bubbled inside Enyo for IE8
				if(enyo.platform.ie == 8){
					this.setAttribute('onchange', enyo.bubbler);
				}

				this.disabledChanged();
				if (this.defaultFocus) {
					this.focus();
				}
			};
		}),

		/**
		* @private
		*/
		typeChanged: function () {
			this.setAttribute('type', this.type);
		},

		/**
		* @private
		*/
		placeholderChanged: function () {
			this.setAttribute('placeholder', this.placeholder);
			this.valueChanged();
		},

		/**
		* @fires enyo.Input#onDisabledChange
		* @private
		*/
		disabledChanged: function () {
			this.setAttribute('disabled', this.disabled);
			this.bubble('onDisabledChange');
		},

		/**
		* @private
		*/
		valueChanged: function () {
			var node = this.hasNode(),
				attrs = this.attributes;
			if (node) {
				if (node.value !== this.value) {
					node.value = this.value;
				}
				// we manually update the cached value so that the next time the
				// attribute is requested or the control is re-rendered it will
				// have the correct value - this is because calling setAttribute()
				// in some cases does not receive an appropriate response from the
				// browser
				attrs.value = this.value;
			} else {
				this.setAttribute('value', this.value);
			}
			this.detectTextDirectionality((this.value || this.value === 0 || this.value === '0') ? this.value : this.get('placeholder'));
		},

		/**
		* @private
		*/
		iekeyup: function (sender, e) {
			var ie = enyo.platform.ie, kc = e.keyCode;
			// input event missing on ie 8, fails to fire on backspace and delete keys in ie 9
			if (ie <= 8 || (ie == 9 && (kc == 8 || kc == 46))) {
				this.bubble('oninput', e);
			}
		},

		/**
		* @private
		*/
		iekeydown: function (sender, e) {
			var wp = enyo.platform.windowsPhone, kc = e.keyCode, dt = e.dispatchTarget;
			// onchange event fails to fire on enter key for Windows Phone 8, so we force blur
			if (wp <= 8 && kc == 13 && this.tag == 'input' && dt.hasNode()) {
				dt.node.blur();
			}
		},

		/**
		* @private
		*/
		clear: function () {
			this.setValue('');
		},

		// note: we disallow dragging of an input to allow text selection on all platforms
		/**
		* @private
		*/
		dragstart: function () {
			return this.hasFocus();
		},

		/**
		* @private
		*/
		focused: function () {
			if (this.selectOnFocus) {
				enyo.asyncMethod(this, 'selectContents');
			}
		},

		/**
		* @private
		*/
		selectContents: function () {
			var n = this.hasNode();

			if (n && n.setSelectionRange) {
				n.setSelectionRange(0, n.value.length);
			} else if (n && n.createTextRange) {
				var r = n.createTextRange();
				r.expand('textedit');
				r.select();
			}
		},

		/**
		* @private
		*/
		input: function () {
			var val = this.getNodeProperty('value');
			this.setValue(val);
		}
	});

})(enyo, this);
<|endoftext|>


<commit_before>var path = require('path'),
    sys = require('sys'),
    Step = require('step'),
    Tile = require('../lib/tilelive/tile'),
    MBTiles = require('../lib/tilelive/mbtiles'),
    Map = require('../lib/tilelive/map'),
    TileBatch = require('../lib/tilelive/batch'),
    assert = require('assert'),
    fs = require('fs');

var TEST_MAPFILE = 'http://tilemill-testing.s3.amazonaws.com/tilelive_test/world.mml';

exports['Database setup'] = function() {
    var mb = new MBTiles(__dirname + '/tmp/creation.mbtiles');
    Step(
        function() {
            mb.open(this);
        },
        function() {
            var next = this;
            mb.setup(function(err) {
                assert.isUndefined(err, 'MBTiles setup threw an error');
                fs.stat(__dirname + '/tmp/creation.mbtiles', function(err, stats) {
                    assert.isNull(err, 'The file was not created');
                });
                next();
            });

        },
        function() {
            mb.db.close(this);
        },
        function() {
            fs.unlinkSync(__dirname + '/tmp/creation.mbtiles');
        }
    );
};

exports['Tile Batch'] = function(beforeExit) {
    try {
        fs.mkdirSync(__dirname + '/tmp', 0777);
    } catch(err) {}

    try {
        fs.unlinkSync(__dirname + '/tmp/batch.mbtiles');
    } catch(err) {}

    var batch = new TileBatch({
        filepath: __dirname + '/tmp/batch.mbtiles',
        batchsize: 100,
        bbox: [
            -20037500,
            -20037500,
            20037500,
            20037500
        ],
        format: 'png',
        minzoom: 0,
        maxzoom: 2,
        datasource: TEST_MAPFILE,
        mapfile_dir: __dirname + '/data/',
        interactivity: {
            key_name: 'ISO3',
            layer: 0
        },
        metadata: {
            name: 'Test batch',
            type: 'overlay',
            description: 'test',
            version: '1.1',
            formatter: 'function(options, data) { '
                + 'return "" + data.NAME + "
'
                + 'Population: " + data.POP2005 + "";'
                + '}'
        }
    });

    var times = {
        setup: 0,
        render: 0,
        grid: 0,
        finish: 0
    };
    var steps = {
        setup: false,
        render: false,
        grid: false,
        finish: false
    };

    Step(
        function() {
            times.setup = +new Date();
            batch.setup(function(err) {
                if (err) throw err;
                steps.setup = true;
                times.setup = +new Date() - times.setup;
                this();
            }.bind(this));
        },
        function(err) {
            if (err) throw err;
            times.render = +new Date();
            var next = this;
            var end = function(err, tiles) {
                if (err) throw err;
                steps.render = true;
                times.render = +new Date() - times.render;
                next();
            };
            var render = function() {
                process.nextTick(function() {
                    batch.renderChunk(function(err, tiles) {
                        if (!tiles) return end(err, tiles);
                        render();
                    });
                });
            };
            render();
        },
        function(err) {
            if (err) throw err;
            if (!batch.interactivity) return this();
            times.grid = +new Date();
            batch.fillGridData(function(err, tiles) {
                if (err) throw err;
                times.grid = +new Date() - times.grid;
                steps.grid = true;
                this();
            }.bind(this));
        },
        function(err) {
            if (err) throw err;
            times.finish = +new Date();
            batch.finish(this);
        },
        function(err) {
            if (err) throw err;
            times.finish = +new Date() - times.finish;
            steps.finish = true;
        }
    );

    beforeExit(function() {
        console.log('setup:        %ss', times.setup * .001);
        console.log('renderChunk:  %ss', times.render * .001);
        console.log('fillGridData: %ss', times.grid * .001);
        console.log('finish:       %ss', times.finish * .001);

        assert.ok(steps.setup, 'setup did not complete');
        assert.ok(steps.render, 'renderChunk did not complete');
        assert.ok(steps.grid, 'fillGridData did not complete');
        assert.ok(steps.finish, 'finish did not complete');
    });
};
<commit_msg>Fix checks for interactivity.<commit_after>var path = require('path'),
    sys = require('sys'),
    Step = require('step'),
    Tile = require('../lib/tilelive/tile'),
    MBTiles = require('../lib/tilelive/mbtiles'),
    Map = require('../lib/tilelive/map'),
    TileBatch = require('../lib/tilelive/batch'),
    assert = require('assert'),
    fs = require('fs');

var TEST_MAPFILE = 'http://tilemill-testing.s3.amazonaws.com/tilelive_test/world.mml';

exports['Database setup'] = function() {
    var mb = new MBTiles(__dirname + '/tmp/creation.mbtiles');
    Step(
        function() {
            mb.open(this);
        },
        function() {
            var next = this;
            mb.setup(function(err) {
                assert.isUndefined(err, 'MBTiles setup threw an error');
                fs.stat(__dirname + '/tmp/creation.mbtiles', function(err, stats) {
                    assert.isNull(err, 'The file was not created');
                });
                next();
            });

        },
        function() {
            mb.db.close(this);
        },
        function() {
            fs.unlinkSync(__dirname + '/tmp/creation.mbtiles');
        }
    );
};

exports['Tile Batch'] = function(beforeExit) {
    try {
        fs.mkdirSync(__dirname + '/tmp', 0777);
    } catch(err) {}

    try {
        fs.unlinkSync(__dirname + '/tmp/batch.mbtiles');
    } catch(err) {}

    var batch = new TileBatch({
        filepath: __dirname + '/tmp/batch.mbtiles',
        batchsize: 100,
        bbox: [
            -20037500,
            -20037500,
            20037500,
            20037500
        ],
        format: 'png',
        minzoom: 0,
        maxzoom: 2,
        datasource: TEST_MAPFILE,
        mapfile_dir: __dirname + '/data/',
        interactivity: {
            key_name: 'ISO3',
            layer: 0
        },
        metadata: {
            name: 'Test batch',
            type: 'overlay',
            description: 'test',
            version: '1.1',
            formatter: 'function(options, data) { '
                + 'return "" + data.NAME + "
'
                + 'Population: " + data.POP2005 + "";'
                + '}'
        }
    });

    var times = {
        setup: 0,
        render: 0,
        grid: 0,
        finish: 0
    };
    var steps = {
        setup: false,
        render: false,
        grid: false,
        finish: false
    };

    Step(
        function() {
            times.setup = +new Date();
            batch.setup(function(err) {
                if (err) throw err;
                steps.setup = true;
                times.setup = +new Date() - times.setup;
                this();
            }.bind(this));
        },
        function(err) {
            if (err) throw err;
            times.render = +new Date();
            var next = this;
            var end = function(err, tiles) {
                if (err) throw err;
                steps.render = true;
                times.render = +new Date() - times.render;
                next();
            };
            var render = function() {
                process.nextTick(function() {
                    batch.renderChunk(function(err, tiles) {
                        if (!tiles) return end(err, tiles);
                        render();
                    });
                });
            };
            render();
        },
        function(err) {
            if (err) throw err;
            if (!batch.options.interactivity) return this();
            times.grid = +new Date();
            batch.fillGridData(function(err, tiles) {
                if (err) throw err;
                times.grid = +new Date() - times.grid;
                steps.grid = true;
                this();
            }.bind(this));
        },
        function(err) {
            if (err) throw err;
            times.finish = +new Date();
            batch.finish(this);
        },
        function(err) {
            if (err) throw err;
            times.finish = +new Date() - times.finish;
            steps.finish = true;
        }
    );

    beforeExit(function() {
        console.log('setup:        %ss', times.setup * .001);
        console.log('renderChunk:  %ss', times.render * .001);
        console.log('fillGridData: %ss', times.grid * .001);
        console.log('finish:       %ss', times.finish * .001);

        assert.ok(steps.setup, 'setup did not complete');
        assert.ok(steps.render, 'renderChunk did not complete');
        batch.options.interactivity && assert.ok(steps.grid, 'fillGridData did not complete');
        assert.ok(steps.finish, 'finish did not complete');
    });
};
<|endoftext|>


<commit_before>var Model = require('base/model');
var debug = require('debug')("craftodex:ui:agent:model");
var _ = require('lodash');

var Relationships = require('relationship/collection');

module.exports = Model.extend({

  modelType: "Agent",

  initialize: function () {
    debug("initialize", this);
    Model.prototype.initialize.apply(this, arguments);
    this.on("change", debug.bind(null, "change"));
  },

  props: {
    name: "string",
  },

  children: {
    relationships: Relationships,
  },

  derived: {
    relsByType: {
      deps: ['relationships'],
      cache: false,
      fn: function () {
        var rels = {};
        this.relationships.forEach(function (rel) {
          var relType = rel.relationshipType;
          if (!relType) return;
          var relType = relType.getId();
          if (!rels[relType]) {
            rels[relType] = new Relationships();
          }
          rels[relType].add(rel);
        });
        return rels;
      },
    },

    hasRelsByType: {
      deps: ['relsByType'],
      cache: false,
      fn: function () {
        debug("hasRelsByType", this.relsByType)
        return _.mapValues(this.relsByType, function (rels) {
          return rels.filter(function (rel) {
            debug(rel.is && rel.is.getId(), this.getId())
            return rel.is && (rel.is.getId() === this.getId());
          }, this)
        }, this);
      },
    },

  },

});
<commit_msg>change agent children to collections<commit_after>var Model = require('base/model');
var debug = require('debug')("craftodex:ui:agent:model");
var _ = require('lodash');

var Relationships = require('relationship/collection');

module.exports = Model.extend({

  modelType: "Agent",

  initialize: function () {
    debug("initialize", this);
    Model.prototype.initialize.apply(this, arguments);
    this.on("change", debug.bind(null, "change"));
  },

  props: {
    name: "string",
  },

  collections: {
    relationships: Relationships,
  },

  derived: {
    relsByType: {
      deps: ['relationships'],
      cache: false,
      fn: function () {
        var rels = {};
        this.relationships.forEach(function (rel) {
          var relType = rel.relationshipType;
          if (!relType) return;
          var relType = relType.getId();
          if (!rels[relType]) {
            rels[relType] = new Relationships();
          }
          rels[relType].add(rel);
        });
        return rels;
      },
    },

    hasRelsByType: {
      deps: ['relsByType'],
      cache: false,
      fn: function () {
        debug("hasRelsByType", this.relsByType)
        return _.mapValues(this.relsByType, function (rels) {
          return rels.filter(function (rel) {
            debug(rel.is && rel.is.getId(), this.getId())
            return rel.is && (rel.is.getId() === this.getId());
          }, this)
        }, this);
      },
    },

  },

});
<|endoftext|>


<commit_before>import { assert } from 'chai';
import * as R from 'ramda';

import * as RA from '../src';

describe('thenCatchP', function() {
  context('given fulfilled Promise', function() {
    specify('should call "onFulfilled" callback', async function() {
      const promise = RA.resolveP(1);
      const expected = await RA.thenCatchP(
        R.add(1),
        R.always('danger!'),
        promise
      );

      assert.strictEqual(expected, 2);
    });
  });

  context('given rejected Promise', function() {
    specify('should call "onRejected" callback', async function() {
      const promise = RA.rejectP('a');
      const expected = await RA.thenCatchP(
        R.add(1),
        R.always('danger!'),
        promise
      );

      assert.strictEqual(expected, 'danger!');
    });
  });

  it('should curry', async function() {
    const promise = RA.resolveP(1);
    assert.strictEqual(
      await RA.thenCatchP(R.add(1), R.always('a'), promise),
      2
    );
    assert.strictEqual(
      await RA.thenCatchP(R.add(1), R.always('a'))(promise),
      2
    );
    assert.strictEqual(
      await RA.thenCatchP(R.add(1))(R.always('a'))(promise),
      2
    );
  });
});
<commit_msg>style(thenCatchP): fix linting issues<commit_after>import { assert } from 'chai';
import * as R from 'ramda';

import * as RA from '../src';

describe('thenCatchP', function () {
  context('given fulfilled Promise', function () {
    specify('should call "onFulfilled" callback', async function () {
      const promise = RA.resolveP(1);
      const expected = await RA.thenCatchP(
        R.add(1),
        R.always('danger!'),
        promise
      );

      assert.strictEqual(expected, 2);
    });
  });

  context('given rejected Promise', function () {
    specify('should call "onRejected" callback', async function () {
      const promise = RA.rejectP('a');
      const expected = await RA.thenCatchP(
        R.add(1),
        R.always('danger!'),
        promise
      );

      assert.strictEqual(expected, 'danger!');
    });
  });

  it('should curry', async function () {
    const promise = RA.resolveP(1);
    assert.strictEqual(
      await RA.thenCatchP(R.add(1), R.always('a'), promise),
      2
    );
    assert.strictEqual(
      await RA.thenCatchP(R.add(1), R.always('a'))(promise),
      2
    );
    assert.strictEqual(
      await RA.thenCatchP(R.add(1))(R.always('a'))(promise),
      2
    );
  });
});
<|endoftext|>


<commit_before>/*global module:true*/
'use strict';

Math.log2 = Math.log2 || function(x) {
  return Math.log(x) / Math.LN2;
};

Math.log10 = Math.log10 || function(x) {
  return Math.log(x) / Math.LN10;
};

(function() {
  var Helpers = {
    avg: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        v += arr[index];
      }
      return v / arr.length;
    },
    min: function(arr) {
      if (arr.length === 0) return 0;
      var v = arr[0];
      for (var index = 1; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.avg(v2);
        if (v2 < v) v = v2;
      }
      return Math.max(0, v);
    },
    max: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.avg(v2);
        if (v2 > v) v = v2;
      }
      return Math.max(0, v);
    },
    upperMax: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.max(v2);
        if (v2 > v) v = v2;
      }
      return Math.max(0, v);
    },
    niceNumbers: function(range, round) {
      var exponent = Math.floor(Math.log10(range));
      var fraction = range / Math.pow(10, exponent);
      var niceFraction;
      if (round) {
        if (fraction < 1.5) niceFraction = 1;
        else if (fraction < 3) niceFraction = 2;
        else if (fraction < 7) niceFraction = 5;
        else niceFraction = 10;
      } else {
        if (fraction <= 1.0) niceFraction = 1;
        else if (fraction <= 2) niceFraction = 2;
        else if (fraction <= 5) niceFraction = 5;
        else niceFraction = 10;
      }
      return niceFraction * Math.pow(10, exponent);
    },
    getLinearTicks: function(min, max, maxTicks) {
      var range = Helpers.niceNumbers(max - min, false);
      var tickSpacing = Helpers.niceNumbers(range / (maxTicks - 1), true);
      return [
        Math.floor(min / tickSpacing) * tickSpacing,
        Math.ceil(max / tickSpacing) * tickSpacing,
        tickSpacing
      ];
    }
  };

  var BarChart = (function() {
    function BarChart(ctx, options) {
      this.options = {
        font: 'Helvetica',
        fontSizeTitle: 24,
        fontSizeAxes: 20,
        fontSizeTicks: 18,
        fontSizeLabels: 18,
        paddingPercentBars: 0.10,
        paddingPercentTicks: 0.15,
        paddingPixelsVertical: 10,
        paddingPixelsHorizontal: 10,
        paddingPixelsTicks: 10,
        fillColorBackground: 'rgb(255, 255, 255)',
        strokeColorBars: 'rgb(0, 0, 0)',
        fillColorBars: 'rgba(180, 180, 180, 0.25)',
        scaleStyle: 'linear',
        errorBarStyle: 'none',
        defaultMaxTick: 0
      };
      options = options || { };
      for (var key in this.options) {
        if (options.hasOwnProperty(key)) this.options[key] = options[key];
      }
      this.ctx = ctx;
      this.content = { };
    }

    BarChart.prototype.update = function(content) {
      if (typeof content !== 'object') {
        throw new Error('Collections must be objects.');
      } else if (!(content.hasOwnProperty('labels') && content.hasOwnProperty('data'))) {
        throw new Error('Collection must specify labels and data.');
      } else if (!(Array.isArray(content.labels) && Array.isArray(content.data))) {
        throw new Error('Labels and data must be arrays.');
      } else if (content.labels.length !== content.data.length) {
        throw new Error('Labels and data length must match.');
      }
      content._data_standard_deviation = [];
      content._data_standard_error = [];
      for (var i = 0; i < content.data.length; ++i) {
        var isArr = Array.isArray(content.data[i]);
        if (this.options.scaleStyle === 'log2') {
          if (isArr) {
            for (var i3 = 0; i3 < content.data[i].length; ++i3) content.data[i][i3] = Math.log2(content.data[i][i3]);
          } else content.data[i] = Math.log2(content.data[i]);
        }
        if (isArr) {
          var mean = Helpers.avg(content.data[i]);
          var acc = 0;
          for (var i2 = 0; i2 < content.data[i].length; ++i2) acc += Math.pow(mean - content.data[i][i2], 2);
          acc = Math.sqrt(acc / (content.data[i].length - 1));
          content._data_standard_deviation.push(acc);
          content._data_standard_error.push(acc / Math.sqrt(content.data[i].length));
        } else {
          content._data_standard_deviation.push(0);
          content._data_standard_error.push(0);
        }
      }
      this.content = content;
      this.redraw();
    };

    BarChart.prototype.redraw = function() {
      setTimeout(function() {
        this._draw();
      }.bind(this), 0);
    };

    BarChart.prototype._draw = function() {
      var options = this.options;
      var ctx = this.ctx, content = this.content;
      ctx.translate(-0.5, -0.5);
      var width = ctx.canvas.width, height = ctx.canvas.height;
      var remainingWidth = width, remainingHeight = height;
      var index;

      if (options.fillColorBackground != null) {
        ctx.save();
        ctx.fillStyle = options.fillColorBackground;
        ctx.fillRect(0, 0, width, height);
        ctx.restore();
      }

      var topYPadding = options.paddingPixelsHorizontal;
      remainingHeight -= options.paddingPixelsHorizontal;
      ctx.fillStyle = 'rgb(0, 0, 0)';
      /* Draw title of bar chart */
      if (content.title != null) {
        ctx.save();
        ctx.font = options.fontSizeTitle + 'px ' + options.font;
        ctx.textAlign = 'center';
        ctx.fillText(content.title, width / 2, topYPadding + options.fontSizeTitle);
        ctx.restore();
        remainingHeight -= options.fontSizeTitle * 1.25;
        topYPadding += options.fontSizeTitle * 1.25;
      }

      /* Compute required left padding */
      var leftXPadding = options.paddingPixelsVertical;
      remainingWidth  -= options.paddingPixelsVertical;

      var leftXDrawYLabel = null;
      if (content.yAxis != null) {
        leftXDrawYLabel = leftXPadding + options.fontSizeAxes * 0.5;
        remainingWidth -= options.fontSizeAxes * 1.25;
        leftXPadding += options.fontSizeAxes * 1.25;
      }

      ctx.save();
      ctx.font = options.fontSizeTicks + 'px ' + options.font;
      var maxChartValue = Helpers.upperMax(content.data);
      if (options.defaultMaxTick > maxChartValue) maxChartValue = options.defaultMaxTick;
      var maxYAxisTickWidth = options.scaleStyle == 'log2' ? Math.ceil(Math.pow(2, maxChartValue)) : maxChartValue;
      maxYAxisTickWidth = ctx.measureText(Math.max(maxYAxisTickWidth, 100)).width;
      maxYAxisTickWidth = Math.ceil(maxYAxisTickWidth) + options.paddingPixelsTicks;
      remainingWidth -= maxYAxisTickWidth;
      leftXPadding += maxYAxisTickWidth;
      ctx.restore();

      var rightXPadding = options.paddingPixelsVertical;
      remainingWidth -= options.paddingPixelsVertical;

      /* Draw x-axis label of bar chart */
      var bottomYPadding = options.paddingPixelsHorizontal;
      remainingHeight -= options.paddingPixelsHorizontal;
      if (content.xAxis != null) {
        ctx.save();
        ctx.font = options.fontSizeAxes + 'px ' + options.font;
        ctx.fillStyle = 'rgb(0, 0, 0)';
        ctx.textAlign = 'center';
        ctx.fillText(content.xAxis, (width - remainingWidth) + remainingWidth / 2, height - bottomYPadding);
        remainingHeight -= options.fontSizeAxes;
        bottomYPadding += options.fontSizeAxes;
        ctx.restore();
      }

      var widthPerBar = remainingWidth / content.data.length;

      /* Draw x-axis top labels */
      if (content.topLabels != null) {
        ctx.save();
        ctx.textAlign = 'center';
        ctx.font = options.fontSizeLabels + 'px ' + options.font;
        remainingHeight -= options.fontSizeLabels * 1.5;
        topYPadding += options.fontSizeLabels * 1.5;
        for (index = 0; index < content.topLabels.length; ++index) {
          ctx.fillText(
            content.topLabels[index],
            leftXPadding + index * widthPerBar + widthPerBar / 2,
            topYPadding - options.fontSizeLabels / 2
          );
        }
        ctx.restore();
      }

      /* Draw x-axis labels */
      ctx.save();
      ctx.textAlign = 'center';
      ctx.font = options.fontSizeLabels + 'px ' + options.font;
      var computedBarPadding = Math.floor((widthPerBar * options.paddingPercentBars) / 2);
      for (index = 0; index < content.labels.length; ++index) {
        ctx.fillText(
          content.labels[index],
          leftXPadding + index * widthPerBar + widthPerBar / 2,
          height - options.fontSizeLabels / 2 - bottomYPadding
        );
      }
      remainingHeight -= options.fontSizeLabels * 1.5;
      bottomYPadding += options.fontSizeLabels * 1.5;
      ctx.restore();

      /* Draw boundaries */
      ctx.save();
      ctx.strokeStyle = 'rgb(0, 0, 0)';
      ctx.beginPath();
      ctx.moveTo(leftXPadding, topYPadding);
      ctx.lineTo(leftXPadding, topYPadding + remainingHeight);
      ctx.lineTo(leftXPadding + remainingWidth, topYPadding + remainingHeight);
      ctx.stroke();
      ctx.restore();

      /* Draw y-axis label of bar chart */
      if (content.yAxis != null) {
        ctx.save();
        ctx.rotate(Math.PI * 1.5);
        ctx.font = options.fontSizeAxes + 'px ' + options.font;
        ctx.fillStyle = 'rgb(0, 0, 0)';
        ctx.textAlign = 'center';
        ctx.fillText(content.yAxis, -(topYPadding + remainingHeight / 2), leftXDrawYLabel);
        ctx.restore();
      }

      /* Draw y-axis labels */
      ctx.save();
      ctx.fillStyle = 'rgb(0, 0, 0)';
      ctx.strokeStyle = 'rgba(0, 0, 0, 0.20)';
      ctx.font = options.fontSizeTicks + 'px ' + options.font;
      ctx.textAlign = 'right';
      var tickMeta = Helpers.getLinearTicks(0, maxChartValue, Math.max(2, remainingHeight / (options.fontSizeTicks * (1 + options.paddingPercentTicks))));
      maxChartValue = tickMeta[1] + Math.ceil(maxChartValue / options.fontSizeTicks);
      var ticks = [];
      while (tickMeta[0] <= tickMeta[1]) {
        ticks.push(tickMeta[0]);
        tickMeta[0] += tickMeta[2];
      }
      for (index = 0; index < ticks.length; ++index) {
        var tickHeight = Math.round(remainingHeight * (ticks[index] / maxChartValue));
        if (options.scaleStyle == 'log2' && ticks[index] !== 0) ticks[index] = Math.round(Math.pow(2, ticks[index]));
        else ticks[index] = Math.floor(ticks[index] * 100) / 100;
        ctx.fillText(ticks[index] + '', leftXPadding - options.paddingPixelsTicks, topYPadding + remainingHeight - tickHeight);
        if (index == 0) continue;
        ctx.beginPath();
        ctx.moveTo(leftXPadding, topYPadding + remainingHeight - tickHeight);
        ctx.lineTo(leftXPadding + remainingWidth, topYPadding + remainingHeight - tickHeight);
        ctx.stroke();
      }
      ctx.restore();

      /* Draw bars */
      ctx.save();
      for (index = 0; index < content.data.length; ++index) {
        if (content.fillColor != null) {
          if (Array.isArray(content.fillColor)) ctx.fillStyle = content.fillColor[index];
          else ctx.fillStyle = content.fillColor;
        } else ctx.fillStyle = options.fillColorBars;
        if (content.strokeColor != null) {
          if (Array.isArray(content.strokeColor)) ctx.fillStyle = content.strokeColor[index];
          else ctx.fillStyle = content.strokeColor;
        } else ctx.strokeStyle = options.strokeColorBars;
        var v = content.data[index];
        if (Array.isArray(v)) v = Helpers.avg(v);
        var renderBarHeight = Math.round(remainingHeight * (v / maxChartValue));
        var renderStartX = leftXPadding + widthPerBar * index;
        var renderUpToY = topYPadding + remainingHeight - renderBarHeight;
        ctx.beginPath();
        ctx.moveTo(renderStartX + computedBarPadding, topYPadding + remainingHeight);
        ctx.lineTo(renderStartX + computedBarPadding, renderUpToY);
        ctx.lineTo(renderStartX + (widthPerBar - 1) - computedBarPadding, renderUpToY);
        ctx.lineTo(renderStartX + (widthPerBar - 1) - computedBarPadding, topYPadding + remainingHeight);
        ctx.stroke();
        ctx.fill();

        if (options.errorBarStyle === 'error') {
          var val;
          if ((val = content._data_standard_error[index]) != 0) {
            var renderBarError = Math.round(remainingHeight * (val / maxChartValue));
            ctx.beginPath();
            var wiskerWidth = Math.round((widthPerBar - computedBarPadding * 2) / 8);
            var x = leftXPadding + widthPerBar * index + widthPerBar / 2;
            ctx.moveTo(x - wiskerWidth, renderUpToY + renderBarError);
            ctx.lineTo(x + wiskerWidth, renderUpToY + renderBarError);
            ctx.moveTo(x, renderUpToY + renderBarError);
            ctx.lineTo(x, renderUpToY - renderBarError);
            ctx.moveTo(x - wiskerWidth, renderUpToY - renderBarError);
            ctx.lineTo(x + wiskerWidth, renderUpToY - renderBarError);
            ctx.stroke();
          }
        }
      }
      ctx.restore();
      ctx.translate(0.5, 0.5);
    };

    return BarChart;
  })();

  if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = BarChart;
  } else {
    window.BarChart = BarChart;
  }
})();
<commit_msg>When using top labels, outline entire chart.<commit_after>/*global module:true*/
'use strict';

Math.log2 = Math.log2 || function(x) {
  return Math.log(x) / Math.LN2;
};

Math.log10 = Math.log10 || function(x) {
  return Math.log(x) / Math.LN10;
};

(function() {
  var Helpers = {
    avg: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        v += arr[index];
      }
      return v / arr.length;
    },
    min: function(arr) {
      if (arr.length === 0) return 0;
      var v = arr[0];
      for (var index = 1; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.avg(v2);
        if (v2 < v) v = v2;
      }
      return Math.max(0, v);
    },
    max: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.avg(v2);
        if (v2 > v) v = v2;
      }
      return Math.max(0, v);
    },
    upperMax: function(arr) {
      var v = 0;
      for (var index = 0; index < arr.length; ++index) {
        var v2 = arr[index];
        if (Array.isArray(v2)) v2 = Helpers.max(v2);
        if (v2 > v) v = v2;
      }
      return Math.max(0, v);
    },
    niceNumbers: function(range, round) {
      var exponent = Math.floor(Math.log10(range));
      var fraction = range / Math.pow(10, exponent);
      var niceFraction;
      if (round) {
        if (fraction < 1.5) niceFraction = 1;
        else if (fraction < 3) niceFraction = 2;
        else if (fraction < 7) niceFraction = 5;
        else niceFraction = 10;
      } else {
        if (fraction <= 1.0) niceFraction = 1;
        else if (fraction <= 2) niceFraction = 2;
        else if (fraction <= 5) niceFraction = 5;
        else niceFraction = 10;
      }
      return niceFraction * Math.pow(10, exponent);
    },
    getLinearTicks: function(min, max, maxTicks) {
      var range = Helpers.niceNumbers(max - min, false);
      var tickSpacing = Helpers.niceNumbers(range / (maxTicks - 1), true);
      return [
        Math.floor(min / tickSpacing) * tickSpacing,
        Math.ceil(max / tickSpacing) * tickSpacing,
        tickSpacing
      ];
    }
  };

  var BarChart = (function() {
    function BarChart(ctx, options) {
      this.options = {
        font: 'Helvetica',
        fontSizeTitle: 24,
        fontSizeAxes: 20,
        fontSizeTicks: 18,
        fontSizeLabels: 18,
        paddingPercentBars: 0.10,
        paddingPercentTicks: 0.15,
        paddingPixelsVertical: 10,
        paddingPixelsHorizontal: 10,
        paddingPixelsTicks: 10,
        fillColorBackground: 'rgb(255, 255, 255)',
        strokeColorBars: 'rgb(0, 0, 0)',
        fillColorBars: 'rgba(180, 180, 180, 0.25)',
        scaleStyle: 'linear',
        errorBarStyle: 'none',
        defaultMaxTick: 0
      };
      options = options || { };
      for (var key in this.options) {
        if (options.hasOwnProperty(key)) this.options[key] = options[key];
      }
      this.ctx = ctx;
      this.content = { };
    }

    BarChart.prototype.update = function(content) {
      if (typeof content !== 'object') {
        throw new Error('Collections must be objects.');
      } else if (!(content.hasOwnProperty('labels') && content.hasOwnProperty('data'))) {
        throw new Error('Collection must specify labels and data.');
      } else if (!(Array.isArray(content.labels) && Array.isArray(content.data))) {
        throw new Error('Labels and data must be arrays.');
      } else if (content.labels.length !== content.data.length) {
        throw new Error('Labels and data length must match.');
      }
      content._data_standard_deviation = [];
      content._data_standard_error = [];
      for (var i = 0; i < content.data.length; ++i) {
        var isArr = Array.isArray(content.data[i]);
        if (this.options.scaleStyle === 'log2') {
          if (isArr) {
            for (var i3 = 0; i3 < content.data[i].length; ++i3) content.data[i][i3] = Math.log2(content.data[i][i3]);
          } else content.data[i] = Math.log2(content.data[i]);
        }
        if (isArr) {
          var mean = Helpers.avg(content.data[i]);
          var acc = 0;
          for (var i2 = 0; i2 < content.data[i].length; ++i2) acc += Math.pow(mean - content.data[i][i2], 2);
          acc = Math.sqrt(acc / (content.data[i].length - 1));
          content._data_standard_deviation.push(acc);
          content._data_standard_error.push(acc / Math.sqrt(content.data[i].length));
        } else {
          content._data_standard_deviation.push(0);
          content._data_standard_error.push(0);
        }
      }
      this.content = content;
      this.redraw();
    };

    BarChart.prototype.redraw = function() {
      setTimeout(function() {
        this._draw();
      }.bind(this), 0);
    };

    BarChart.prototype._draw = function() {
      var options = this.options;
      var ctx = this.ctx, content = this.content;
      ctx.translate(-0.5, -0.5);
      var width = ctx.canvas.width, height = ctx.canvas.height;
      var remainingWidth = width, remainingHeight = height;
      var index;

      if (options.fillColorBackground != null) {
        ctx.save();
        ctx.fillStyle = options.fillColorBackground;
        ctx.fillRect(0, 0, width, height);
        ctx.restore();
      }

      var topYPadding = options.paddingPixelsHorizontal;
      remainingHeight -= options.paddingPixelsHorizontal;
      ctx.fillStyle = 'rgb(0, 0, 0)';
      /* Draw title of bar chart */
      if (content.title != null) {
        ctx.save();
        ctx.font = options.fontSizeTitle + 'px ' + options.font;
        ctx.textAlign = 'center';
        ctx.fillText(content.title, width / 2, topYPadding + options.fontSizeTitle);
        ctx.restore();
        remainingHeight -= options.fontSizeTitle * 1.25;
        topYPadding += options.fontSizeTitle * 1.25;
      }

      /* Compute required left padding */
      var leftXPadding = options.paddingPixelsVertical;
      remainingWidth  -= options.paddingPixelsVertical;

      var leftXDrawYLabel = null;
      if (content.yAxis != null) {
        leftXDrawYLabel = leftXPadding + options.fontSizeAxes * 0.5;
        remainingWidth -= options.fontSizeAxes * 1.25;
        leftXPadding += options.fontSizeAxes * 1.25;
      }

      ctx.save();
      ctx.font = options.fontSizeTicks + 'px ' + options.font;
      var maxChartValue = Helpers.upperMax(content.data);
      if (options.defaultMaxTick > maxChartValue) maxChartValue = options.defaultMaxTick;
      var maxYAxisTickWidth = options.scaleStyle == 'log2' ? Math.ceil(Math.pow(2, maxChartValue)) : maxChartValue;
      maxYAxisTickWidth = ctx.measureText(Math.max(maxYAxisTickWidth, 100)).width;
      maxYAxisTickWidth = Math.ceil(maxYAxisTickWidth) + options.paddingPixelsTicks;
      remainingWidth -= maxYAxisTickWidth;
      leftXPadding += maxYAxisTickWidth;
      ctx.restore();

      var rightXPadding = options.paddingPixelsVertical;
      remainingWidth -= options.paddingPixelsVertical;

      /* Draw x-axis label of bar chart */
      var bottomYPadding = options.paddingPixelsHorizontal;
      remainingHeight -= options.paddingPixelsHorizontal;
      if (content.xAxis != null) {
        ctx.save();
        ctx.font = options.fontSizeAxes + 'px ' + options.font;
        ctx.fillStyle = 'rgb(0, 0, 0)';
        ctx.textAlign = 'center';
        ctx.fillText(content.xAxis, (width - remainingWidth) + remainingWidth / 2, height - bottomYPadding);
        remainingHeight -= options.fontSizeAxes;
        bottomYPadding += options.fontSizeAxes;
        ctx.restore();
      }

      var widthPerBar = remainingWidth / content.data.length;

      /* Draw x-axis top labels */
      if (content.topLabels != null) {
        ctx.save();
        ctx.textAlign = 'center';
        ctx.font = options.fontSizeLabels + 'px ' + options.font;
        remainingHeight -= options.fontSizeLabels * 1.5;
        topYPadding += options.fontSizeLabels * 1.5;
        for (index = 0; index < content.topLabels.length; ++index) {
          ctx.fillText(
            content.topLabels[index],
            leftXPadding + index * widthPerBar + widthPerBar / 2,
            topYPadding - options.fontSizeLabels / 2
          );
        }
        ctx.restore();
      }

      /* Draw x-axis labels */
      ctx.save();
      ctx.textAlign = 'center';
      ctx.font = options.fontSizeLabels + 'px ' + options.font;
      var computedBarPadding = Math.floor((widthPerBar * options.paddingPercentBars) / 2);
      for (index = 0; index < content.labels.length; ++index) {
        ctx.fillText(
          content.labels[index],
          leftXPadding + index * widthPerBar + widthPerBar / 2,
          height - options.fontSizeLabels / 2 - bottomYPadding
        );
      }
      remainingHeight -= options.fontSizeLabels * 1.5;
      bottomYPadding += options.fontSizeLabels * 1.5;
      ctx.restore();

      /* Draw boundaries */
      ctx.save();
      ctx.strokeStyle = 'rgb(0, 0, 0)';
      ctx.beginPath();
      if (content.topLabels != null) {
        ctx.moveTo(leftXPadding + remainingWidth, topYPadding);
        ctx.lineTo(leftXPadding, topYPadding);
      } else {
        ctx.moveTo(leftXPadding, topYPadding);
      }
      ctx.lineTo(leftXPadding, topYPadding + remainingHeight);
      ctx.lineTo(leftXPadding + remainingWidth, topYPadding + remainingHeight);
      if (content.topLabels != null) ctx.lineTo(leftXPadding + remainingWidth, topYPadding);
      ctx.stroke();
      ctx.restore();

      /* Draw y-axis label of bar chart */
      if (content.yAxis != null) {
        ctx.save();
        ctx.rotate(Math.PI * 1.5);
        ctx.font = options.fontSizeAxes + 'px ' + options.font;
        ctx.fillStyle = 'rgb(0, 0, 0)';
        ctx.textAlign = 'center';
        ctx.fillText(content.yAxis, -(topYPadding + remainingHeight / 2), leftXDrawYLabel);
        ctx.restore();
      }

      /* Draw y-axis labels */
      ctx.save();
      ctx.fillStyle = 'rgb(0, 0, 0)';
      ctx.strokeStyle = 'rgba(0, 0, 0, 0.20)';
      ctx.font = options.fontSizeTicks + 'px ' + options.font;
      ctx.textAlign = 'right';
      var tickMeta = Helpers.getLinearTicks(0, maxChartValue, Math.max(2, remainingHeight / (options.fontSizeTicks * (1 + options.paddingPercentTicks))));
      maxChartValue = tickMeta[1] + Math.ceil(maxChartValue / options.fontSizeTicks);
      var ticks = [];
      while (tickMeta[0] <= tickMeta[1]) {
        ticks.push(tickMeta[0]);
        tickMeta[0] += tickMeta[2];
      }
      for (index = 0; index < ticks.length; ++index) {
        var tickHeight = Math.round(remainingHeight * (ticks[index] / maxChartValue));
        if (options.scaleStyle == 'log2' && ticks[index] !== 0) ticks[index] = Math.round(Math.pow(2, ticks[index]));
        else ticks[index] = Math.floor(ticks[index] * 100) / 100;
        ctx.fillText(ticks[index] + '', leftXPadding - options.paddingPixelsTicks, topYPadding + remainingHeight - tickHeight);
        if (index == 0) continue;
        ctx.beginPath();
        ctx.moveTo(leftXPadding, topYPadding + remainingHeight - tickHeight);
        ctx.lineTo(leftXPadding + remainingWidth, topYPadding + remainingHeight - tickHeight);
        ctx.stroke();
      }
      ctx.restore();

      /* Draw bars */
      ctx.save();
      for (index = 0; index < content.data.length; ++index) {
        if (content.fillColor != null) {
          if (Array.isArray(content.fillColor)) ctx.fillStyle = content.fillColor[index];
          else ctx.fillStyle = content.fillColor;
        } else ctx.fillStyle = options.fillColorBars;
        if (content.strokeColor != null) {
          if (Array.isArray(content.strokeColor)) ctx.fillStyle = content.strokeColor[index];
          else ctx.fillStyle = content.strokeColor;
        } else ctx.strokeStyle = options.strokeColorBars;
        var v = content.data[index];
        if (Array.isArray(v)) v = Helpers.avg(v);
        var renderBarHeight = Math.round(remainingHeight * (v / maxChartValue));
        var renderStartX = leftXPadding + widthPerBar * index;
        var renderUpToY = topYPadding + remainingHeight - renderBarHeight;
        ctx.beginPath();
        ctx.moveTo(renderStartX + computedBarPadding, topYPadding + remainingHeight);
        ctx.lineTo(renderStartX + computedBarPadding, renderUpToY);
        ctx.lineTo(renderStartX + (widthPerBar - 1) - computedBarPadding, renderUpToY);
        ctx.lineTo(renderStartX + (widthPerBar - 1) - computedBarPadding, topYPadding + remainingHeight);
        ctx.stroke();
        ctx.fill();

        if (options.errorBarStyle === 'error') {
          var val;
          if ((val = content._data_standard_error[index]) != 0) {
            var renderBarError = Math.round(remainingHeight * (val / maxChartValue));
            ctx.beginPath();
            var wiskerWidth = Math.round((widthPerBar - computedBarPadding * 2) / 8);
            var x = leftXPadding + widthPerBar * index + widthPerBar / 2;
            ctx.moveTo(x - wiskerWidth, renderUpToY + renderBarError);
            ctx.lineTo(x + wiskerWidth, renderUpToY + renderBarError);
            ctx.moveTo(x, renderUpToY + renderBarError);
            ctx.lineTo(x, renderUpToY - renderBarError);
            ctx.moveTo(x - wiskerWidth, renderUpToY - renderBarError);
            ctx.lineTo(x + wiskerWidth, renderUpToY - renderBarError);
            ctx.stroke();
          }
        }
      }
      ctx.restore();
      ctx.translate(0.5, 0.5);
    };

    return BarChart;
  })();

  if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = BarChart;
  } else {
    window.BarChart = BarChart;
  }
})();
<|endoftext|>


<commit_before>/**
	_enyo.Popup_ is a control used to display certain content on top of other
	content.

	Popups are initially hidden on creation; they can be shown by calling the
	_show_ method and re-hidden by calling _hide_.  Popups may be centered using
	the	_centered_ property; if not centered, they should be given a specific
	position.

	A popup may be optionally floated above all application content by setting
	its _floating_ property to _true_.  This has the advantage of guaranteeing
	that the popup will be displayed on top of other content.  This usage is
	appropriate when the popup does not need to scroll along with other content.

	For more information, see the documentation on
	[Popups](https://github.com/enyojs/enyo/wiki/Popups) in the Enyo Developer
	Guide.
 */
enyo.kind({
	name: "enyo.Popup",
	classes: "enyo-popup",
	published: {
		//* Set to true to prevent controls outside the popup from receiving
		//* events while the popup is showing
		modal: false,
		//* By default, the popup will hide when the user taps outside it or
		//* presses ESC.  Set to false to prevent this behavior.
		autoDismiss: true,
		//* Set to true to render the popup in a floating layer outside of other
		//* controls.  This can be used to guarantee that the popup will be
		//* shown on top of other controls.
		floating: false,
		//* Set to true to automatically center the popup in the middle of the viewport
		centered: false
	},
	//* @protected
	showing: false,
	handlers: {
		ondown: "down",
		onkeydown: "keydown",
		ondragstart: "dragstart",
		onfocus: "focus",
		onblur: "blur",
		onRequestShow: "requestShow",
		onRequestHide: "requestHide"
	},
	captureEvents: true,
	//* @public
	events: {
		//* Fires after the popup is shown.
		onShow: "",
		//* Fires after the popup is hidden.
		onHide: ""
	},
	//* @protected
	tools: [
		{kind: "Signals", onKeydown: "keydown"}
	],
	create: function() {
		this.inherited(arguments);
		/*if (this.floating) {
			this.setParent(enyo.floatingLayer);
		}*/
		this.canGenerate = !this.floating;
	},
	render: function() {
		if (this.floating) {
			if (!enyo.floatingLayer.hasNode()) {
				enyo.floatingLayer.render();
			}
			this.parentNode = enyo.floatingLayer.hasNode();
		}
		this.inherited(arguments);
	},
	destroy: function() {
		if (this.showing) {
			this.release();
		}
		this.inherited(arguments);
	},

	reflow: function() {
		this.updatePosition();
		this.inherited(arguments);
	},
	calcViewportSize: function() {
		if (window.innerWidth) {
			return {
				width: window.innerWidth,
				height: window.innerHeight
			};
		} else {
			var e = document.documentElement;
			return {
				width: e.offsetWidth,
				height: e.offsetHeight
			};
		}
	},
	updatePosition: function() {
		if( this.centered ) {
			var d = this.calcViewportSize();
			var b = this.getBounds();

			this.addStyles( "top: " + Math.max( ( ( d.height - b.height ) / 2 ), 0 ) + "px; left: " + Math.max( ( ( d.width - b.width ) / 2 ), 0 ) + "px;" );
		}
	},
	showingChanged: function() {
		// auto render when shown.
		if (this.floating && this.showing && !this.hasNode()) {
			this.render();
		}
		// hide while sizing
		if (this.centered) {
			this.applyStyle("visibility", "hidden");
		}
		this.inherited(arguments);
		if (this.showing) {
			this.resized();
			if (this.captureEvents) {
				this.capture();
			}
		} else {
			if (this.captureEvents) {
				this.release();
			}
		}
		// show after sizing
		if (this.centered) {
			this.applyStyle("visibility", null);
		}
		// events desired due to programmatic show/hide
		if (this.hasNode()) {
			this[this.showing ? "doShow" : "doHide"]();
		}
	},
	capture: function() {
		enyo.dispatcher.capture(this, !this.modal);
	},
	release: function() {
		enyo.dispatcher.release();
	},
	down: function(inSender, inEvent) {
		//record the down event to verify in tap
		this.downEvent = inEvent;

		// prevent focus from shifting outside the popup when modal.
		if (this.modal && !inEvent.dispatchTarget.isDescendantOf(this)) {
			inEvent.preventDefault();
		}
	},
	tap: function(inSender, inEvent) {
		// dismiss on tap if property is set and click started & ended outside the popup
		if (this.autoDismiss && (!inEvent.dispatchTarget.isDescendantOf(this)) && this.downEvent &&
			(!this.downEvent.dispatchTarget.isDescendantOf(this))) {
			this.downEvent = null;
			this.hide();
			return true;
		}
	},
	// if a drag event occurs outside a popup, hide
	dragstart: function(inSender, inEvent) {
		var inScope = (inEvent.dispatchTarget === this || inEvent.dispatchTarget.isDescendantOf(this));
		if (inSender.autoDismiss && !inScope) {
			inSender.setShowing(false);
		}
		return true;
	},
	keydown: function(inSender, inEvent) {
		if (this.showing && this.autoDismiss && inEvent.keyCode == 27 /* escape */) {
			this.hide();
		}
	},
	// If something inside the popup blurred, keep track of it.
	blur: function(inSender, inEvent) {
		if (inEvent.dispatchTarget.isDescendantOf(this)) {
			this.lastFocus = inEvent.originator;
		}
	},
	// When something outside the popup focuses (e.g., due to tab key), focus our last focused control.
	focus: function(inSender, inEvent) {
		var dt = inEvent.dispatchTarget;
		if (this.modal && !dt.isDescendantOf(this)) {
			if (dt.hasNode()) {
				dt.node.blur();
			}
			var n = (this.lastFocus && this.lastFocus.hasNode()) || this.hasNode();
			if (n) {
				n.focus();
			}
		}
	},
	requestShow: function(inSender, inEvent) {
		this.show();
		return true;
	},
	requestHide: function(inSender, inEvent) {
		this.hide();
		return true;
	}
});
<commit_msg>Add public showAtEvent method to enyo.Popup for easier positioning near mouse events Enyo-DCO-1.1-Signed-off-by: Ian Beck <ian@onecrayon.com><commit_after>/**
	_enyo.Popup_ is a control used to display certain content on top of other
	content.

	Popups are initially hidden on creation; they can be shown by calling the
	_show_ method and re-hidden by calling _hide_.  Popups may be centered using
	the	_centered_ property; if not centered, they should be given a specific
	position.

	A popup may be optionally floated above all application content by setting
	its _floating_ property to _true_.  This has the advantage of guaranteeing
	that the popup will be displayed on top of other content.  This usage is
	appropriate when the popup does not need to scroll along with other content.

	For more information, see the documentation on
	[Popups](https://github.com/enyojs/enyo/wiki/Popups) in the Enyo Developer
	Guide.
 */
enyo.kind({
	name: "enyo.Popup",
	classes: "enyo-popup",
	published: {
		//* Set to true to prevent controls outside the popup from receiving
		//* events while the popup is showing
		modal: false,
		//* By default, the popup will hide when the user taps outside it or
		//* presses ESC.  Set to false to prevent this behavior.
		autoDismiss: true,
		//* Set to true to render the popup in a floating layer outside of other
		//* controls.  This can be used to guarantee that the popup will be
		//* shown on top of other controls.
		floating: false,
		//* Set to true to automatically center the popup in the middle of the viewport
		centered: false
	},
	//* @protected
	showing: false,
	handlers: {
		ondown: "down",
		onkeydown: "keydown",
		ondragstart: "dragstart",
		onfocus: "focus",
		onblur: "blur",
		onRequestShow: "requestShow",
		onRequestHide: "requestHide"
	},
	captureEvents: true,
	//* @public
	events: {
		//* Fires after the popup is shown.
		onShow: "",
		//* Fires after the popup is hidden.
		onHide: ""
	},
	//* @protected
	tools: [
		{kind: "Signals", onKeydown: "keydown"}
	],
	create: function() {
		this.inherited(arguments);
		/*if (this.floating) {
			this.setParent(enyo.floatingLayer);
		}*/
		this.canGenerate = !this.floating;
	},
	render: function() {
		if (this.floating) {
			if (!enyo.floatingLayer.hasNode()) {
				enyo.floatingLayer.render();
			}
			this.parentNode = enyo.floatingLayer.hasNode();
		}
		this.inherited(arguments);
	},
	destroy: function() {
		if (this.showing) {
			this.release();
		}
		this.inherited(arguments);
	},

	reflow: function() {
		this.updatePosition();
		this.inherited(arguments);
	},
	calcViewportSize: function() {
		if (window.innerWidth) {
			return {
				width: window.innerWidth,
				height: window.innerHeight
			};
		} else {
			var e = document.documentElement;
			return {
				width: e.offsetWidth,
				height: e.offsetHeight
			};
		}
	},
	updatePosition: function() {
		var d = this.calcViewportSize();
		var b = this.getBounds();

		if (this.targetPosition) {
			// For brevity's sake...
			var p = this.targetPosition;

			// Test and optionally adjust our target bounds (only first is commented, because logic is effectively identical for all scenarios)
			if (typeof p.left === 'number') {
				// If popup will be outside window bounds, switch anchor
				if (p.left + b.width > d.width) {
					if (p.left - b.width >= 0) {
						// Switching to right corner will fit in window
						p.right = d.width - p.left;
					} else {
						// Neither corner will work; stick at side of window
						p.right = 0;
					}
					p.left = null;
				} else {
					p.right = null;
				}
			} else if (typeof p.right === 'number') {
				if (p.right - b.width < 0) {
					if (p.right + b.width <= d.width) {
						p.left = d.width - p.right;
					} else {
						p.left = 0;
					}
					p.right = null;
				} else {
					p.left = null;
				}
			}

			if (typeof p.top === 'number') {
				if (p.top + b.height > d.height) {
					if (p.top - b.height > 0) {
						p.bottom = d.height - p.top;
					} else {
						p.bottom = 0;
					}
					p.top = null;
				} else {
					p.bottom = null;
				}
			} else if (typeof p.bottom === 'number') {
				if (p.bottom - b.height < 0) {
					if (p.bottom + b.height <= d.height) {
						p.top = d.height - p.bottom;
					} else {
						p.top = 0;
					}
					p.bottom = null;
				} else {
					p.top = null;
				}
			}

			// 'initial' values are necessary to override positioning rules in the CSS
			this.addStyles('left: ' + (p.left !== null ? p.left + 'px' : 'initial') + '; right: ' + (p.right !== null ? p.right + 'px' : 'initial') + '; top: ' + (p.top !== null ? p.top + 'px' : 'initial') + '; bottom: ' + (p.bottom !== null ? p.bottom + 'px' : 'initial') + ';');
		} else if (this.centered) {
			this.addStyles( "top: " + Math.max( ( ( d.height - b.height ) / 2 ), 0 ) + "px; left: " + Math.max( ( ( d.width - b.width ) / 2 ), 0 ) + "px;" );
		}
	},
	showingChanged: function() {
		// auto render when shown.
		if (this.floating && this.showing && !this.hasNode()) {
			this.render();
		}
		// hide while sizing, and move to top corner for accurate sizing
		if (this.centered || this.targetPosition) {
			this.applyStyle("visibility", "hidden");
			this.addStyles("top: 0px; left: 0px; right: initial; bottom: initial;");
		}
		this.inherited(arguments);
		if (this.showing) {
			this.resized();
			if (this.captureEvents) {
				this.capture();
			}
		} else {
			if (this.captureEvents) {
				this.release();
			}
		}
		// show after sizing
		if (this.centered || this.targetPosition) {
			this.applyStyle("visibility", null);
		}
		// events desired due to programmatic show/hide
		if (this.hasNode()) {
			this[this.showing ? "doShow" : "doHide"]();
		}
	},
	capture: function() {
		enyo.dispatcher.capture(this, !this.modal);
	},
	release: function() {
		enyo.dispatcher.release();
	},
	down: function(inSender, inEvent) {
		//record the down event to verify in tap
		this.downEvent = inEvent;

		// prevent focus from shifting outside the popup when modal.
		if (this.modal && !inEvent.dispatchTarget.isDescendantOf(this)) {
			inEvent.preventDefault();
		}
	},
	tap: function(inSender, inEvent) {
		// dismiss on tap if property is set and click started & ended outside the popup
		if (this.autoDismiss && (!inEvent.dispatchTarget.isDescendantOf(this)) && this.downEvent &&
			(!this.downEvent.dispatchTarget.isDescendantOf(this))) {
			this.downEvent = null;
			this.hide();
			return true;
		}
	},
	// if a drag event occurs outside a popup, hide
	dragstart: function(inSender, inEvent) {
		var inScope = (inEvent.dispatchTarget === this || inEvent.dispatchTarget.isDescendantOf(this));
		if (inSender.autoDismiss && !inScope) {
			inSender.setShowing(false);
		}
		return true;
	},
	keydown: function(inSender, inEvent) {
		if (this.showing && this.autoDismiss && inEvent.keyCode == 27 /* escape */) {
			this.hide();
		}
	},
	// If something inside the popup blurred, keep track of it.
	blur: function(inSender, inEvent) {
		if (inEvent.dispatchTarget.isDescendantOf(this)) {
			this.lastFocus = inEvent.originator;
		}
	},
	// When something outside the popup focuses (e.g., due to tab key), focus our last focused control.
	focus: function(inSender, inEvent) {
		var dt = inEvent.dispatchTarget;
		if (this.modal && !dt.isDescendantOf(this)) {
			if (dt.hasNode()) {
				dt.node.blur();
			}
			var n = (this.lastFocus && this.lastFocus.hasNode()) || this.hasNode();
			if (n) {
				n.focus();
			}
		}
	},
	requestShow: function(inSender, inEvent) {
		this.show();
		return true;
	},
	requestHide: function(inSender, inEvent) {
		this.hide();
		return true;
	},

	//* @public
	/**
		Open at the location of a mouse event (_inEvent_). The popup's
		position is automatically constrained so that it does not
		display outside the viewport.

		_inOffset_ is an object which may contain left and top
		properties to specify an offset relative to the location the
		popup would otherwise be positioned.
	*/
	showAtEvent: function(inEvent, inOffset) {
		// Calculate our ideal target based on the event position and offset
		var p = {
			left: inEvent.centerX || inEvent.clientX || inEvent.pageX,
			top: inEvent.centerY || inEvent.clientY || inEvent.pageY
		};
		if (inOffset) {
			p.left += inOffset.left || 0;
			p.top += inOffset.top || 0;
		}

		// Save our target position for later processing
		this.targetPosition = p;

		// Show the dialog
		this.show();
	}
});
<|endoftext|>


<commit_before>
/**
 * WPCOM module
 */

var WPCOM = require('../');
var Site = require('../lib/site');
var Media = require('../lib/media');
var util = require('./util');
var fs = require('fs');
var assert = require('assert');

/**
 * Testing data
 */

var test = require('./data');

/**
 * WPCOM instance
 */

describe('WPCOM#Site#Media', function(){
  var post_added;

  // Create a new_media before to start the tests

  var new_media;
  before(function(done){
    util.addMedia(function(err, media) {
      if (err) throw err;

      new_media = media;
      done();
    });
  });

  after(function(done){
    var site = util.private_site();

    // clean new_post post
    site.deleteMedia(media_added.media[0].id, function(err, data) {
      if (err) throw err;

      // clean post_added post
      site.deleteMedia(media_added.media[1].id, function(err, data) {
        if (err) throw err;
        done();
      });
    });
  });

  describe('sync', function(){

    it('should create an `Media` instance from `Site`', function(){
      var media = WPCOM().site().media();
      assert.ok(media instanceof Media);
    });

  });

  describe('async', function(){

    describe('media.get()', function(){

      it('should get added media', function(done){
        var site = util.private_site();
        var media = site.media(test.media_id);

        media.get(function(err, info){
          if (err) throw err;

          assert.equal(3, info.id);
          done();
        });
      });

    });

    describe('media.update()', function(){

      it('should edit the media title', function(done){
        var site = util.private_site();
        var edited_title = "This is the new title";

        site
        .media(new_media.media[0].id)
        .update( { title: edited_title }, function(err, data){
          if (err) throw err;

          assert.ok(data);
          assert.equal(edited_title, data.title);

          done();
        });
      });

    });

    describe('media.addFiles([fs])', function(){

      it('should create a new media from a file', function(done){
        var site = util.private_site();

        // pass streams
        var files = [];
        for (var i = 0; i < test.new_media_data.files.length; i++) {
          files.push(fs.createReadStream(test.new_media_data.files[i]));
        }

        site
        .media()
        .addFiles(files, function(err, data){
          if (err) throw err;

          assert.ok(data);
          assert.ok(data.media instanceof Array);
          assert.equal(test.new_media_data.files.length, data.media.length);
          done();
        });

      });

    });

    describe('media.addUrls([\'url1\', \'url2\'])', function(){

      it('should create a new media', function(done){
        var site = util.private_site();

        site
        .media()
        .addUrls(test.new_media_data.media_urls, function(err, data){
          if (err) throw err;

          assert.ok(data);
          assert.ok(data.media instanceof Array);
          assert.equal(test.new_media_data.media_urls.length, data.media.length);

          media_added = data;

          done();
        });

      });

    });

    describe('media.delete()', function(){

      it('should delete a media', function(done){
        var site = util.private_site();

        site
        .media(new_media.media[0].id)
        .del(function(err, data){
          if (err) throw err;

          assert.equal(new_media.media[0].id, data.id);
          done();
        });

      });

    });

  });

});
<commit_msg>test: update to ID media property<commit_after>
/**
 * WPCOM module
 */

var WPCOM = require('../');
var Site = require('../lib/site');
var Media = require('../lib/media');
var util = require('./util');
var fs = require('fs');
var assert = require('assert');

/**
 * Testing data
 */

var test = require('./data');

/**
 * WPCOM instance
 */

describe('WPCOM#Site#Media', function(){
  var media_added;

  // Create a new_media before to start the tests

  var new_media;
  before(function(done){
    util.addMedia(function(err, media) {
      if (err) throw err;

      new_media = media;
      done();
    });
  });

  after(function(done){
    var site = util.private_site();

    // clean new_post post
    site.deleteMedia(media_added.media[0].ID, function(err, data) {
      if (err) throw err;

      // clean media_added post
      site.deleteMedia(media_added.media[1].ID, function(err, data) {
        if (err) throw err;
        done();
      });
    });
  });

  describe('sync', function(){

    it('should create an `Media` instance from `Site`', function(){
      var media = WPCOM().site().media();
      assert.ok(media instanceof Media);
    });

  });

  describe('async', function(){

    describe('media.get()', function(){

      it('should get added media', function(done){
        var site = util.private_site();
        var media = site.media(test.media_id);

        media.get(function(err, info){
          if (err) throw err;

          assert.equal(3, info.ID);
          done();
        });
      });

    });

    describe('media.update()', function(){

      it('should edit the media title', function(done){
        var site = util.private_site();
        var edited_title = "This is the new title";

        site
        .media(new_media.media[0].ID)
        .update( { title: edited_title }, function(err, data){
          if (err) throw err;

          assert.ok(data);
          assert.equal(edited_title, data.title);

          done();
        });
      });

    });

    describe('media.addFiles([fs])', function(){

      it('should create a new media from a file', function(done){
        var site = util.private_site();

        // pass streams
        var files = [];
        for (var i = 0; i < test.new_media_data.files.length; i++) {
          files.push(fs.createReadStream(test.new_media_data.files[i]));
        }

        site
        .media()
        .addFiles(files, function(err, data){
          if (err) throw err;

          assert.ok(data);
          assert.ok(data.media instanceof Array);
          assert.equal(test.new_media_data.files.length, data.media.length);
          done();
        });

      });

    });

    describe('media.addUrls([\'url1\', \'url2\'])', function(){

      it('should create a new media', function(done){
        var site = util.private_site();

        site
        .media()
        .addUrls(test.new_media_data.media_urls, function(err, data){
          if (err) throw err;

          assert.ok(data);
          assert.ok(data.media instanceof Array);
          assert.equal(test.new_media_data.media_urls.length, data.media.length);

          media_added = data;

          done();
        });

      });

    });

    describe('media.delete()', function(){

      it('should delete a media', function(done){
        var site = util.private_site();

        site
        .media(new_media.media[0].ID)
        .del(function(err, data){
          if (err) throw err;

          assert.equal(new_media.media[0].ID, data.ID);
          done();
        });

      });

    });

  });

});
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import {injectIntl, intlShape} from 'react-intl'
import _isEqual from 'lodash/isEqual'

import Button from '../../Button'
import {
  StyledDateAbstractControl,
  StyledDateAbstractInput,
  StyledDateAbstractWrapper
} from './StyledDateAbstract'

class DateAbstract extends React.Component {
  Flatpickr = null

  constructor(props) {
    super(props)
    this.wrapper = React.createRef()

    this.state = {altInput: ''}

    import(/* webpackChunkName: "flatpickr" */ '!style-loader!css-loader!flatpickr/dist/themes/light.css')

    Promise.all([
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/de.js'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/fr.js'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/it.js')
    ]).then(response => {
      this.Flatpickr = response[0].default
      this.localeMap = {
        'de-CH': response[1].German,
        'de': response[1].German,
        'fr': response[2].French,
        'it': response[3].Italian
      }

      this.initializeFlatPickr()
    })
  }

  initializeFlatPickr = flatpickr => {
    const locale = this.localeMap[this.props.intl.locale]

    this.options = {
      wrap: true,
      onChange: this.handleOnChange,
      altInput: true,
      altInputClass: '',
      clickOpens: !this.props.immutable,
      defaultDate: this.props.value,
      ...(locale ? {locale} : {}),
      ...(this.props.options ? this.props.options.flatpickrOptions : {})
    }

    this.flatpickr = new this.Flatpickr(this.wrapper.current, this.options)
    this.flatpickr.calendarContainer.classList.add('tocco-ui-theme')

    if (this.props.initialized) {
      this.props.initialized()
    }
    this.setState({altInput: this.flatpickr.altInput.value})
  }

  getLocale = localeCode => {
    if (this.localeMap) {
      let locale = this.localeMap[localeCode]

      // Fallback english
      if (!locale && this.Flatpickr) {
        locale = this.Flatpickr.l10ns.en
      }
      return locale
    }
    return null
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    if (this.Flatpickr && this.flatpickr) {
      if (!_isEqual(
        prevProps.options.flatpickrOptions.altFormat,
        this.props.options.flatpickrOptions.altFormat
      )) {
        this.flatpickr.set('altFormat', this.props.options.flatpickrOptions.altFormat)
        this.flatpickr.redraw()
      }
      if (!_isEqual(prevProps.intl.locale, this.props.intl.locale)) {
        const locale = this.getLocale(this.props.intl.locale)
        this.Flatpickr.localize(locale)
        this.flatpickr.set('locale', locale)
        this.flatpickr.redraw()
      }
      if (!_isEqual(prevProps.value, this.props.value)) {
        this.flatpickr.setDate(this.props.value, false)
        this.flatpickr.redraw()
      }
    }
  }

  componentWillUnmount() {
    this.flatpickr.destroy()
  }

  handleOnChange = selectedDates => {
    const isoStrings = selectedDates.map(date => date.toISOString())
    this.props.onChange(isoStrings)
  }

  hasValue = () => {
    return this.props.value && this.props.value.length > 0 && this.props.value.every(v => v)
  }

  handleOnBlur = () => {
    if (this.props.onBlur) {
      const altValue = this.flatpickr.altInput.value
      this.props.onBlur(altValue, this.flatpickr.selectedDates, r => this.flatpickr.setDate(r, true))
    }
  }

  render() {
    return (
      <StyledDateAbstractWrapper
        data-wrap
        onBlur={this.handleOnBlur}
        immutable={this.props.immutable}
        ref={this.wrapper}
      >
        <StyledDateAbstractInput
          type="text"
          data-input
          immutable={this.props.immutable}
          {...(this.props.options ? {placeholder: this.props.options.placeholderText} : {})}
        />
        <StyledDateAbstractInput
          disabled
          immutable={this.props.immutable}
          value={this.state.altInput}
        />
        <StyledDateAbstractControl
          data-clear
          hideButton={!this.hasValue() || this.props.immutable}
        >
          <Button
            icon="times"
            look="ball"
            tabIndex={-1}
          />
        </StyledDateAbstractControl>
      </StyledDateAbstractWrapper>
    )
  }
}

DateAbstract.propTypes = {
  intl: intlShape.isRequired,
  onBlur: PropTypes.func,
  onChange: PropTypes.func,
  value: PropTypes.arrayOf(PropTypes.string),
  options: PropTypes.shape({
    placeholderText: PropTypes.string,
    flatpickrOptions: PropTypes.object
  }),
  immutable: PropTypes.bool,
  initialized: PropTypes.func,
  events: PropTypes.shape({
    onFocus: PropTypes.func
  })
}

export default injectIntl(DateAbstract)
<commit_msg>fix(tocco-ui): declare font family for date pickers<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import {injectIntl, intlShape} from 'react-intl'
import _isEqual from 'lodash/isEqual'
import {withTheme} from 'styled-components'

import {theme} from '../../utilStyles'
import Button from '../../Button'
import {
  StyledDateAbstractControl,
  StyledDateAbstractInput,
  StyledDateAbstractWrapper
} from './StyledDateAbstract'

class DateAbstract extends React.Component {
  Flatpickr = null

  constructor(props) {
    super(props)
    this.wrapper = React.createRef()

    this.state = {altInput: ''}

    import(/* webpackChunkName: "flatpickr" */ '!style-loader!css-loader!flatpickr/dist/themes/light.css')

    Promise.all([
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/de.js'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/fr.js'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/it.js')
    ]).then(response => {
      this.Flatpickr = response[0].default
      this.localeMap = {
        'de-CH': response[1].German,
        'de': response[1].German,
        'fr': response[2].French,
        'it': response[3].Italian
      }

      this.initializeFlatPickr()
    })
  }

  initializeFlatPickr = flatpickr => {
    const locale = this.localeMap[this.props.intl.locale]

    this.options = {
      wrap: true,
      onChange: this.handleOnChange,
      altInput: true,
      altInputClass: '',
      clickOpens: !this.props.immutable,
      defaultDate: this.props.value,
      ...(locale ? {locale} : {}),
      ...(this.props.options ? this.props.options.flatpickrOptions : {})
    }

    this.flatpickr = new this.Flatpickr(this.wrapper.current, this.options)
    this.flatpickr.calendarContainer.classList.add('tocco-ui-theme')
    this.flatpickr.calendarContainer.style.fontFamily = theme.fontFamily('regular')(this.props)

    if (this.props.initialized) {
      this.props.initialized()
    }
    this.setState({altInput: this.flatpickr.altInput.value})
  }

  getLocale = localeCode => {
    if (this.localeMap) {
      let locale = this.localeMap[localeCode]

      // Fallback english
      if (!locale && this.Flatpickr) {
        locale = this.Flatpickr.l10ns.en
      }
      return locale
    }
    return null
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    if (this.Flatpickr && this.flatpickr) {
      if (!_isEqual(
        prevProps.options.flatpickrOptions.altFormat,
        this.props.options.flatpickrOptions.altFormat
      )) {
        this.flatpickr.set('altFormat', this.props.options.flatpickrOptions.altFormat)
        this.flatpickr.redraw()
      }
      if (!_isEqual(prevProps.intl.locale, this.props.intl.locale)) {
        const locale = this.getLocale(this.props.intl.locale)
        this.Flatpickr.localize(locale)
        this.flatpickr.set('locale', locale)
        this.flatpickr.redraw()
      }
      if (!_isEqual(prevProps.value, this.props.value)) {
        this.flatpickr.setDate(this.props.value, false)
        this.flatpickr.redraw()
      }
    }
  }

  componentWillUnmount() {
    this.flatpickr.destroy()
  }

  handleOnChange = selectedDates => {
    const isoStrings = selectedDates.map(date => date.toISOString())
    this.props.onChange(isoStrings)
  }

  hasValue = () => {
    return this.props.value && this.props.value.length > 0 && this.props.value.every(v => v)
  }

  handleOnBlur = () => {
    if (this.props.onBlur) {
      const altValue = this.flatpickr.altInput.value
      this.props.onBlur(altValue, this.flatpickr.selectedDates, r => this.flatpickr.setDate(r, true))
    }
  }

  render() {
    return (
      <StyledDateAbstractWrapper
        data-wrap
        onBlur={this.handleOnBlur}
        immutable={this.props.immutable}
        ref={this.wrapper}
      >
        <StyledDateAbstractInput
          type="text"
          data-input
          immutable={this.props.immutable}
          {...(this.props.options ? {placeholder: this.props.options.placeholderText} : {})}
        />
        <StyledDateAbstractInput
          disabled
          immutable={this.props.immutable}
          value={this.state.altInput}
        />
        <StyledDateAbstractControl
          data-clear
          hideButton={!this.hasValue() || this.props.immutable}
        >
          <Button
            icon="times"
            look="ball"
            tabIndex={-1}
          />
        </StyledDateAbstractControl>
      </StyledDateAbstractWrapper>
    )
  }
}

DateAbstract.propTypes = {
  intl: intlShape.isRequired,
  onBlur: PropTypes.func,
  onChange: PropTypes.func,
  value: PropTypes.arrayOf(PropTypes.string),
  options: PropTypes.shape({
    placeholderText: PropTypes.string,
    flatpickrOptions: PropTypes.object
  }),
  immutable: PropTypes.bool,
  initialized: PropTypes.func,
  events: PropTypes.shape({
    onFocus: PropTypes.func
  })
}

export default withTheme(injectIntl(DateAbstract))
<|endoftext|>