<commit_before>/**
 * @license
 * Copyright 2012 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Image field.  Used for pictures, icons, etc.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

goog.module('Blockly.FieldImage');
goog.module.declareLegacyNamespace();

const Field = goog.require('Blockly.Field');
const Size = goog.require('Blockly.utils.Size');
const Svg = goog.require('Blockly.utils.Svg');
const fieldRegistry = goog.require('Blockly.fieldRegistry');
const {createSvgElement, XLINK_NS} = goog.require('Blockly.utils.dom');
const {inherits} = goog.require('Blockly.utils.object');
const {replaceMessageReferences} = goog.require('Blockly.utils');

/**
 * Class for an image on a block.
 * @param {string} src The URL of the image.
 * @param {!(string|number)} width Width of the image.
 * @param {!(string|number)} height Height of the image.
 * @param {string=} opt_alt Optional alt text for when block is collapsed.
 * @param {function(!FieldImage)=} opt_onClick Optional function to be
 *     called when the image is clicked. If opt_onClick is defined, opt_alt must
 *     also be defined.
 * @param {boolean=} opt_flipRtl Whether to flip the icon in RTL.
 * @param {Object=} opt_config A map of options used to configure the field.
 *    See the [field creation documentation]{@link https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/image#creation}
 *    for a list of properties this parameter supports.
 * @extends {Field}
 * @constructor
 */
const FieldImage = function(src, width, height,
    opt_alt, opt_onClick, opt_flipRtl, opt_config) {
  // Return early.
  if (!src) {
    throw Error('Src value of an image field is required');
  }
  src = replaceMessageReferences(src);
  const imageHeight = Number(replaceMessageReferences(height));
  const imageWidth = Number(replaceMessageReferences(width));
  if (isNaN(imageHeight) || isNaN(imageWidth)) {
    throw Error('Height and width values of an image field must cast to' +
      ' numbers.');
  }
  if (imageHeight <= 0 || imageWidth <= 0) {
    throw Error('Height and width values of an image field must be greater' +
      ' than 0.');
  }

  // Initialize configurable properties.
  /**
   * Whether to flip this image in RTL.
   * @type {boolean}
   * @private
   */
  this.flipRtl_ = false;

  /**
   * Alt text of this image.
   * @type {string}
   * @private
   */
  this.altText_ = '';

  FieldImage.superClass_.constructor.call(
      this, src, null, opt_config);

  if (!opt_config) {  // If the config wasn't passed, do old configuration.
    this.flipRtl_ = !!opt_flipRtl;
    this.altText_ = replaceMessageReferences(opt_alt) || '';
  }

  // Initialize other properties.
  /**
   * The size of the area rendered by the field.
   * @type {Size}
   * @protected
   * @override
   */
  this.size_ = new Size(imageWidth,
      imageHeight + FieldImage.Y_PADDING);

  /**
   * Store the image height, since it is different from the field height.
   * @type {number}
   * @private
   */
  this.imageHeight_ = imageHeight;

  /**
   * The function to be called when this field is clicked.
   * @type {?function(!FieldImage)}
   * @private
   */
  this.clickHandler_ = null;

  if (typeof opt_onClick == 'function') {
    this.clickHandler_ = opt_onClick;
  }

  /**
   * The rendered field's image element.
   * @type {SVGImageElement}
   * @private
   */
  this.imageElement_ = null;
};
inherits(FieldImage, Field);

/**
 * The default value for this field.
 * @type {*}
 * @protected
 */
FieldImage.prototype.DEFAULT_VALUE = '';

/**
 * Construct a FieldImage from a JSON arg object,
 * dereferencing any string table references.
 * @param {!Object} options A JSON object with options (src, width, height,
 *    alt, and flipRtl).
 * @return {!FieldImage} The new field instance.
 * @package
 * @nocollapse
 */
FieldImage.fromJson = function(options) {
  // `this` might be a subclass of FieldImage if that class doesn't override
  // the static fromJson method.
  return new this(options['src'], options['width'], options['height'],
      undefined, undefined, undefined, options);
};

/**
 * Vertical padding below the image, which is included in the reported height of
 * the field.
 * @type {number}
 * @private
 */
FieldImage.Y_PADDING = 1;

/**
 * Editable fields usually show some sort of UI indicating they are
 * editable. This field should not.
 * @type {boolean}
 */
FieldImage.prototype.EDITABLE = false;

/**
 * Used to tell if the field needs to be rendered the next time the block is
 * rendered. Image fields are statically sized, and only need to be
 * rendered at initialization.
 * @type {boolean}
 * @protected
 */
FieldImage.prototype.isDirty_ = false;

/**
 * Configure the field based on the given map of options.
 * @param {!Object} config A map of options to configure the field based on.
 * @protected
 * @override
 */
FieldImage.prototype.configure_ = function(config) {
  FieldImage.superClass_.configure_.call(this, config);
  this.flipRtl_ = !!config['flipRtl'];
  this.altText_ = replaceMessageReferences(config['alt']) || '';
};

/**
 * Create the block UI for this image.
 * @package
 */
FieldImage.prototype.initView = function() {
  this.imageElement_ = createSvgElement(
      Svg.IMAGE,
      {
        'height': this.imageHeight_ + 'px',
        'width': this.size_.width + 'px',
        'alt': this.altText_
      },
      this.fieldGroup_);
  this.imageElement_.setAttributeNS(XLINK_NS,
      'xlink:href', /** @type {string} */ (this.value_));

  if (this.clickHandler_) {
    this.imageElement_.style.cursor = 'pointer';
  }
};

/**
 * @override
 */
FieldImage.prototype.updateSize_ = function() {
  // NOP
};

/**
 * Ensure that the input value (the source URL) is a string.
 * @param {*=} opt_newValue The input value.
 * @return {?string} A string, or null if invalid.
 * @protected
 */
FieldImage.prototype.doClassValidation_ = function(opt_newValue) {
  if (typeof opt_newValue != 'string') {
    return null;
  }
  return opt_newValue;
};

/**
 * Update the value of this image field, and update the displayed image.
 * @param {*} newValue The value to be saved. The default validator guarantees
 * that this is a string.
 * @protected
 */
FieldImage.prototype.doValueUpdate_ = function(newValue) {
  this.value_ = newValue;
  if (this.imageElement_) {
    this.imageElement_.setAttributeNS(XLINK_NS,
        'xlink:href', String(this.value_));
  }
};

/**
 * Get whether to flip this image in RTL
 * @return {boolean} True if we should flip in RTL.
 * @override
 */
FieldImage.prototype.getFlipRtl = function() {
  return this.flipRtl_;
};

/**
 * Set the alt text of this image.
 * @param {?string} alt New alt text.
 * @public
 */
FieldImage.prototype.setAlt = function(alt) {
  if (alt == this.altText_) {
    return;
  }
  this.altText_ = alt || '';
  if (this.imageElement_) {
    this.imageElement_.setAttribute('alt', this.altText_);
  }
};

/**
 * If field click is called, and click handler defined,
 * call the handler.
 * @protected
 */
FieldImage.prototype.showEditor_ = function() {
  if (this.clickHandler_) {
    this.clickHandler_(this);
  }
};

/**
 * Set the function that is called when this image  is clicked.
 * @param {?function(!FieldImage)} func The function that is called
 *    when the image is clicked, or null to remove.
 */
FieldImage.prototype.setOnClickHandler = function(func) {
  this.clickHandler_ = func;
};

/**
 * Use the `getText_` developer hook to override the field's text
 * representation.
 * Return the image alt text instead.
 * @return {?string} The image alt text.
 * @protected
 * @override
 */
FieldImage.prototype.getText_ = function() {
  return this.altText_;
};

fieldRegistry.register('field_image', FieldImage);

exports = FieldImage;
<commit_msg>clang-format core/field_image.js<commit_after>/**
 * @license
 * Copyright 2012 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Image field.  Used for pictures, icons, etc.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

goog.module('Blockly.FieldImage');
goog.module.declareLegacyNamespace();

const Field = goog.require('Blockly.Field');
const Size = goog.require('Blockly.utils.Size');
const Svg = goog.require('Blockly.utils.Svg');
const fieldRegistry = goog.require('Blockly.fieldRegistry');
const {createSvgElement, XLINK_NS} = goog.require('Blockly.utils.dom');
const {inherits} = goog.require('Blockly.utils.object');
const {replaceMessageReferences} = goog.require('Blockly.utils');

/**
 * Class for an image on a block.
 * @param {string} src The URL of the image.
 * @param {!(string|number)} width Width of the image.
 * @param {!(string|number)} height Height of the image.
 * @param {string=} opt_alt Optional alt text for when block is collapsed.
 * @param {function(!FieldImage)=} opt_onClick Optional function to be
 *     called when the image is clicked. If opt_onClick is defined, opt_alt must
 *     also be defined.
 * @param {boolean=} opt_flipRtl Whether to flip the icon in RTL.
 * @param {Object=} opt_config A map of options used to configure the field.
 *    See the [field creation documentation]{@link
 * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/image#creation}
 *    for a list of properties this parameter supports.
 * @extends {Field}
 * @constructor
 */
const FieldImage = function(
    src, width, height, opt_alt, opt_onClick, opt_flipRtl, opt_config) {
  // Return early.
  if (!src) {
    throw Error('Src value of an image field is required');
  }
  src = replaceMessageReferences(src);
  const imageHeight = Number(replaceMessageReferences(height));
  const imageWidth = Number(replaceMessageReferences(width));
  if (isNaN(imageHeight) || isNaN(imageWidth)) {
    throw Error(
        'Height and width values of an image field must cast to' +
        ' numbers.');
  }
  if (imageHeight <= 0 || imageWidth <= 0) {
    throw Error(
        'Height and width values of an image field must be greater' +
        ' than 0.');
  }

  // Initialize configurable properties.
  /**
   * Whether to flip this image in RTL.
   * @type {boolean}
   * @private
   */
  this.flipRtl_ = false;

  /**
   * Alt text of this image.
   * @type {string}
   * @private
   */
  this.altText_ = '';

  FieldImage.superClass_.constructor.call(this, src, null, opt_config);

  if (!opt_config) {  // If the config wasn't passed, do old configuration.
    this.flipRtl_ = !!opt_flipRtl;
    this.altText_ = replaceMessageReferences(opt_alt) || '';
  }

  // Initialize other properties.
  /**
   * The size of the area rendered by the field.
   * @type {Size}
   * @protected
   * @override
   */
  this.size_ = new Size(imageWidth, imageHeight + FieldImage.Y_PADDING);

  /**
   * Store the image height, since it is different from the field height.
   * @type {number}
   * @private
   */
  this.imageHeight_ = imageHeight;

  /**
   * The function to be called when this field is clicked.
   * @type {?function(!FieldImage)}
   * @private
   */
  this.clickHandler_ = null;

  if (typeof opt_onClick == 'function') {
    this.clickHandler_ = opt_onClick;
  }

  /**
   * The rendered field's image element.
   * @type {SVGImageElement}
   * @private
   */
  this.imageElement_ = null;
};
inherits(FieldImage, Field);

/**
 * The default value for this field.
 * @type {*}
 * @protected
 */
FieldImage.prototype.DEFAULT_VALUE = '';

/**
 * Construct a FieldImage from a JSON arg object,
 * dereferencing any string table references.
 * @param {!Object} options A JSON object with options (src, width, height,
 *    alt, and flipRtl).
 * @return {!FieldImage} The new field instance.
 * @package
 * @nocollapse
 */
FieldImage.fromJson = function(options) {
  // `this` might be a subclass of FieldImage if that class doesn't override
  // the static fromJson method.
  return new this(
      options['src'], options['width'], options['height'], undefined, undefined,
      undefined, options);
};

/**
 * Vertical padding below the image, which is included in the reported height of
 * the field.
 * @type {number}
 * @private
 */
FieldImage.Y_PADDING = 1;

/**
 * Editable fields usually show some sort of UI indicating they are
 * editable. This field should not.
 * @type {boolean}
 */
FieldImage.prototype.EDITABLE = false;

/**
 * Used to tell if the field needs to be rendered the next time the block is
 * rendered. Image fields are statically sized, and only need to be
 * rendered at initialization.
 * @type {boolean}
 * @protected
 */
FieldImage.prototype.isDirty_ = false;

/**
 * Configure the field based on the given map of options.
 * @param {!Object} config A map of options to configure the field based on.
 * @protected
 * @override
 */
FieldImage.prototype.configure_ = function(config) {
  FieldImage.superClass_.configure_.call(this, config);
  this.flipRtl_ = !!config['flipRtl'];
  this.altText_ = replaceMessageReferences(config['alt']) || '';
};

/**
 * Create the block UI for this image.
 * @package
 */
FieldImage.prototype.initView = function() {
  this.imageElement_ = createSvgElement(
      Svg.IMAGE, {
        'height': this.imageHeight_ + 'px',
        'width': this.size_.width + 'px',
        'alt': this.altText_
      },
      this.fieldGroup_);
  this.imageElement_.setAttributeNS(
      XLINK_NS, 'xlink:href', /** @type {string} */ (this.value_));

  if (this.clickHandler_) {
    this.imageElement_.style.cursor = 'pointer';
  }
};

/**
 * @override
 */
FieldImage.prototype.updateSize_ = function() {
  // NOP
};

/**
 * Ensure that the input value (the source URL) is a string.
 * @param {*=} opt_newValue The input value.
 * @return {?string} A string, or null if invalid.
 * @protected
 */
FieldImage.prototype.doClassValidation_ = function(opt_newValue) {
  if (typeof opt_newValue != 'string') {
    return null;
  }
  return opt_newValue;
};

/**
 * Update the value of this image field, and update the displayed image.
 * @param {*} newValue The value to be saved. The default validator guarantees
 * that this is a string.
 * @protected
 */
FieldImage.prototype.doValueUpdate_ = function(newValue) {
  this.value_ = newValue;
  if (this.imageElement_) {
    this.imageElement_.setAttributeNS(
        XLINK_NS, 'xlink:href', String(this.value_));
  }
};

/**
 * Get whether to flip this image in RTL
 * @return {boolean} True if we should flip in RTL.
 * @override
 */
FieldImage.prototype.getFlipRtl = function() {
  return this.flipRtl_;
};

/**
 * Set the alt text of this image.
 * @param {?string} alt New alt text.
 * @public
 */
FieldImage.prototype.setAlt = function(alt) {
  if (alt == this.altText_) {
    return;
  }
  this.altText_ = alt || '';
  if (this.imageElement_) {
    this.imageElement_.setAttribute('alt', this.altText_);
  }
};

/**
 * If field click is called, and click handler defined,
 * call the handler.
 * @protected
 */
FieldImage.prototype.showEditor_ = function() {
  if (this.clickHandler_) {
    this.clickHandler_(this);
  }
};

/**
 * Set the function that is called when this image  is clicked.
 * @param {?function(!FieldImage)} func The function that is called
 *    when the image is clicked, or null to remove.
 */
FieldImage.prototype.setOnClickHandler = function(func) {
  this.clickHandler_ = func;
};

/**
 * Use the `getText_` developer hook to override the field's text
 * representation.
 * Return the image alt text instead.
 * @return {?string} The image alt text.
 * @protected
 * @override
 */
FieldImage.prototype.getText_ = function() {
  return this.altText_;
};

fieldRegistry.register('field_image', FieldImage);

exports = FieldImage;
<|endoftext|>


<commit_before>var map_data = {};
var form = this;
var player_data = {};
var current_map = null;
var hero_names = [];
var hero_sub_roles = {};
var sub_role_classes = {};
var available_heroes = [];
var num_ban_suggestions = 10;
var num_player_suggestions = 8;
var num_general_suggestions = 10;

$(document).ready(function() {
	chrome.storage.sync.get(function(items) {
		console.log(items);
		for (key in items) {
			key_type = key.split(':')[0];
			//console.log(key+" is a "+key_type);
			if (key_type == 'map') {
				map_name = items[key].map;
				map_data[map_name] = items[key].heroes;
				$('select#map').append("<OPTION>"+map_name+"</OPTION>");
			} else if (key_type == 'player') {
				player = items[key];
				player_data[player.ID] = player.heroes;
				$('select.player_select').append("<OPTION value='"+player.ID+"'>"+player.name+"</OPTION>");
			} else if (key_type == 'hero_sub_roles') {
				hero_sub_roles = items[key];
				for (hero in hero_sub_roles) {
					role = hero_sub_roles[hero];
					sub_role_classes[role] = role.replace(' ','');
				}

				hero_names = Object.keys(hero_sub_roles);
				hero_names.sort();
				for (var i = 0, len = hero_names.length; i < len; i++) {
					$('select.hero_select').append("<OPTION>"+hero_names[i]+"</OPTION>");
				}
			}
		}

		// Set current map whenever map is changed.
		$('select#map').change(function(){
			current_map = $(this).val();
		});

		$('select').change(function() {
			update_suggestions();
		});

	});
});

function update_suggestions() {
	if (current_map) {
		window.available_heroes = get_available_heroes();

		// Get ban suggestions
		update_ban_suggestions();

		// Get players suggestions
		update_players_suggestions();

		// Get general suggestions
		update_general_suggestions();
	}
}

function hero_display(name, score) {
	return ''+ name + ' (' + score + ')';
}

function update_ban_suggestions() {
	ban_suggestions = get_ban_suggestions();
	display = "";
	for (var i = 0; i < num_ban_suggestions; i++) {
		hero = ban_suggestions[i];
		name = hero['hero'];
		score = hero['score'];
		display += hero_display(name,score.toFixed(0));
	}
	$('#suggested_bans').html(display);
}

function get_ban_suggestions() {
	possible_bans = [];
	for (var i=0, len=window.available_heroes.length; i < len; i++) {
		hero = window.available_heroes[i];
		if (m = map_data[current_map][hero]) {
			score = ( m['Games Banned'] + m['Games Played'] ) * m['Win Percent'] ;
			possible_bans.push({'hero':hero, 'score':score});
		}
	}
	possible_bans.sort(function(a,b){
		return a['score'] - b['score'];
	});

	return possible_bans.reverse();
}

function update_players_suggestions() {
	$('select.player_select').each(function(){
		if (player_id = $(this).val()) {
			player_suggestions = get_player_suggestions(player_id);
			display = "";
			for (var i = 0; i < num_player_suggestions; i++) {
				hero = player_suggestions[i];
				name = hero['hero'];
				score = hero['score'];
				display += hero_display(name,score.toFixed(0));
			}
			$(this).closest('tr').find('.hero_suggestions').html(display);
		}
	});
}

function get_player_suggestions(player_id) {
	possible_heroes = [];
	for (var i=0, len=window.available_heroes.length; i < len; i++) {
		hero = window.available_heroes[i]
		m = map_data[current_map][hero]
		p = player_data[player_id][hero]
		if (m && p && p['Win Percent']) {
			player_confidence = ( p['Win Percent'] * p['Games Played'] + 1 ) / (p['Games Played'] + 2);
			score = Math.pow( m['Win Percent'] * player_confidence, 1/2 ) * 10000;
			possible_heroes.push({'hero':hero, 'score':score});
		}
	}
	possible_heroes.sort(function(a,b){
		return a['score'] - b['score'];
	});

	return possible_heroes.reverse();
}

function update_general_suggestions() {
	general_suggestions = get_general_suggestions();
	display = "";
	for (var i = 0; i < num_general_suggestions; i++) {
		hero = general_suggestions[i];
		name = hero['hero'];
		score = hero['score'];
		display += hero_display(name,score.toFixed(0));
	}
	$('#general_suggestions').html(display);
}

function get_general_suggestions() {
	possible_heroes = [];
	for (var i=0, len=window.available_heroes.length; i < len; i++) {
		hero = window.available_heroes[i];
		if (m = map_data[current_map][hero]) {
			score = m['Win Percent'] * 1000;
			possible_heroes.push({'hero':hero, 'score':score});
		}
	}
	possible_heroes.sort(function(a,b){
		return a['score'] - b['score'];
	});

	return possible_heroes.reverse();
}

function get_available_heroes() {
	heroes = {};
	for (var i = 0, len = hero_names.length; i < len; i++) {
		heroes[hero_names[i]] = null;
	}

	$('select.hero_select').each(function(){
		if ( hero_name = $(this).val() ) {
			delete heroes[hero_name];
		}
	});

	return Object.keys(heroes);
}

<commit_msg>let instead of var<commit_after>let map_data = {};
let player_data = {};
let current_map = null;
let hero_names = [];
let hero_sub_roles = {};
let sub_role_classes = {};
let available_heroes = [];
let num_ban_suggestions = 10;
let num_player_suggestions = 8;
let num_general_suggestions = 10;

$(document).ready(function() {
	chrome.storage.sync.get(function(items) {
		console.log(items);
		for (key in items) {
			key_type = key.split(':')[0];
			//console.log(key+" is a "+key_type);
			if (key_type == 'map') {
				map_name = items[key].map;
				map_data[map_name] = items[key].heroes;
				$('select#map').append("<OPTION>"+map_name+"</OPTION>");
			} else if (key_type == 'player') {
				player = items[key];
				player_data[player.ID] = player.heroes;
				$('select.player_select').append("<OPTION value='"+player.ID+"'>"+player.name+"</OPTION>");
			} else if (key_type == 'hero_sub_roles') {
				hero_sub_roles = items[key];
				for (hero in hero_sub_roles) {
					role = hero_sub_roles[hero];
					sub_role_classes[role] = role.replace(' ','');
				}

				hero_names = Object.keys(hero_sub_roles);
				hero_names.sort();
				for (let i = 0, len = hero_names.length; i < len; i++) {
					$('select.hero_select').append("<OPTION>"+hero_names[i]+"</OPTION>");
				}
			}
		}

		// Set current map whenever map is changed.
		$('select#map').change(function(){
			current_map = $(this).val();
		});

		$('select').change(function() {
			update_suggestions();
		});

	});
});

function update_suggestions() {
	if (current_map) {
		window.available_heroes = get_available_heroes();

		// Get ban suggestions
		update_ban_suggestions();

		// Get players suggestions
		update_players_suggestions();

		// Get general suggestions
		update_general_suggestions();
	}
}

function hero_display(name, score) {
	return ''+ name + ' (' + score + ')';
}

function update_ban_suggestions() {
	ban_suggestions = get_ban_suggestions();
	display = "";
	for (let i = 0; i < num_ban_suggestions; i++) {
		hero = ban_suggestions[i];
		name = hero['hero'];
		score = hero['score'];
		display += hero_display(name,score.toFixed(0));
	}
	$('#suggested_bans').html(display);
}

function get_ban_suggestions() {
	possible_bans = [];
	for (let i=0, len=window.available_heroes.length; i < len; i++) {
		hero = window.available_heroes[i];
		if (m = map_data[current_map][hero]) {
			score = ( m['Games Banned'] + m['Games Played'] ) * m['Win Percent'] ;
			possible_bans.push({'hero':hero, 'score':score});
		}
	}
	possible_bans.sort(function(a,b){
		return a['score'] - b['score'];
	});

	return possible_bans.reverse();
}

function update_players_suggestions() {
	$('select.player_select').each(function(){
		if (player_id = $(this).val()) {
			player_suggestions = get_player_suggestions(player_id);
			display = "";
			for (let i = 0; i < num_player_suggestions; i++) {
				hero = player_suggestions[i];
				name = hero['hero'];
				score = hero['score'];
				display += hero_display(name,score.toFixed(0));
			}
			$(this).closest('tr').find('.hero_suggestions').html(display);
		}
	});
}

function get_player_suggestions(player_id) {
	possible_heroes = [];
	for (let i=0, len=window.available_heroes.length; i < len; i++) {
		hero = window.available_heroes[i]
		m = map_data[current_map][hero]
		p = player_data[player_id][hero]
		if (m && p && p['Win Percent']) {
			player_confidence = ( p['Win Percent'] * p['Games Played'] + 1 ) / (p['Games Played'] + 2);
			score = Math.pow( m['Win Percent'] * player_confidence, 1/2 ) * 10000;
			possible_heroes.push({'hero':hero, 'score':score});
		}
	}
	possible_heroes.sort(function(a,b){
		return a['score'] - b['score'];
	});

	return possible_heroes.reverse();
}

function update_general_suggestions() {
	general_suggestions = get_general_suggestions();
	display = "";
	for (let i = 0; i < num_general_suggestions; i++) {
		hero = general_suggestions[i];
		name = hero['hero'];
		score = hero['score'];
		display += hero_display(name,score.toFixed(0));
	}
	$('#general_suggestions').html(display);
}

function get_general_suggestions() {
	possible_heroes = [];
	for (let i=0, len=window.available_heroes.length; i < len; i++) {
		hero = window.available_heroes[i];
		if (m = map_data[current_map][hero]) {
			score = m['Win Percent'] * 1000;
			possible_heroes.push({'hero':hero, 'score':score});
		}
	}
	possible_heroes.sort(function(a,b){
		return a['score'] - b['score'];
	});

	return possible_heroes.reverse();
}

function get_available_heroes() {
	heroes = {};
	for (let i = 0, len = hero_names.length; i < len; i++) {
		heroes[hero_names[i]] = null;
	}

	$('select.hero_select').each(function(){
		if ( hero_name = $(this).val() ) {
			delete heroes[hero_name];
		}
	});

	return Object.keys(heroes);
}

<|endoftext|>


<commit_before>(function(window){

    var Recorder = function(cfg){
        var config = cfg || {};
        var bufferLen = config.bufferLen || 16384;
        var numChannels = config.numChannels || 1;
        var bufferCallback = config.bufferCallback || function(buffer) { console.log(buffer); };
        var errorCallback = config.errorCallback || function(error) { console.log(error); };
        var recording = false;

        this.init = function() {
            audio_context = createAudioContext();
            navigator.getUserMedia({audio: true}, startUserMedia, function(e) {
                errorCallback('No live audio input: ' + e);
            });
        }

        this.configure = function(cfg){
            for (var prop in cfg){
                if (cfg.hasOwnProperty(prop)){
                    config[prop] = cfg[prop];
                }
            }
        }

        this.record = function(){
            recording = true;
        }

        this.stop = function(){
            recording = false;
        }

        function createAudioContext() {
            try {
                window.AudioContext = window.AudioContext || window.webkitAudioContext;
                navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;

                audio_context = new AudioContext;
                console.log('Audio context set up.');
                console.log('navigator.getUserMedia ' + (navigator.getUserMedia ? 'available.' : 'not present!'));

                return audio_context;
            } catch (e) {
                errorCallback('No web audio support in this browser!');
            }
        }

        function startUserMedia(stream) {
            var source = audio_context.createMediaStreamSource(stream);
            console.log('Media stream created.');

            source.context.createScriptProcessor = source.context.createScriptProcessor || source.context.createJavaScriptNode;
            var sourceProcessor = source.context.createScriptProcessor(bufferLen, numChannels, numChannels);

            sourceProcessor.onaudioprocess = function(e){
                if (!recording) return;
                var buffer = [];
                for (var channel = 0; channel < numChannels; channel++){
                        buffer.push(e.inputBuffer.getChannelData(channel));
                }

                bufferCallback(buffer);
            }

            source.connect(sourceProcessor);
            sourceProcessor.connect(source.context.destination);
            console.log('Input connected to audio context destination.');
        }

    };

    window.Recorder = Recorder;

})(window);
<commit_msg>Recorder.js works in Firefox.<commit_after>(function(window){

    var Recorder = function(cfg){
        var config = cfg || {};
        var bufferLen = config.bufferLen || 16384;
        var numChannels = config.numChannels || 1;
        var bufferCallback = config.bufferCallback || function(buffer) { console.log(buffer); };
        var errorCallback = config.errorCallback || function(error) { console.log(error); };
        var recording = false;

        this.init = function() {
            audio_context = createAudioContext();
            navigator.getUserMedia({audio: true}, startUserMedia, function(e) {
                errorCallback('No live audio input: ' + e);
            });
        }

        this.configure = function(cfg){
            for (var prop in cfg){
                if (cfg.hasOwnProperty(prop)){
                    config[prop] = cfg[prop];
                }
            }
        }

        this.record = function(){
            recording = true;
        }

        this.stop = function(){
            recording = false;
        }

        function createAudioContext() {
            try {
                window.AudioContext = window.AudioContext || window.webkitAudioContext;
                navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

                audio_context = new AudioContext;
                console.log('Audio context set up.');
                console.log('navigator.getUserMedia ' + (navigator.getUserMedia ? 'available.' : 'not present!'));

                return audio_context;
            } catch (e) {
                errorCallback('No web audio support in this browser!');
            }
        }

        function startUserMedia(stream) {
            var source = audio_context.createMediaStreamSource(stream);
            console.log('Media stream created.');

            source.context.createScriptProcessor = source.context.createScriptProcessor || source.context.createJavaScriptNode;
            var sourceProcessor = source.context.createScriptProcessor(bufferLen, numChannels, numChannels);

            sourceProcessor.onaudioprocess = function(e){
                if (!recording) return;
                var buffer = [];
                for (var channel = 0; channel < numChannels; channel++){
                        buffer.push(e.inputBuffer.getChannelData(channel));
                }

                bufferCallback(buffer);
            }

            source.connect(sourceProcessor);
            sourceProcessor.connect(source.context.destination);
            console.log('Input connected to audio context destination.');
        }

    };

    window.Recorder = Recorder;

})(window);
<|endoftext|>


<commit_before>/*
 * grunt-text2datauri
 * https://github.com/mobilemind/grunt-text2datauri
 *
 * Copyright (c) 2012 Tom King
 * Licensed under the MIT license.
 */
"use strict";
module.exports = function(grunt) {
  // HELPERS & PRIVATE VARS
  const text2datauriHelpers = require('./text2datauriHelpers.js');
  let configOptions = {};

  // Please see the grunt documentation for more information regarding task and
  // helper creation: https://github.com/gruntjs/grunt/blob/master/docs/toc.md

  // ==========================================================================
  // TASKS
  // ==========================================================================

  // default version to  metadata version OR pkg.version if available
  let text2datauri_pkgVersion = '';
  if (undefined !== grunt.config('meta.version')) text2datauri_pkgVersion = grunt.config('meta.version');
  else if (undefined !== grunt.config('pkg.version')) text2datauri_pkgVersion = grunt.config('pkg.version');

  // main function
  grunt.registerMultiTask('text2datauri', 'Convert file to data: URI.', function() {
    // process js file to create URI
    try {
      // set config options
      configOptions = this.options({
        // Default options
        sourceCharset: 'utf-8', // or 'ascii'; actual format is not validated by text2datauri
        protocol: 'data:', // any string; this is not validated by text2datauri
        mimeType: 'text/html', // any string;  this is not validated by text2datauri
        targetCharset: 'utf-8', // currently only utf-8 is valid
        encoding: 'base64' // or 'uri'; use 'uri' for encodeURIComponent() encoding
      });

      // build prefix
      const uriPrefix = text2datauriHelpers.text2dataPrefix(configOptions);

      // loop through files
      let files = this.files;
      files.forEach(function(filepair) {
        let rawStr = grunt.file.read(filepair.src);
        // here's where ascii/utf-8 might be validated or pre-processed
        // encode rawStr to data value
        let dataStr = text2datauriHelpers.text2data(rawStr, configOptions.encoding);

        // write full URI to file & log
        let fullURI = uriPrefix + dataStr;
        grunt.file.write(filepair.dest, fullURI);
        console.log(filepair.src + ' -> ' + filepair.dest + ' (' + dataStr.length + ' bytes of data, ' + fullURI.length + ' total bytes)');
      });
    }
    catch(e) {
      // warn on error
      grunt.warn(this.name + ' found errors: ' + e.message, 10);
      return false;
    }
    return true;
  });
};
<commit_msg>tasks/text2datauri.js: remove unused "text2datauri_pkgVersion"; address other eslint warings<commit_after>/*
 * grunt-text2datauri
 * https://github.com/mobilemind/grunt-text2datauri
 *
 * Copyright (c) 2012 Tom King
 * Licensed under the MIT license.
 */
"use strict";
module.exports = function(grunt) {
  // HELPERS & PRIVATE VARS
  const text2datauriHelpers = require('./text2datauriHelpers.js');
  let configOptions = {};

  // Please see the grunt documentation for more information regarding task and
  // helper creation: https://github.com/gruntjs/grunt/blob/master/docs/toc.md

  // ==========================================================================
  // TASKS
  // ==========================================================================

  // main function
  grunt.registerMultiTask('text2datauri', 'Convert file to data: URI.', function() {
    // process js file to create URI
    try {
      // set config options
      configOptions = this.options({
        // Default options
        "sourceCharset": 'utf-8', // or 'ascii'; actual format is not validated by text2datauri
        "protocol": 'data:', // any string; this is not validated by text2datauri
        "mimeType": 'text/html', // any string;  this is not validated by text2datauri
        "targetCharset": 'utf-8', // currently only utf-8 is valid
        "encoding": 'base64' // or 'uri'; use 'uri' for encodeURIComponent() encoding
      });

      // build prefix
      const uriPrefix = text2datauriHelpers.text2dataPrefix(configOptions);

      // loop through files
      const files = this.files;
      files.forEach(function(filepair) {
        const rawStr = grunt.file.read(filepair.src);
        // here's where ascii/utf-8 might be validated or pre-processed
        // encode rawStr to data value
        const dataStr = text2datauriHelpers.text2data(rawStr, configOptions.encoding);

        // write full URI to file & log
        const fullURI = uriPrefix + dataStr;
        grunt.file.write(filepair.dest, fullURI);
        console.log(filepair.src + ' -> ' + filepair.dest + ' (' + dataStr.length + ' bytes of data, ' + fullURI.length + ' total bytes)');
      });
    } catch(e) {
      // warn on error
      grunt.warn(this.name + ' found errors: ' + e.message, 10);
      return false;
    }
    return true;
  });
};
<|endoftext|>


<commit_before>import Ember from 'ember';

const {computed, Mixin} = Ember;

export default Mixin.create({
  getOptions(str) {
    return this.get(str).map((a) => {
      return {id: a, name: a};
    });
  },

  businessSales: [
    "below 250k",
    "250k - 500k",
    "500k - 1.0m",
    "1.0m - 1.5m",
    "above 1.5m"
  ],
  guarantorRoles: [
    "Owner",
    "Officer",
    "IT Manager",
    "Other"
  ],
  locales: {
    us: {
      currency: 'USD',
      locale: 'en',
      flagSrc: '/assets/flags/United-States.png',
      states: [
        "Alabama",
        "Alaska",
        "Arizona",
        "Arkansas",
        "California",
        "Colorado",
        "Connecticut",
        "Delaware",
        "District Of Columbia",
        "Florida",
        "Georgia",
        "Hawaii",
        "Idaho",
        "Illinois",
        "Indiana",
        "Iowa",
        "Kansas",
        "Kentucky",
        "Louisiana",
        "Maine",
        "Maryland",
        "Massachusetts",
        "Michigan",
        "Minnesota",
        "Mississippi",
        "Missouri",
        "Montana",
        "Nebraska",
        "Nevada",
        "New Hampshire",
        "New Jersey",
        "New Mexico",
        "New York",
        "North Carolina",
        "North Dakota",
        "Ohio",
        "Oklahoma",
        "Oregon",
        "Pennsylvania",
        "Rhode Island",
        "South Carolina",
        "South Dakota",
        "Tennessee",
        "Texas",
        "Utah",
        "Vermont",
        "Virginia",
        "Washington",
        "West Virginia",
        "Wisconsin",
        "Wyoming"
      ]
    },
    ca: {
      currency: 'CAD',
      locale: 'en-ca',
      flagSrc: '/assets/flags/Canada.png',
      states: [
        "Alberta",
        "British Columbia",
        "Manitoba",
        "New Brunswick",
        "Newfoundland",
        "Northwest Territories",
        "Nova Scotia",
        "Ontario",
        "Prince Edward Island",
        "Quebec",
        "Saskatchewan",
        "Yukon"
      ]
    },
    uk: {
      currency: 'GBP',
      locale: 'en-gb',
      flagSrc: '/assets/flags/United-Kingdom.png',
      states: null //left null to indicate don't ask question
    }
  },
  purposeOfFundsList: [
    'Business Remodel',
    'Business Expansion',
    'Inventory Financing',
    'Marketing Services',
    'Additional Equipment/Technology',
    'Working Capital'
  ],
  structures: [
    "Corporation",
    "S Corporation",
    "Limited Corporation",
    "Limited Liability Corporation",
    "Partnership",
    "Limited Liability Partnership",
    "Sole Proprietorship",
    "Not-for-Profit",
    "Political Campaign",
    "Government Entity",
    "Educational Institution"
  ],
  structuresExemptFromGuarantors: [
    "Political Campaign",
    "Government Entity",
    "Educational Institution"
  ],
  suffixes: [
    "Sr",
    "Jr",
    "II",
    "III",
    "IV"
  ],

  bankruptcyOptions: [
    {label: "yes", value: 'true'},
    {label: "no", value: 'false'}
  ],
  businessSalesOptions: computed('businessSales', function () {
    return this.getOptions('businessSales');
  }),
  guarantorRolesOptions: computed("guarantorRoles", function () {
    return this.getOptions("guarantorRoles");
  }),
  localesCaStatesOptions: computed('locales.ca.states', function () {
    return this.getOptions('locales.ca.states');
  }),
  localesUsStatesOptions: computed('locales.us.states', function () {
    return this.getOptions('locales.us.states');
  }),
  suffixesOptions: computed('suffixes', function () {
    return this.getOptions('suffixes');
  }),
  structuresOptions: computed('structures', function () {
    return this.getOptions('structures');
  }),
  structuresExemptFromGuarantorsOptions: computed('structuresExemptFromGuarantors', function () {
    return this.getOptions('structuresExemptFromGuarantors');
  }),
  purposeOfFundsOptions: computed('purposeOfFundsList', function () {
    return this.getOptions('purposeOfFundsList');
  })
});

<commit_msg>replacing state list with hashes of 2 digit state and province codes<commit_after>import Ember from 'ember';

const {computed, Mixin} = Ember;

export default Mixin.create({
  getOptions(str) {
    return this.get(str).map((a) => {
      return {id: a, name: a};
    });
  },

  businessSales: [
    "below 250k",
    "250k - 500k",
    "500k - 1.0m",
    "1.0m - 1.5m",
    "above 1.5m"
  ],
  guarantorRoles: [
    "Owner",
    "Officer",
    "IT Manager",
    "Other"
  ],
  locales: {
    us: {
      currency: 'USD',
      locale: 'en',
      flagSrc: '/assets/flags/United-States.png',
      states: [
        { id: "AL", name: "Alabama" },
        { id: "AK", name: "Alaska" },
        { id: "AZ", name: "Arizona" },
        { id: "AR", name: "Arkansas" },
        { id: "CA", name: "California" },
        { id: "CO", name: "Colorado" },
        { id: "CT", name: "Connecticut" },
        { id: "DE", name: "Delaware" },
        { id: "DC", name: "District Of Columbia" },
        { id: "FL", name: "Florida" },
        { id: "GA", name: "Georgia" },
        { id: "HI", name: "Hawaii" },
        { id: "ID", name: "Idaho" },
        { id: "IL", name: "Illinois" },
        { id: "IN", name: "Indiana" },
        { id: "IA", name: "Iowa" },
        { id: "KS", name: "Kansas" },
        { id: "KY", name: "Kentucky" },
        { id: "LA", name: "Louisiana" },
        { id: "ME", name: "Maine" },
        { id: "MD", name: "Maryland" },
        { id: "MA", name: "Massachusetts" },
        { id: "MI", name: "Michigan" },
        { id: "MN", name: "Minnesota" },
        { id: "MS", name: "Mississippi" },
        { id: "MO", name: "Missouri" },
        { id: "MT", name: "Montana" },
        { id: "NE", name: "Nebraska" },
        { id: "NV", name: "Nevada" },
        { id: "NH", name: "New Hampshire" },
        { id: "NJ", name: "New Jersey" },
        { id: "NM", name: "New Mexico" },
        { id: "NY", name: "New York" },
        { id: "NC", name: "North Carolina" },
        { id: "ND", name: "North Dakota" },
        { id: "OH", name: "Ohio" },
        { id: "OK", name: "Oklahoma" },
        { id: "OR", name: "Oregon" },
        { id: "PA", name: "Pennsylvania" },
        { id: "RI", name: "Rhode Island" },
        { id: "SC", name: "South Carolina" },
        { id: "SD", name: "South Dakota" },
        { id: "TN", name: "Tennessee" },
        { id: "TX", name: "Texas" },
        { id: "UT", name: "Utah" },
        { id: "VT", name: "Vermont" },
        { id: "VA", name: "Virginia" },
        { id: "WA", name: "Washington" },
        { id: "WV", name: "West Virginia" },
        { id: "WI", name: "Wisconsin" },
        { id: "WY", name: "Wyoming" }
      ]
    },
    ca: {
      currency: 'CAD',
      locale: 'en-ca',
      flagSrc: '/assets/flags/Canada.png',
      states: [
        { id: "AB", name: "Alberta" },
        { id: "BC", name: "British Columbia" },
        { id: "MB", name: "Manitoba" },
        { id: "NB", name: "New Brunswick" },
        { id: "NL", name: "Newfoundland and Labrador" },
        { id: "NS", name: "Nova Scotia" },
        { id: "NT", name: "Northwest Territories" },
        { id: "NU", name: "Nunavut" },
        { id: "ON", name: "Ontario" },
        { id: "PE", name: "Prince Edward Island" },
        { id: "QC", name: "Québec" },
        { id: "SK", name: "Saskatchewan" },
        { id: "YT", name: "Yukon" }
      ]
    },
    uk: {
      currency: 'GBP',
      locale: 'en-gb',
      flagSrc: '/assets/flags/United-Kingdom.png',
      states: null //left null to indicate don't ask question
    }
  },
  purposeOfFundsList: [
    'Business Remodel',
    'Business Expansion',
    'Inventory Financing',
    'Marketing Services',
    'Additional Equipment/Technology',
    'Working Capital'
  ],
  structures: [
    "Corporation",
    "S Corporation",
    "Limited Corporation",
    "Limited Liability Corporation",
    "Partnership",
    "Limited Liability Partnership",
    "Sole Proprietorship",
    "Not-for-Profit",
    "Political Campaign",
    "Government Entity",
    "Educational Institution"
  ],
  structuresExemptFromGuarantors: [
    "Political Campaign",
    "Government Entity",
    "Educational Institution"
  ],
  suffixes: [
    "Sr",
    "Jr",
    "II",
    "III",
    "IV"
  ],
  bankruptcyOptions: [
    {label: "yes", value: 'true'},
    {label: "no", value: 'false'}
  ],
  businessSalesOptions: computed('businessSales', function () {
    return this.getOptions('businessSales');
  }),
  guarantorRolesOptions: computed("guarantorRoles", function () {
    return this.getOptions("guarantorRoles");
  }),
  localesCaStatesOptions: computed('locales.ca.states', function () {
    return this.get('locales.ca.states');
  }),
  localesUsStatesOptions: computed('locales.us.states', function () {
    return this.get('locales.us.states');
  }),
  suffixesOptions: computed('suffixes', function () {
    return this.getOptions('suffixes');
  }),
  structuresOptions: computed('structures', function () {
    return this.getOptions('structures');
  }),
  structuresExemptFromGuarantorsOptions: computed('structuresExemptFromGuarantors', function () {
    return this.getOptions('structuresExemptFromGuarantors');
  }),
  purposeOfFundsOptions: computed('purposeOfFundsList', function () {
    return this.getOptions('purposeOfFundsList');
  })
});
<|endoftext|>


<commit_before>// http://stackoverflow.com/a/3326655/238472
if (!window.console) console = {log: function() {}};
$.aip = {};
$.aip.ds = {};
$.aip.now = function() {
    return new Date().getTime() / 1000;
};
$.aip.error_guard = function(r) {
    return $.Deferred(function($d) {
        if (r && 'error' in r) {
            $d.reject(r.error.message);
        } else {
            $d.resolve(r);
        }
    });
};
$.aip.range = function(n) {
    return Array.apply(0, Array(n)).map(function(e, i) { return i; });
};
$.fn.freeze_size = function() {
    var $this = $(this);
    $this.attr('width', $this.width());
    $this.attr('height', $this.width() * $this.data('height') / $this.data('width'));
    $this.width($this.attr('width'));
    $this.height($this.attr('height'));
};
$.aip.inc = function(name, value) {
    var $t = $('#loading li[name="' + name + '"]');
    if (!value) value = 1;
    $t.text(parseInt($t.text()) + value);
};
$.aip.actual_size = function($img, callback) {
    callback($img[0].naturalWidth, $img[0].naturalHeight);
};
$.aip.async = function(kargs) {
    kargs.url = '/api/async/' + $.aip.sid + kargs.url.slice(4);
    var $d = $.Deferred();
    $.ajax(kargs).then($.aip.error_guard).done(function(r) {
        console.log(r.result.id + ' done');
        $.aip.ds[r.result.id] = $d;
    }).fail($d.reject);
    return $d;
};
$.aip.redo = function(kargs) {
    function inner(depth, make, reloads) {
        var $d = $.Deferred();
        function reject() {
            console.log('deferred failed, arguments: ' + JSON.stringify(arguments));
            if (reloads.length > 0) {
                setTimeout(function() {
                    console.log('redo');
                    inner(depth + 1, make, reloads.slice(1)).done($d.resolve).fail($d.reject);
                }, reloads[0]);
            } else {
                $d.reject(arguments);
            }
        };
        make(depth).done($d.resolve).fail(reject);
        return $d.promise();
    };
    return inner(0, kargs.make, kargs.reloads);
};
$.aip.load_image = function(kargs) {
    function inner($img, src, timeout, reloads) {
        return $.aip.redo({
            make: function(depth) {
                console.log((depth + 1) + 'th loading ' + src);
                // each cross means a reload
                // mod 2 to force reload
                var preview_src = src + '?x=' + ((depth + 2) % 2);
                //var preview_src = src;
                $img.attr('src', preview_src);
                var tid = setTimeout(function() {
                    reject('timeout');
                }, timeout);
                var $d = $.Deferred().done(function() {
                    clearTimeout(tid);
                }).fail(function() {
                    clearTimeout(tid);
                });
                var rejected = false;
                function reject(reason) {
                    rejected = true;
                    $d.reject(reason);
                };
                $img.imagesLoaded().done(function() {
                    clearTimeout(tid);
                    if (!rejected) {
                        console.log('loaded: ' + preview_src);
                        $.aip.actual_size($img, function(width, height) {
                            console.log('sized(' + width + 'x' + height + '): ' + preview_src);
                            $img.data('preview-width', width);
                            $img.data('preview-height', height);
                            $img.freeze_size();
                            $d.resolve();
                        });
                    }
                }).fail(function() {
                    clearTimeout(tid);
                    reject('unknown');
                });
                return $d.promise();
            },
            reloads: reloads
        });
    };
    return inner(kargs.img, kargs.src, kargs.timeout, kargs.reloads);
};
$.fn.preview_area = function() {
    return $(this).data('preview-width') * $(this).data('preview-height');
};
$.fn.viewport_area = function() {
    return $(this).width() * $(this).height();
};
$.aip.super_resolution = function($img, callback, otherwise) {
    var r = {{ config['AIP_RESOLUTION_LEVEL'] }};
    var aa = $img.preview_area();
    var va = $img.viewport_area();
    var need = aa * r < va;
    console.log('super resolution ' + aa + ' x ' + r + ' < ' + va + ' -> ' + need);
    if (need) {
        $.aip.inc('need-enlarge');
        callback();
    } else {
        otherwise();
    }
};
$.aip.error = function(message) {
    message = JSON.stringify(message);
    console.log(message);
    $('#alert_box').html('
×'+message+'
');
};
$.aip.warning = $.aip.error;
$.aip.disturb = function(x) {
    return x * (Math.random() + 0.5)
};
$.aip.init = function(kargs) {
    defaults = {
        makePageData: $.noop
    };
    kargs = $.extend({}, defaults, kargs);
    function postprocess($this) {
        var $preview = $this.find('img.preview');
        $this.find('.plus').each(function() {
            var $plus = $(this);
            var user = $plus.data('user');
            var entry = $plus.data('entry');
            $plus.update = function() {
                $plus.text('+' + $plus.data('count'));
                if ($plus.data('plused')) {
                    $plus.addClass('btn-primary');
                    $plus.unbind('click').click(function() {
                        $.aip.async({
                            method: 'POST',
                            url: '/api/minus',
                            contentType: "application/json",
                            accepts: "application/json",
                            cache: false,
                            dataType: 'json',
                            data: JSON.stringify({ user_id: user, entry_id: entry })
                        }).done(function(data) {
                            $plus.data('count', data.count);
                            $plus.data('plused', false);
                            $plus.update();
                        }).fail(function(reason) {
                            console.log('minus failed, reason: ' + JSON.stringify(reason));
                        });
                    });
                } else {
                    $plus.removeClass('btn-primary');
                    $plus.unbind('click').click(function() {
                        $.aip.async({
                            method: 'POST',
                            url: '/api/plus',
                            contentType: "application/json",
                            accepts: "application/json",
                            cache: false,
                            dataType: 'json',
                            data: JSON.stringify({ user_id: user, entry_id: entry })
                        }).done(function(data) {
                            $plus.data('count', data.count);
                            $plus.data('plused', true);
                            $plus.update();
                        }).fail(function(reason) {
                            console.log('plus failed, reason: ' + JSON.stringify(reason));
                        });
                    });
                }
            };
            $plus.update();
        });
    };
    var $container = $('#items');
    var page = 0;
    function progress(p) {
        $('#bar').width(p + '%');
    };
    var marsed = false;
    var $buffer = $('#buffer');
    $container.waypoint(
        function(direction){
            if (direction === 'down' || direction === 'right') {
                $this = $(this);
                progress(0);
                $('#loading').show();
                $buffer.empty();
                $this.waypoint('disable');
                $.ajax({
                    method: 'GET',
                    url: kargs.makePageUrl(page),
                    accepts: "application/json",
                    cache: false,
                    dataType: 'json',
                    data: kargs.makePageData(page)
                }).then($.aip.error_guard).done(function(data) {
                    var $items = $(data.result).find('.item');
                    var n = $items.length;
                    $.aip.inc('in-json', n);
                    $items.each(function() {
                        $(this).attr('data-loading', false).attr('data-done', false);
                    });
                    $buffer.append($items);
                    var loaded = 0;
                    var cleanup = function() {
                        if ($items.length) {
                            $this.waypoint('enable');
                        } else {
                            console.log('destroy waypoint');
                            $this.waypoint('destroy');
                        }
                        $('#loading').hide();
                        $('#alert_box').html('');
                        page += 1;
                    };
                    // no exception
                    var doneone = function($item) {
                        ++loaded;
                        progress(100 * loaded / n);
                        if (loaded == n) {
                            cleanup();
                        } else if (loaded > n) {
                            throw 'loaded(' + loaded + ') > n(' + n + ')';
                        }
                    };
                    var guarded_doneone = function($item) {
                        if ($item.attr('data-done') == 'false') {
                            doneone($item);
                            $item.attr('data-done', true);
                        }
                    };
                    var dealone = function($item) {
                        try {
                            postprocess($item);
                            $container.append($item);
                            if (!marsed) {
                                console.log('initialize masonry');
                                $container.masonry({
                                    itemSelector: '.item',
                                    isAnimated: true,
                                    columnWidth: '.span2',
                                    transitionDuration: '0.4s'
                                });
                                marsed = true;
                            } else {
                                $container.masonry('appended', $item, true);
                            }
                            $.aip.inc('done');
                        } catch (e) {
                            console.log('postprocess failed');
                            console.log(e);
                        } finally {
                            guarded_doneone($item);
                        }
                    };
                    var proxied = function($item) {
                        $.aip.inc('need-proxied');
                        var error = function(message) {
                            $.aip.error(message);
                            guarded_doneone($item);
                        };
                        var $img = $item.find('img.preview');
                        $.aip.redo({
                            make: function() {
                                return $.aip.async({
                                    method: 'GET',
                                    url: '/api/proxied_url/' + $img.data('md5'),
                                    accepts: "application/json",
                                    cache: false,
                                    dataType: 'json',
                                    timeout: {{ config['AIP_PROXIED_TIMEOUT'] }},
                                    data: { width: $img.width() }
                                });
                            },
                            reloads: $.aip.range({{ config['AIP_REPROXY_LIMIT'] }}).map(function() {
                                return $.aip.disturb({{ config['AIP_REPROXY_INTERVAL'] }});
                            })
                        }).done(function(r) {
                            $.aip.inc('proxied');
                            try {
                                dealone($item);
                                $.aip.load_image({
                                    img: $img,
                                    src: r.result,
                                    timeout: {{ config['AIP_LOADING_TIMEOUT'] }},
                                    reloads: $.aip.range({{ config['AIP_RELOAD_LIMIT'] }}).map(function() {
                                        return $.aip.disturb({{ config['AIP_RELOAD_INTERVAL'] }});
                                    })
                                }).done($.noop).fail(function(reason) {
                                    error('load image failed, reason: ' + JSON.stringify(reason));
                                    $.aip.inc('proxied-preview-loading-failed');
                                });
                            } catch (e) {
                                console.log('fatal error');
                                console.log(JSON.stringify(e));
                            }
                        }).fail(function(reason) {
                            error('proxy failed, reason: ' + JSON.stringify(reason));
                        });
                    };
                    $items.each(function() {
                        var $this = $(this);
                        var $img = $this.find('img.preview');
                        $img.freeze_size();
                        $.aip.load_image({
                            img: $img,
                            src: $img.data('src'),
                            timeout: {{ config['AIP_LOADING_TIMEOUT'] }},
                            reloads: $.aip.range({{ config['AIP_RELOAD_LIMIT'] }}).map(function() {
                                return $.aip.disturb({{ config['AIP_RELOAD_INTERVAL'] }});
                            })
                        }).done(function() {
                            console.log($img.attr('src') + 'loaded');
                            $this.attr('data-loading', true);
                            var r = {{ config['AIP_RESOLUTION_LEVEL'] }};
                            $.aip.super_resolution($img, function() {
                                proxied($this);
                            }, function() {
                                dealone($this);
                            });
                        }).fail(function(reason) {
                            console.log('load image failed, reason: ' + reason);
                            $.aip.inc('original-preview-loading-failed');
                            proxied($this);
                        });
                    });
                }).fail(function(reason) {
                    $('#loading').hide();
                    $.aip.log.warning('load more failed, reason: ' + JSON.stringify(reason));
                });
            }
        }, {
            offset: 'bottom-in-view'
        }
    );
    $.aip.inited = true;
};
$.aip.is = function(kargs) {
    $.aip.source = new EventSource('/api/async/stream')
    $.aip.source.onmessage = function(e) {
        $.Deferred().resolve($.parseJSON(e.data)).then($.aip.error_guard).done(function(r) {
            console.log(r);
            if (r.key == 'hello') {
                $.aip.sid = r.value;
                console.log('hello: ' + $.aip.sid);
                if (!$.aip.inited) {
                    console.log('init');
                    $.aip.init(kargs);
                }
                $.ajax({
                    method: 'POST',
                    url: '/api/async/reply/' + $.aip.sid,
                    cache: false
                });
            } else if (r.key == 'result') {
                if (r.value.id in $.aip.ds) {
                    console.log('result: ' + r.value.id);
                    $.aip.ds[r.value.id].resolve(r.value.result);
                    delete $.aip.ds[r.value.id];
                } else {
                    console.log(r.value.id + ' not in ' + JSON.stringify($.aip.ds));
                }
            } else {
                console.log('unknown event: ' + r.key);
            }
        }).fail(function(reason) {
            console.log('pump failed, reason: ' + JSON.stringify(reason));
        });
    };
};
<commit_msg>async calls' result may comes earlier than their ids<commit_after>// http://stackoverflow.com/a/3326655/238472
if (!window.console) console = {log: function() {}};
$.aip = {};
// store async calls' deferred object or their result when their result comes
// earlier than their ids
$.aip.calls = {};
$.aip.now = function() {
    return new Date().getTime() / 1000;
};
$.aip.error_guard = function(r) {
    return $.Deferred(function($d) {
        if (r && 'error' in r) {
            $d.reject(r.error.message);
        } else {
            $d.resolve(r);
        }
    });
};
$.aip.range = function(n) {
    return Array.apply(0, Array(n)).map(function(e, i) { return i; });
};
$.fn.freeze_size = function() {
    var $this = $(this);
    $this.attr('width', $this.width());
    $this.attr('height', $this.width() * $this.data('height') / $this.data('width'));
    $this.width($this.attr('width'));
    $this.height($this.attr('height'));
};
$.aip.inc = function(name, value) {
    var $t = $('#loading li[name="' + name + '"]');
    if (!value) value = 1;
    $t.text(parseInt($t.text()) + value);
};
$.aip.actual_size = function($img, callback) {
    callback($img[0].naturalWidth, $img[0].naturalHeight);
};
$.aip.async = function(kargs) {
    kargs.url = '/api/async/' + $.aip.sid + kargs.url.slice(4);
    var $d = $.Deferred();
    $.ajax(kargs).then($.aip.error_guard).done(function(r) {
        if (r.result.id in $.aip.calls) {
            $.aip.calls[r.result.id] = $d;
        } else {
            console.log('async call ' + r.result.id + ' arrive later than its result');
            // result is already here
            $d.resolve($.aip.calls[r.value.id]);
            delete $.aip.calls[r.value.id];
        }
    }).fail($d.reject);
    return $d;
};
$.aip.redo = function(kargs) {
    function inner(depth, make, reloads) {
        var $d = $.Deferred();
        function reject() {
            console.log('deferred failed, arguments: ' + JSON.stringify(arguments));
            if (reloads.length > 0) {
                setTimeout(function() {
                    console.log('redo');
                    inner(depth + 1, make, reloads.slice(1)).done($d.resolve).fail($d.reject);
                }, reloads[0]);
            } else {
                $d.reject(arguments);
            }
        };
        make(depth).done($d.resolve).fail(reject);
        return $d.promise();
    };
    return inner(0, kargs.make, kargs.reloads);
};
$.aip.load_image = function(kargs) {
    function inner($img, src, timeout, reloads) {
        return $.aip.redo({
            make: function(depth) {
                console.log((depth + 1) + 'th loading ' + src);
                // each cross means a reload
                // mod 2 to force reload
                var preview_src = src + '?x=' + ((depth + 2) % 2);
                //var preview_src = src;
                $img.attr('src', preview_src);
                var tid = setTimeout(function() {
                    reject('timeout');
                }, timeout);
                var $d = $.Deferred().done(function() {
                    clearTimeout(tid);
                }).fail(function() {
                    clearTimeout(tid);
                });
                var rejected = false;
                function reject(reason) {
                    rejected = true;
                    $d.reject(reason);
                };
                $img.imagesLoaded().done(function() {
                    clearTimeout(tid);
                    if (!rejected) {
                        console.log('loaded: ' + preview_src);
                        $.aip.actual_size($img, function(width, height) {
                            console.log('sized(' + width + 'x' + height + '): ' + preview_src);
                            $img.data('preview-width', width);
                            $img.data('preview-height', height);
                            $img.freeze_size();
                            $d.resolve();
                        });
                    }
                }).fail(function() {
                    clearTimeout(tid);
                    reject('unknown');
                });
                return $d.promise();
            },
            reloads: reloads
        });
    };
    return inner(kargs.img, kargs.src, kargs.timeout, kargs.reloads);
};
$.fn.preview_area = function() {
    return $(this).data('preview-width') * $(this).data('preview-height');
};
$.fn.viewport_area = function() {
    return $(this).width() * $(this).height();
};
$.aip.super_resolution = function($img, callback, otherwise) {
    var r = {{ config['AIP_RESOLUTION_LEVEL'] }};
    var aa = $img.preview_area();
    var va = $img.viewport_area();
    var need = aa * r < va;
    console.log('super resolution ' + aa + ' x ' + r + ' < ' + va + ' -> ' + need);
    if (need) {
        $.aip.inc('need-enlarge');
        callback();
    } else {
        otherwise();
    }
};
$.aip.error = function(message) {
    message = JSON.stringify(message);
    console.log(message);
    $('#alert_box').html('
×'+message+'
');
};
$.aip.warning = $.aip.error;
$.aip.disturb = function(x) {
    return x * (Math.random() + 0.5)
};
$.aip.init = function(kargs) {
    defaults = {
        makePageData: $.noop
    };
    kargs = $.extend({}, defaults, kargs);
    function postprocess($this) {
        var $preview = $this.find('img.preview');
        $this.find('.plus').each(function() {
            var $plus = $(this);
            var user = $plus.data('user');
            var entry = $plus.data('entry');
            $plus.update = function() {
                $plus.text('+' + $plus.data('count'));
                if ($plus.data('plused')) {
                    $plus.addClass('btn-primary');
                    $plus.unbind('click').click(function() {
                        $.aip.async({
                            method: 'POST',
                            url: '/api/minus',
                            contentType: "application/json",
                            accepts: "application/json",
                            cache: false,
                            dataType: 'json',
                            data: JSON.stringify({ user_id: user, entry_id: entry })
                        }).done(function(data) {
                            $plus.data('count', data.count);
                            $plus.data('plused', false);
                            $plus.update();
                        }).fail(function(reason) {
                            console.log('minus failed, reason: ' + JSON.stringify(reason));
                        });
                    });
                } else {
                    $plus.removeClass('btn-primary');
                    $plus.unbind('click').click(function() {
                        $.aip.async({
                            method: 'POST',
                            url: '/api/plus',
                            contentType: "application/json",
                            accepts: "application/json",
                            cache: false,
                            dataType: 'json',
                            data: JSON.stringify({ user_id: user, entry_id: entry })
                        }).done(function(data) {
                            $plus.data('count', data.count);
                            $plus.data('plused', true);
                            $plus.update();
                        }).fail(function(reason) {
                            console.log('plus failed, reason: ' + JSON.stringify(reason));
                        });
                    });
                }
            };
            $plus.update();
        });
    };
    var $container = $('#items');
    var page = 0;
    function progress(p) {
        $('#bar').width(p + '%');
    };
    var marsed = false;
    var $buffer = $('#buffer');
    $container.waypoint(
        function(direction){
            if (direction === 'down' || direction === 'right') {
                $this = $(this);
                progress(0);
                $('#loading').show();
                $buffer.empty();
                $this.waypoint('disable');
                $.ajax({
                    method: 'GET',
                    url: kargs.makePageUrl(page),
                    accepts: "application/json",
                    cache: false,
                    dataType: 'json',
                    data: kargs.makePageData(page)
                }).then($.aip.error_guard).done(function(data) {
                    var $items = $(data.result).find('.item');
                    var n = $items.length;
                    $.aip.inc('in-json', n);
                    $items.each(function() {
                        $(this).attr('data-loading', false).attr('data-done', false);
                    });
                    $buffer.append($items);
                    var loaded = 0;
                    var cleanup = function() {
                        if ($items.length) {
                            $this.waypoint('enable');
                        } else {
                            console.log('destroy waypoint');
                            $this.waypoint('destroy');
                        }
                        $('#loading').hide();
                        $('#alert_box').html('');
                        page += 1;
                    };
                    // no exception
                    var doneone = function($item) {
                        ++loaded;
                        progress(100 * loaded / n);
                        if (loaded == n) {
                            cleanup();
                        } else if (loaded > n) {
                            throw 'loaded(' + loaded + ') > n(' + n + ')';
                        }
                    };
                    var guarded_doneone = function($item) {
                        if ($item.attr('data-done') == 'false') {
                            doneone($item);
                            $item.attr('data-done', true);
                        }
                    };
                    var dealone = function($item) {
                        try {
                            postprocess($item);
                            $container.append($item);
                            if (!marsed) {
                                console.log('initialize masonry');
                                $container.masonry({
                                    itemSelector: '.item',
                                    isAnimated: true,
                                    columnWidth: '.span2',
                                    transitionDuration: '0.4s'
                                });
                                marsed = true;
                            } else {
                                $container.masonry('appended', $item, true);
                            }
                            $.aip.inc('done');
                        } catch (e) {
                            console.log('postprocess failed');
                            console.log(e);
                        } finally {
                            guarded_doneone($item);
                        }
                    };
                    var proxied = function($item) {
                        $.aip.inc('need-proxied');
                        var error = function(message) {
                            $.aip.error(message);
                            guarded_doneone($item);
                        };
                        var $img = $item.find('img.preview');
                        $.aip.redo({
                            make: function() {
                                return $.aip.async({
                                    method: 'GET',
                                    url: '/api/proxied_url/' + $img.data('md5'),
                                    accepts: "application/json",
                                    cache: false,
                                    dataType: 'json',
                                    timeout: {{ config['AIP_PROXIED_TIMEOUT'] }},
                                    data: { width: $img.width() }
                                });
                            },
                            reloads: $.aip.range({{ config['AIP_REPROXY_LIMIT'] }}).map(function() {
                                return $.aip.disturb({{ config['AIP_REPROXY_INTERVAL'] }});
                            })
                        }).done(function(r) {
                            $.aip.inc('proxied');
                            try {
                                dealone($item);
                                $.aip.load_image({
                                    img: $img,
                                    src: r.result,
                                    timeout: {{ config['AIP_LOADING_TIMEOUT'] }},
                                    reloads: $.aip.range({{ config['AIP_RELOAD_LIMIT'] }}).map(function() {
                                        return $.aip.disturb({{ config['AIP_RELOAD_INTERVAL'] }});
                                    })
                                }).done($.noop).fail(function(reason) {
                                    error('load image failed, reason: ' + JSON.stringify(reason));
                                    $.aip.inc('proxied-preview-loading-failed');
                                });
                            } catch (e) {
                                console.log('fatal error');
                                console.log(JSON.stringify(e));
                            }
                        }).fail(function(reason) {
                            error('proxy failed, reason: ' + JSON.stringify(reason));
                        });
                    };
                    $items.each(function() {
                        var $this = $(this);
                        var $img = $this.find('img.preview');
                        $img.freeze_size();
                        $.aip.load_image({
                            img: $img,
                            src: $img.data('src'),
                            timeout: {{ config['AIP_LOADING_TIMEOUT'] }},
                            reloads: $.aip.range({{ config['AIP_RELOAD_LIMIT'] }}).map(function() {
                                return $.aip.disturb({{ config['AIP_RELOAD_INTERVAL'] }});
                            })
                        }).done(function() {
                            console.log($img.attr('src') + 'loaded');
                            $this.attr('data-loading', true);
                            var r = {{ config['AIP_RESOLUTION_LEVEL'] }};
                            $.aip.super_resolution($img, function() {
                                proxied($this);
                            }, function() {
                                dealone($this);
                            });
                        }).fail(function(reason) {
                            console.log('load image failed, reason: ' + reason);
                            $.aip.inc('original-preview-loading-failed');
                            proxied($this);
                        });
                    });
                }).fail(function(reason) {
                    $('#loading').hide();
                    $.aip.log.warning('load more failed, reason: ' + JSON.stringify(reason));
                });
            }
        }, {
            offset: 'bottom-in-view'
        }
    );
    $.aip.inited = true;
};
$.aip.is = function(kargs) {
    $.aip.source = new EventSource('/api/async/stream')
    $.aip.source.onmessage = function(e) {
        $.Deferred().resolve($.parseJSON(e.data)).then($.aip.error_guard).done(function(r) {
            console.log(r);
            if (r.key == 'hello') {
                $.aip.sid = r.value;
                console.log('hello: ' + $.aip.sid);
                if (!$.aip.inited) {
                    console.log('init');
                    $.aip.init(kargs);
                }
                $.ajax({
                    method: 'POST',
                    url: '/api/async/reply/' + $.aip.sid,
                    cache: false
                });
            } else if (r.key == 'result') {
                if (r.value.id in $.aip.calls) {
                    console.log('result: ' + r.value.id);
                    $.aip.calls[r.value.id].resolve(r.value.result);
                    delete $.aip.calls[r.value.id];
                } else {
                    // async call id arrive later than its result
                    // store its result first
                    $.aip.calls[r.value.id] = r.value.result;
                }
            } else {
                console.log('unknown event: ' + r.key);
            }
        }).fail(function(reason) {
            console.log('pump failed, reason: ' + JSON.stringify(reason));
        });
    };
};
<|endoftext|>


<commit_before>var gulp = require('gulp');
var gutil = require('gulp-util');
var iconfontCss = require('gulp-iconfont-css');
var svgicons2svgfont = require('gulp-svgicons2svgfont');
var svg2ttf = require('gulp-svg2ttf');
var ttf2eot = require('gulp-ttf2eot');
var ttf2woff = require('gulp-ttf2woff');
var config = require('./../config');
var runSequence = require('run-sequence');

gulp.task('iconfont', function (callback) {

	if (config.global.tasks.iconfont) {
		runSequence(
			'convertIconsToTtf',
			[
				'convertTtfToEot',
				'convertTtfToWoff'
			],
			callback
		);
	} else {
		callback();
		gutil.log(gutil.colors.yellow('iconfont disabled'));
	}

});

gulp.task('convertIconsToTtf', function () {

	return gulp.src(config.global.src + '/_icons/*.svg')
		.pipe(iconfontCss(config.iconfontCss))
		.pipe(svgicons2svgfont(config.iconfont))
		.pipe(svg2ttf())
		.pipe(gulp.dest(config.global.dev + '/resources/fonts/icons/'));

});

gulp.task('convertTtfToEot', function () {

	return gulp.src(config.global.dev + '/resources/fonts/icons/*.ttf')
		.pipe(ttf2eot())
		.pipe(gulp.dest(config.global.dev + '/resources/fonts/icons/'));

});

gulp.task('convertTtfToWoff', function () {

	return gulp.src(config.global.dev + '/resources/fonts/icons/*.ttf')
		.pipe(ttf2woff())
		.pipe(gulp.dest(config.global.dev + '/resources/fonts/icons/'));

});
<commit_msg>multiple iconfont files<commit_after>var gulp = require('gulp');
var gutil = require('gulp-util');
var iconfontCss = require('gulp-iconfont-css');
var svgicons2svgfont = require('gulp-svgicons2svgfont');
var svg2ttf = require('gulp-svg2ttf');
var ttf2eot = require('gulp-ttf2eot');
var ttf2woff = require('gulp-ttf2woff');
var config = require('./../config');
var runSequence = require('run-sequence');
var mergeStream = require('merge-stream');

gulp.task('iconfont', function (callback) {

	if (config.global.tasks.iconfont) {
		runSequence(
			'convertIconsToTtf',
			[
				'convertTtfToEot',
				'convertTtfToWoff'
			],
			callback
		);
	} else {
		callback();
		gutil.log(gutil.colors.yellow('iconfont disabled'));
	}

});

gulp.task('convertIconsToTtf', function () {

	var iconfontArray = config.iconfontCss;

	if (!Array.isArray(iconfontArray)) {
		iconfontArray = [iconfontArray];
	}

	return mergeStream(iconfontArray.map(function(currentResource) {
		return gulp.src(config.global.src + '/_icons/*.svg')
			.pipe(iconfontCss(currentResource))
			.pipe(svgicons2svgfont(config.iconfont))
			.pipe(svg2ttf())
			.pipe(gulp.dest(config.global.dev + '/resources/fonts/icons/'));
	}));

});

gulp.task('convertTtfToEot', function () {

	return gulp.src(config.global.dev + '/resources/fonts/icons/*.ttf')
		.pipe(ttf2eot())
		.pipe(gulp.dest(config.global.dev + '/resources/fonts/icons/'));

});

gulp.task('convertTtfToWoff', function () {

	return gulp.src(config.global.dev + '/resources/fonts/icons/*.ttf')
		.pipe(ttf2woff())
		.pipe(gulp.dest(config.global.dev + '/resources/fonts/icons/'));

});
<|endoftext|>


<commit_before>const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const browserlist = require('../config/browserlist');
const babelConfig = require('../config/babelConfig');

babelConfig.plugins.push([
  'import',
  {
    libraryName: 'zarm',
    libraryDirectory: 'components',
    style: true,
  },
]);

module.exports = {
  devtool: 'eval-source-map',
  output: {
    path: path.resolve(__dirname, '../../assets'),
    filename: 'js/[name].js',
    chunkFilename: 'js/[name].[chunkhash:8].js',
    publicPath: '/',
  },

  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: babelConfig,
          },
        ],
      },
      {
        test: /\.(ts|tsx)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: babelConfig,
          },
          {
            loader: 'awesome-typescript-loader',
          },
        ],
      },
      {
        test: /\.(css|scss)$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader?importLoaders=1',
          },
          {
            loader: 'postcss-loader',
            options: {
              plugins: [
                require('autoprefixer')({
                  browsers: browserlist,
                }),
              ],
            },
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
              outputStyle: 'compact',
            },
          },
        ],
      },
      {
        test: /\.(png|jpg|jpeg|gif|svg)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'url-loader?limit=8192&name=images/[name].[hash:8].[ext]',
          },
        ],
      },
      {
        test: /\.(woff|woff2|ttf|eot|svg)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'file-loader?name=fonts/[name].[hash:8].[ext]',
          },
        ],
      },
    ],
  },

  resolve: {
    extensions: [' ', '.js', '.jsx', '.ts', '.tsx', '.scss'],
  },

  plugins: [],
};
<commit_msg>perf: reduce size of site bundle<commit_after>const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const browserlist = require('../config/browserlist');
const babelConfig = require('../config/babelConfig');

babelConfig.plugins.push([
  'import',
  {
    libraryName: 'zarm',
    libraryDirectory: 'components',
    style: true,
  },
]);

module.exports = {
  output: {
    path: path.resolve(__dirname, '../../assets'),
    filename: 'js/[name].js',
    chunkFilename: 'js/[name].[chunkhash:8].js',
    publicPath: '/',
  },

  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: babelConfig,
          },
        ],
      },
      {
        test: /\.(ts|tsx)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: babelConfig,
          },
          {
            loader: 'awesome-typescript-loader',
          },
        ],
      },
      {
        test: /\.(css|scss)$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader?importLoaders=1',
          },
          {
            loader: 'postcss-loader',
            options: {
              plugins: [
                require('autoprefixer')({
                  browsers: browserlist,
                }),
              ],
            },
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
              outputStyle: 'compact',
            },
          },
        ],
      },
      {
        test: /\.(png|jpg|jpeg|gif|svg)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'url-loader?limit=8192&name=images/[name].[hash:8].[ext]',
          },
        ],
      },
      {
        test: /\.(woff|woff2|ttf|eot|svg)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'file-loader?name=fonts/[name].[hash:8].[ext]',
          },
        ],
      },
    ],
  },

  resolve: {
    extensions: [' ', '.js', '.jsx', '.ts', '.tsx', '.scss'],
  },

  plugins: [],
};
<|endoftext|>


<commit_before>import {
  dateInput,
  formatDate,
  bindUIEvents as bindDateInputUIEvents,
} from './base/inputs/dateInput';
import {
  datePicker,
  bindUIEvents as bindDatePickerUIEvents,
} from './base/inputs/datePicker';
import {
  monetaryInput,
  formatMonetary,
  bindUIEvents as bindMonetaryUIEvents,
} from './base/inputs/monetaryInput';
import passwordInput from './base/inputs/passwordInput';
import {
  phoneInput,
  formatPhone,
  bindUIEvents as bindPhoneInputUIEvents,
} from './base/inputs/phoneInput';
import {
  requiredSelect,
  runValidation as runRequiredSelectValidation,
} from './base/inputs/requiredSelect';
import {
  requiredTextInput,
  runValidation as runRequiredTextInputValidation,
  bindUIEvents as bindRequiredTextInputUIEvents,
} from './base/inputs/requiredTextInput';
import {
  requiredTick,
  runValidation as runRequiredTickValidation,
  bindUIEvents as bindRequiredTickUIEvents,
} from './base/inputs/requiredTick';
import {
  ssnInput,
  formatSSN,
  bindUIEvents as bindSSNInputUIEvents,
} from './base/inputs/ssnInput';
import {
  hugeInput,
  hugeInput as hugeTextInput,
  bindUIEventsHugeInput,
  bindUIEvents as bindUIEventsHugeInputOld,
} from './base/inputs/hugeInput';
import {
  alerts,
  dismissAlert,
  bindUIEvents as bindAlertUIEvents,
} from './components/alerts';
import {
  masthead,
  toggleMobileNav,
  hideMobileNavs,
  focusTrap,
  addClassOnScroll,
  hideSelectorMask,
  showSelectorMask,
  toggleScrollEvent,
  checkScrollDirection,
  toggleMenu,
  bindUIEvents as bindMastheadUIEvents,
} from './components/masthead';
import {
  modals,
  showModal,
  hideModal,
  isMaskClicked,
  isWaitModal,
  handleModalKeyEvents,
  handleMaskEvents,
  currentOpenModal,
  bindUIEvents as bindModalUIEvents,
} from './components/modals';
import {
  setItemLabels,
  setAriaLabel,
  pagination,
} from './components/pagination';
import {
  spinners,
  getSpinnerClasses,
  setSpinning,
  cancelSpinning,
} from './components/spinners';
import {
  tabs,
  bindUIEvents,
  ariaOrientation,
  resetTabs,
  setActiveTab,
  advanceTab,
  retreatTab,
  getActiveTabIndex,
} from './components/tabs';
import {
  toggle,
  toggleIconType,
  toggleAriaExpanded,
  handleToggleClick,
  bindToggleUIEvents,
} from './components/toggle';
import { tooltip } from './components/tooltip';
import isValidDate from './utilities/validation/isValidDate';
import isValidMonetary from './utilities/validation/isValidMonetary';
import isValidPhone from './utilities/validation/isValidPhone';
import isValidSSN from './utilities/validation/isValidSSN';
import setInvalidSelect from './utilities/validation/setInvalidSelect';
import setInvalidTextInput from './utilities/validation/setInvalidTextInput';
import setInvalidTick from './utilities/validation/setInvalidTick';
import setValidSelect from './utilities/validation/setValidSelect';
import setValidTextInput from './utilities/validation/setValidTextInput';
import setValidTick from './utilities/validation/setValidTick';
import runValidation from './utilities/validation/validation-runner';
import detectJS from './utilities/detectJS';
import addClassIfNotEmpty from './utilities/addClassIfNotEmpty';
import toggleClassWithValue from './utilities/toggleClassWithValue';
import {
  getFocusableEls,
  focusFirstEl,
  isActiveElement,
} from './utilities/elementState';
import getElements from './utilities/getElements';
import {
  isTabPressed,
  isEscPressed,
  isEnterPressed,
  isSpacePressed,
  isDownPressed,
  isUpPressed,
  isLeftPressed,
  isRightPressed,
} from './utilities/keypress';
import toggleValue from './utilities/toggleValue';
import {
  dropdowns,
  bindUIEvents as bindDropdownUIEvents,
  toggleDropDown,
  hideDropDown,
  showDropDown,
  removeActiveStatus,
} from './components/dropdown';
import {
  stepper,
  bindUIEvents as bindStepperUIEvents,
} from './components/stepper';
import { carousel } from './components/carousel';
import { highlightBoard } from './components/highlight-board';
import toggleAriaExpandedAttribute from './utilities/toggleAriaExpanded';
import isElementVisible from './utilities/isElementVisible';
import scrollYDirection from './utilities/scrollYDirection';
import { checkbox, bindCheckboxUIEvents } from './base/inputs/checkbox';
import generateIdForInput from './utilities/generateIdForInput';
import { radioInput, bindRadioUIEvents } from './base/inputs/radioInput';
import resetListItems from './utilities/resetListItems';

export {
  dateInput,
  formatDate,
  bindDateInputUIEvents,
  datePicker,
  bindDatePickerUIEvents,
  monetaryInput,
  formatMonetary,
  bindMonetaryUIEvents,
  passwordInput,
  phoneInput,
  highlightBoard,
  formatPhone,
  bindPhoneInputUIEvents,
  requiredSelect,
  runRequiredSelectValidation,
  requiredTextInput,
  runRequiredTextInputValidation,
  bindRequiredTextInputUIEvents,
  requiredTick,
  runRequiredTickValidation,
  bindRequiredTickUIEvents,
  ssnInput,
  formatSSN,
  bindSSNInputUIEvents,
  alerts,
  dismissAlert,
  bindAlertUIEvents,
  masthead,
  toggleMobileNav,
  hideMobileNavs,
  focusTrap,
  addClassOnScroll,
  showSelectorMask,
  hideSelectorMask,
  bindMastheadUIEvents,
  modals,
  showModal,
  hideModal,
  isMaskClicked,
  isWaitModal,
  handleModalKeyEvents,
  handleMaskEvents,
  currentOpenModal,
  bindModalUIEvents,
  setItemLabels,
  setAriaLabel,
  pagination,
  spinners,
  getSpinnerClasses,
  setSpinning,
  cancelSpinning,
  tabs,
  bindUIEvents,
  ariaOrientation,
  resetTabs,
  setActiveTab,
  advanceTab,
  retreatTab,
  getActiveTabIndex,
  toggle,
  toggleIconType,
  toggleAriaExpanded,
  handleToggleClick,
  bindToggleUIEvents,
  tooltip,
  isValidDate,
  isValidMonetary,
  isValidPhone,
  isValidSSN,
  setInvalidSelect,
  setInvalidTextInput,
  setInvalidTick,
  setValidSelect,
  setValidTextInput,
  setValidTick,
  runValidation,
  detectJS,
  getFocusableEls,
  focusFirstEl,
  isActiveElement,
  getElements,
  isTabPressed,
  isEscPressed,
  isEnterPressed,
  isSpacePressed,
  isUpPressed,
  isDownPressed,
  isLeftPressed,
  isRightPressed,
  toggleValue,
  dropdowns,
  bindDropdownUIEvents,
  toggleDropDown,
  hideDropDown,
  showDropDown,
  removeActiveStatus,
  stepper,
  carousel,
  bindStepperUIEvents,
  toggleScrollEvent,
  isElementVisible,
  scrollYDirection,
  checkScrollDirection,
  toggleMenu,
  hugeTextInput,
  hugeInput,
  bindUIEventsHugeInput,
  bindUIEventsHugeInputOld,
  addClassIfNotEmpty,
  toggleClassWithValue,
  toggleAriaExpandedAttribute,
  checkbox,
  bindCheckboxUIEvents,
  generateIdForInput,
  radioInput,
  bindRadioUIEvents,
  resetListItems,
};
<commit_msg>oopsie<commit_after>import {
  dateInput,
  formatDate,
  bindUIEvents as bindDateInputUIEvents,
} from './base/inputs/dateInput';
import {
  datePicker,
  bindUIEvents as bindDatePickerUIEvents,
} from './base/inputs/datePicker';
import {
  monetaryInput,
  formatMonetary,
  bindUIEvents as bindMonetaryUIEvents,
} from './base/inputs/monetaryInput';
import passwordInput from './base/inputs/passwordInput';
import {
  phoneInput,
  formatPhone,
  bindUIEvents as bindPhoneInputUIEvents,
} from './base/inputs/phoneInput';
import {
  requiredSelect,
  runValidation as runRequiredSelectValidation,
} from './base/inputs/requiredSelect';
import {
  requiredTextInput,
  runValidation as runRequiredTextInputValidation,
  bindUIEvents as bindRequiredTextInputUIEvents,
} from './base/inputs/requiredTextInput';
import {
  requiredTick,
  runValidation as runRequiredTickValidation,
  bindUIEvents as bindRequiredTickUIEvents,
} from './base/inputs/requiredTick';
import {
  ssnInput,
  formatSSN,
  bindUIEvents as bindSSNInputUIEvents,
} from './base/inputs/ssnInput';
import {
  hugeInput,
  hugeInput as hugeTextInput,
  bindUIEventsHugeInput,
  bindUIEvents as bindUIEventsHugeInputOld,
} from './base/inputs/hugeInput';
import {
  alerts,
  dismissAlert,
  bindUIEvents as bindAlertUIEvents,
} from './components/alerts';
import {
  masthead,
  toggleMobileNav,
  hideMobileNavs,
  focusTrap,
  addClassOnScroll,
  hideSelectorMask,
  showSelectorMask,
  toggleScrollEvent,
  checkScrollDirection,
  toggleMenu,
  bindUIEvents as bindMastheadUIEvents,
} from './components/masthead';
import {
  modals,
  showModal,
  hideModal,
  isMaskClicked,
  isWaitModal,
  handleModalKeyEvents,
  handleMaskEvents,
  currentOpenModal,
  bindUIEvents as bindModalUIEvents,
} from './components/modals';
import {
  setItemLabels,
  setAriaLabel,
  pagination,
} from './components/pagination';
import {
  spinners,
  getSpinnerClasses,
  setSpinning,
  cancelSpinning,
} from './components/spinners';
import {
  tabs,
  bindUIEvents,
  ariaOrientation,
  resetTabs,
  setActiveTab,
  advanceTab,
  retreatTab,
  getActiveTabIndex,
} from './components/tabs';
import {
  toggle,
  toggleIconType,
  toggleAriaExpanded,
  handleToggleClick,
  bindToggleUIEvents,
} from './components/toggle';
import { tooltip } from './components/tooltip';
import isValidDate from './utilities/validation/isValidDate';
import isValidMonetary from './utilities/validation/isValidMonetary';
import isValidPhone from './utilities/validation/isValidPhone';
import isValidSSN from './utilities/validation/isValidSSN';
import setInvalidSelect from './utilities/validation/setInvalidSelect';
import setInvalidTextInput from './utilities/validation/setInvalidTextInput';
import setInvalidTick from './utilities/validation/setInvalidTick';
import setValidSelect from './utilities/validation/setValidSelect';
import setValidTextInput from './utilities/validation/setValidTextInput';
import setValidTick from './utilities/validation/setValidTick';
import runValidation from './utilities/validation/validation-runner';
import detectJS from './utilities/detectJS';
import addClassIfNotEmpty from './utilities/addClassIfNotEmpty';
import toggleClassWithValue from './utilities/toggleClassWithValue';
import {
  getFocusableEls,
  focusFirstEl,
  isActiveElement,
} from './utilities/elementState';
import getElements from './utilities/getElements';
import {
  isTabPressed,
  isEscPressed,
  isEnterPressed,
  isSpacePressed,
  isDownPressed,
  isUpPressed,
  isLeftPressed,
  isRightPressed,
} from './utilities/keypress';
import toggleValue from './utilities/toggleValue';
import {
  dropdowns,
  bindUIEvents as bindDropdownUIEvents,
  toggleDropDown,
  hideDropDown,
  showDropDown,
  removeActiveStatus,
} from './components/dropdown';
import {
  stepper,
  bindUIEvents as bindStepperUIEvents,
} from './components/stepper';
import { carousel } from './components/carousel';
import { highlightBoard } from './components/highlight-board';
import toggleAriaExpandedAttribute from './utilities/toggleAriaExpanded';
import generateAriaControls from './utilities/generateAriaControls';
import generateAriaOwns from './utilities/generateAriaOwns';
import isElementVisible from './utilities/isElementVisible';
import scrollYDirection from './utilities/scrollYDirection';
import { checkbox, bindCheckboxUIEvents } from './base/inputs/checkbox';
import generateIdForInput from './utilities/generateIdForInput';
import { radioInput, bindRadioUIEvents } from './base/inputs/radioInput';
import resetListItems from './utilities/resetListItems';

export {
  dateInput,
  formatDate,
  bindDateInputUIEvents,
  datePicker,
  bindDatePickerUIEvents,
  monetaryInput,
  formatMonetary,
  bindMonetaryUIEvents,
  passwordInput,
  phoneInput,
  highlightBoard,
  formatPhone,
  bindPhoneInputUIEvents,
  requiredSelect,
  runRequiredSelectValidation,
  requiredTextInput,
  runRequiredTextInputValidation,
  bindRequiredTextInputUIEvents,
  requiredTick,
  runRequiredTickValidation,
  bindRequiredTickUIEvents,
  ssnInput,
  formatSSN,
  bindSSNInputUIEvents,
  alerts,
  dismissAlert,
  bindAlertUIEvents,
  masthead,
  toggleMobileNav,
  hideMobileNavs,
  focusTrap,
  addClassOnScroll,
  showSelectorMask,
  hideSelectorMask,
  bindMastheadUIEvents,
  modals,
  showModal,
  hideModal,
  isMaskClicked,
  isWaitModal,
  handleModalKeyEvents,
  handleMaskEvents,
  currentOpenModal,
  bindModalUIEvents,
  setItemLabels,
  setAriaLabel,
  pagination,
  spinners,
  getSpinnerClasses,
  setSpinning,
  cancelSpinning,
  tabs,
  bindUIEvents,
  ariaOrientation,
  resetTabs,
  setActiveTab,
  advanceTab,
  retreatTab,
  getActiveTabIndex,
  toggle,
  toggleIconType,
  toggleAriaExpanded,
  handleToggleClick,
  bindToggleUIEvents,
  tooltip,
  isValidDate,
  isValidMonetary,
  isValidPhone,
  isValidSSN,
  setInvalidSelect,
  setInvalidTextInput,
  setInvalidTick,
  setValidSelect,
  setValidTextInput,
  setValidTick,
  runValidation,
  detectJS,
  getFocusableEls,
  focusFirstEl,
  isActiveElement,
  getElements,
  isTabPressed,
  isEscPressed,
  isEnterPressed,
  isSpacePressed,
  isUpPressed,
  isDownPressed,
  isLeftPressed,
  isRightPressed,
  toggleValue,
  dropdowns,
  bindDropdownUIEvents,
  toggleDropDown,
  hideDropDown,
  showDropDown,
  removeActiveStatus,
  stepper,
  carousel,
  bindStepperUIEvents,
  toggleScrollEvent,
  isElementVisible,
  scrollYDirection,
  checkScrollDirection,
  toggleMenu,
  hugeTextInput,
  hugeInput,
  bindUIEventsHugeInput,
  bindUIEventsHugeInputOld,
  addClassIfNotEmpty,
  toggleClassWithValue,
  toggleAriaExpandedAttribute,
  generateAriaControls,
  generateAriaOwns,
  checkbox,
  bindCheckboxUIEvents,
  generateIdForInput,
  radioInput,
  bindRadioUIEvents,
  resetListItems,
};
<|endoftext|>