<commit_before>/**
 * RunTime.js
 *
 * Copyright 2013, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

/*jshint smarttabs:true, undef:true, unused:true, latedef:true, curly:true, bitwise:true, scripturl:true, browser:true */
/*global define:true, ActiveXObject:true */

/**
Defines constructor for Silverlight runtime.

@class moxie/runtime/silverlight/Runtime
@private
*/
define("moxie/runtime/silverlight/Runtime", [
	"moxie/core/utils/Basic",
	"moxie/core/utils/Env",
	"moxie/core/utils/Dom",
	"moxie/core/Exceptions",
	"moxie/runtime/Runtime"
], function(Basic, Env, Dom, x, Runtime) {

	var type = 'silverlight', extensions = {};

	/**
	Constructor for the Silverlight Runtime

	@class SilverlightRuntime
	@extends Runtime
	*/
	Runtime.addConstructor(type, (function() {

		function SilverlightRuntime(options) {
			var I = this, initTimer;

			function isInstalled(version) {
				var isVersionSupported = false, control = null, actualVer,
					actualVerArray, reqVerArray, requiredVersionPart, actualVersionPart, index = 0;

				try {
					try {
						control = new ActiveXObject('AgControl.AgControl');

						if (control.IsVersionSupported(version)) {
							isVersionSupported = true;
						}

						control = null;
					} catch (e) {
						var plugin = navigator.plugins["Silverlight Plug-In"];

						if (plugin) {
							actualVer = plugin.description;

							if (actualVer === "1.0.30226.2") {
								actualVer = "2.0.30226.2";
							}

							actualVerArray = actualVer.split(".");

							while (actualVerArray.length > 3) {
								actualVerArray.pop();
							}

							while ( actualVerArray.length < 4) {
								actualVerArray.push(0);
							}

							reqVerArray = version.split(".");

							while (reqVerArray.length > 4) {
								reqVerArray.pop();
							}

							do {
								requiredVersionPart = parseInt(reqVerArray[index], 10);
								actualVersionPart = parseInt(actualVerArray[index], 10);
								index++;
							} while (index < reqVerArray.length && requiredVersionPart === actualVersionPart);

							if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) {
								isVersionSupported = true;
							}
						}
					}
				} catch (e2) {
					isVersionSupported = false;
				}

				return isVersionSupported;
			}

			Runtime.call(this, type, Basic.extend({}, { xap_url: Env.xap_url }, options));

			Basic.extend(this, {

				getShim: function() {
					return Dom.get(this.uid).content.Moxie;
				},

				init : function() {
					var container;

					// minimal requirement Flash Player 10
					if (!isInstalled('2.0.31005.0') || Env.browser === 'Opera') {
						this.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
						return;
					}

					container = this.getShimContainer();

					container.innerHTML = '<object id="' + this.uid + '" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;">' +
						'<param name="source" value="' + options.xap_url + '"/>' +
						'<param name="background" value="Transparent"/>' +
						'<param name="windowless" value="true"/>' +
						'<param name="enablehtmlaccess" value="true"/>' +
						'<param name="initParams" value="uid=' + this.uid + ',target=' + Env.global_event_dispatcher + '"/>' +
					'</object>';

					// Init is dispatched by the shim
					initTimer = setTimeout(function() {
						if (I && !I.initialized) { // runtime might be already destroyed by this moment
							I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
						}
					}, 5000); // silverlight may take quite some time to initialize
				},

				destroy: (function(destroy) { // extend default destroy method
					return function() {
						destroy.call(I);
						clearTimeout(initTimer); // initialization check might be still onwait
						initTimer = destroy = I = null;
					};
				}(this.destroy))

			}, extensions);
		}

		SilverlightRuntime.can = (function() {
			var use_clienthttp = function() {
					var rc = this.options.required_caps || {};
					return  rc.send_custom_headers ||
						rc.return_status_code && Basic.arrayDiff(rc.return_status_code, [200, 404]) ||
						rc.use_http_method && Basic.arrayDiff(rc.use_http_method, ['GET', 'POST']);
				},

				caps = Basic.extend({}, Runtime.caps, {
					access_binary: true,
					access_image_binary: true,
					display_media: true,
					drag_and_drop: false,
					report_upload_progress: true,
					resize_image: true,
					return_response_headers: function() {
						return use_clienthttp.call(this);
					},
					return_response_type: true,
					return_status_code: function(code) {
						return use_clienthttp.call(this) || !Basic.arrayDiff(code, [200, 404]);
					},
					select_multiple: true,
					send_binary_string: true,
					send_browser_cookies: function() {
						return !use_clienthttp.call(this);
					},
					send_custom_headers: function() {
						return use_clienthttp.call(this);
					},
					send_multipart: true,
					slice_blob: true,
					stream_upload: true,
					summon_file_dialog: false,
					upload_filesize: true,
					use_http_method: function(methods) {
						return use_clienthttp.call(this) || !Basic.arrayDiff(methods, ['GET', 'POST']);
					}
				});

			function can() {
				var args = [].slice.call(arguments);
				args.unshift(caps);
				return Runtime.can.apply(this, args);
			}
			return can;
		}());

		return SilverlightRuntime;
	}()));

	return extensions;
});
<commit_msg>Runtime, Silverlight: In Mac OS X Silverlight sometimes takes too long to initialize on first load. Give it 10 seconds, instead of just 5 on Windows.<commit_after>/**
 * RunTime.js
 *
 * Copyright 2013, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

/*jshint smarttabs:true, undef:true, unused:true, latedef:true, curly:true, bitwise:true, scripturl:true, browser:true */
/*global define:true, ActiveXObject:true */

/**
Defines constructor for Silverlight runtime.

@class moxie/runtime/silverlight/Runtime
@private
*/
define("moxie/runtime/silverlight/Runtime", [
	"moxie/core/utils/Basic",
	"moxie/core/utils/Env",
	"moxie/core/utils/Dom",
	"moxie/core/Exceptions",
	"moxie/runtime/Runtime"
], function(Basic, Env, Dom, x, Runtime) {

	var type = 'silverlight', extensions = {};

	/**
	Constructor for the Silverlight Runtime

	@class SilverlightRuntime
	@extends Runtime
	*/
	Runtime.addConstructor(type, (function() {

		function SilverlightRuntime(options) {
			var I = this, initTimer;

			function isInstalled(version) {
				var isVersionSupported = false, control = null, actualVer,
					actualVerArray, reqVerArray, requiredVersionPart, actualVersionPart, index = 0;

				try {
					try {
						control = new ActiveXObject('AgControl.AgControl');

						if (control.IsVersionSupported(version)) {
							isVersionSupported = true;
						}

						control = null;
					} catch (e) {
						var plugin = navigator.plugins["Silverlight Plug-In"];

						if (plugin) {
							actualVer = plugin.description;

							if (actualVer === "1.0.30226.2") {
								actualVer = "2.0.30226.2";
							}

							actualVerArray = actualVer.split(".");

							while (actualVerArray.length > 3) {
								actualVerArray.pop();
							}

							while ( actualVerArray.length < 4) {
								actualVerArray.push(0);
							}

							reqVerArray = version.split(".");

							while (reqVerArray.length > 4) {
								reqVerArray.pop();
							}

							do {
								requiredVersionPart = parseInt(reqVerArray[index], 10);
								actualVersionPart = parseInt(actualVerArray[index], 10);
								index++;
							} while (index < reqVerArray.length && requiredVersionPart === actualVersionPart);

							if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) {
								isVersionSupported = true;
							}
						}
					}
				} catch (e2) {
					isVersionSupported = false;
				}

				return isVersionSupported;
			}

			Runtime.call(this, type, Basic.extend({}, { xap_url: Env.xap_url }, options));

			Basic.extend(this, {

				getShim: function() {
					return Dom.get(this.uid).content.Moxie;
				},

				init : function() {
					var container;

					// minimal requirement Flash Player 10
					if (!isInstalled('2.0.31005.0') || Env.browser === 'Opera') {
						this.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
						return;
					}

					container = this.getShimContainer();

					container.innerHTML = '<object id="' + this.uid + '" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;">' +
						'<param name="source" value="' + options.xap_url + '"/>' +
						'<param name="background" value="Transparent"/>' +
						'<param name="windowless" value="true"/>' +
						'<param name="enablehtmlaccess" value="true"/>' +
						'<param name="initParams" value="uid=' + this.uid + ',target=' + Env.global_event_dispatcher + '"/>' +
					'</object>';

					// Init is dispatched by the shim
					initTimer = setTimeout(function() {
						if (I && !I.initialized) { // runtime might be already destroyed by this moment
							I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
						}
					}, Env.OS !== 'Windows'? 10000 : 5000); // give it more time to initialize in non Windows OS (like Mac)
				},

				destroy: (function(destroy) { // extend default destroy method
					return function() {
						destroy.call(I);
						clearTimeout(initTimer); // initialization check might be still onwait
						initTimer = destroy = I = null;
					};
				}(this.destroy))

			}, extensions);
		}

		SilverlightRuntime.can = (function() {
			var use_clienthttp = function() {
					var rc = this.options.required_caps || {};
					return  rc.send_custom_headers ||
						rc.return_status_code && Basic.arrayDiff(rc.return_status_code, [200, 404]) ||
						rc.use_http_method && Basic.arrayDiff(rc.use_http_method, ['GET', 'POST']);
				},

				caps = Basic.extend({}, Runtime.caps, {
					access_binary: true,
					access_image_binary: true,
					display_media: true,
					drag_and_drop: false,
					report_upload_progress: true,
					resize_image: true,
					return_response_headers: function() {
						return use_clienthttp.call(this);
					},
					return_response_type: true,
					return_status_code: function(code) {
						return use_clienthttp.call(this) || !Basic.arrayDiff(code, [200, 404]);
					},
					select_multiple: true,
					send_binary_string: true,
					send_browser_cookies: function() {
						return !use_clienthttp.call(this);
					},
					send_custom_headers: function() {
						return use_clienthttp.call(this);
					},
					send_multipart: true,
					slice_blob: true,
					stream_upload: true,
					summon_file_dialog: false,
					upload_filesize: true,
					use_http_method: function(methods) {
						return use_clienthttp.call(this) || !Basic.arrayDiff(methods, ['GET', 'POST']);
					}
				});

			function can() {
				var args = [].slice.call(arguments);
				args.unshift(caps);
				return Runtime.can.apply(this, args);
			}
			return can;
		}());

		return SilverlightRuntime;
	}()));

	return extensions;
});
<|endoftext|>


<commit_before>'use strict';

angular.module('copayApp.controllers').controller('collectEmailController', function($scope, $state, $timeout, profileService, configService, walletService) {

  var wallet, walletId;
  $scope.data = {};

  $scope.$on("$ionicView.beforeEnter", function(event, data) {
    walletId = data.stateParams.walletId;
    wallet = profileService.getWallet(walletId);
    $scope.data.accept = true;
  });

  $scope.save = function() {
    var opts = {
      emailFor: {}
    };
    opts.emailFor[walletId] = $scope.data.email;
    walletService.updateRemotePreferences(wallet, {
      email: $scope.data.email,
    }, function(err) {
      if (err) $log.warn(err);
      configService.set(opts, function(err) {
        if (err) $log.warn(err);
        $scope.goNextView();
      });
    });
  };

  $scope.goNextView = function() {
    $state.go('onboarding.backupRequest', {
      walletId: walletId
    });
  };

  $scope.confirm = function(emailForm) {
    if (emailForm.$invalid) return;
    $scope.confirmation = true;
  };

  $scope.cancel = function() {
    $scope.confirmation = false;
    $timeout(function() {
      $scope.$digest();
    }, 1);
  };

});
<commit_msg>Collect email with google sheets<commit_after>'use strict';

angular.module('copayApp.controllers').controller('collectEmailController', function($scope, $state, $log, $timeout, $http, $httpParamSerializer, profileService, configService, walletService, appConfigService) {

  var wallet, walletId;
  $scope.data = {};
  // Get more info: https://mashe.hawksey.info/2014/07/google-sheets-as-a-database-insert-with-apps-script-using-postget-methods-with-ajax-example/
  var URL = "https://script.google.com/macros/s/AKfycbwQXvUw6-Ix0cRLMi7hBB8dlgNTCTgwfNIQRds6RypPV7dO8evW/exec";

  var _post = function(dataSrc) {
    return {
      method: 'POST',
      url: URL,
      headers: {
        'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
      },
      data: $httpParamSerializer(dataSrc)
    };
  };

  $scope.$on("$ionicView.beforeEnter", function(event, data) {
    walletId = data.stateParams.walletId;
    wallet = profileService.getWallet(walletId);
    $scope.data.accept = true;
  });

  var collectEmail = function() {
    var dataSrc = {
      "App": appConfigService.nameCase,
      "Email": $scope.data.email,
      "Platform": ionic.Platform.platform(),
      "DeviceVersion": ionic.Platform.version()
    };

    $http(_post(dataSrc)).then(function() {
      $log.info("SUCCESS: Email collected");
    }, function(err) {
      $log.error("ERROR: Could not collect email");
    });
  };

  $scope.save = function() {
    var opts = {
      emailFor: {}
    };
    opts.emailFor[walletId] = $scope.data.email;
    walletService.updateRemotePreferences(wallet, {
      email: $scope.data.email,
    }, function(err) {
      if (err) $log.warn(err);
      configService.set(opts, function(err) {
        if (err) $log.warn(err);
        if ($scope.data.accept) collectEmail();
        $scope.goNextView();
      });
    });
  };

  $scope.goNextView = function() {
    $state.go('onboarding.backupRequest', {
      walletId: walletId
    });
  };

  $scope.confirm = function(emailForm) {
    if (emailForm.$invalid) return;
    $scope.confirmation = true;
  };

  $scope.cancel = function() {
    $scope.confirmation = false;
    $timeout(function() {
      $scope.$digest();
    }, 1);
  };

});
<|endoftext|>


<commit_before>/*
---
name: ART.Input
description: Base Input Class
requires: [ART.Sheet, ART.Widget, ART/ART.Rectangle, ART/Pill]
provides: ART.Input
...
*/

(function(){

ART.Sheet.define('input.art', {
	'width': 150,
	'height': 22,
	'border-color': 'hsb(0, 0, 0, 0.4)',
	'reflection-color': ['hsb(0, 0, 83)', 'hsb(0, 0, 0, 0)'],
	'background-color': 'hsb(0, 0, 100)',
	'shadow-color': 'hsb(0, 0, 0, 0.18)',
	'border-radius': [2, 2, 2, 2],
	'font-family': 'Arial',
	'font-variant': 'normal',
	'font-size': 12,
	'font-color': 'hsb(0, 0, 5)',
	'placeholder-color': 'hsb(0, 0, 60)',
	'padding': [2, 6, 2, 6]
});

ART.Sheet.define('input.art:focused', {
	'border-color': ['hsb(205, 80, 100)', 'hsb(205, 100, 95)']
});

var Input = ART.Input = new Class({

	Extends: ART.Widget,

	name: 'input',

	options: {
		placeholder: null,
		tabIndex: null,
		inputElement: null,
		blurOnElementBlur: true,
		placeholder: null,
		useChange: true,
		changeTimeout: 500
	},

	initialize: function(options){
		this.parent($merge(options, {useFocus: false}));

		this.shadowLayer = new ART.Rectangle;
		this.borderLayer = new ART.Rectangle;
		this.reflectionLayer = new ART.Rectangle;
		this.backgroundLayer = new ART.Rectangle;
		this.canvas.grab(this.shadowLayer, this.borderLayer, this.reflectionLayer, this.backgroundLayer);

		this.input = (this.options.inputElement || new Element('input')).setStyles({
			border: 0, outline: "none", padding: 0, margin: 0, position: 'absolute', top: 0, left: 0, background: 'transparent',
			tabIndex: this.options.tabIndex
		});

		this.input.inject(this.element);

		this.lastChange = this.input.value;

		if (this.options.placeholder) this._holdPlace();

		var self = this;

		this.input.addEvents({

			focus: function(){
				if (self.holdingPlace) this.value = '';
				self.holdingPlace = false;
			},

			blur: function(){
				self._holdPlace();
			}

		});

		var change = null;

		if (this.options.useChange) this.input.addEvent('keydown', function(){
			var input = this;
			if (change != null) clearTimeout(change);
			change = function(){
				if (input.value != self.lastChange){
					self.fireEvent('change', input.value);
					self.lastChange = input.value;
				}
			}.delay(self.options.changeTimeout);
		});

		this._setFocusEvents(this.input);
	},

	_holdPlace: function(){
		if (this.input.value == ''){
			this.input.value = this.options.placeholder;
			this.holdingPlace = true;
		}
	},

	draw: function(newSheet){
		var sheet = this.parent(newSheet), cs = this.currentSheet;
		var boxChanged = !!(sheet.width || sheet.height || sheet.padding || sheet.borderRadius);

		if (cs.glyph && !this.glyphLayer){
			this.glyphLayer = new ART.Shape(cs.glyph);
			this.canvas.grab(this.glyphLayer);
		} else if (!cs.glyph && this.glyphLayer){
			this.glyphLayer.eject();
			this.glyphLayer = null;
		}

		if (boxChanged){
			this.resize(cs.width, cs.height + 1);

			var brt = cs.borderRadius[0], brr = cs.borderRadius[1];
			var brb = cs.borderRadius[2], brl = cs.borderRadius[3];

			var pill = ((cs.width < cs.height) ? cs.width : cs.height) / 2;
			this.shadowLayer.draw(cs.width, cs.height, cs.pill ? pill : cs.borderRadius).translate(0, 1);
			this.borderLayer.draw(cs.width, cs.height, cs.pill ? pill : cs.borderRadius);
			this.reflectionLayer.draw(cs.width - 2, cs.height - 2, cs.pill ? pill - 1 : [brt - 1, brr - 1, brb - 1, brl - 1]).translate(1, 1);
			this.backgroundLayer.draw(cs.width - 2, cs.height - 3, cs.pill ? pill - 1 : [brt - 1, brr - 1, brb - 1, brl - 1]).translate(1, 2);

			this.input.setStyles({
				width: cs.width - cs.padding[1] - cs.padding[3],
				height: cs.height - cs.padding[0] - cs.padding[2],
				top: cs.padding[0],
				left: cs.padding[3]
			});
			if (this.glyphLayer) this.glyphLayer.translate(cs.glyphLeft, cs.glyphTop);
		}

		if (sheet.fontFamily) this.input.setStyle('font-family', sheet.fontFamily);
		if (this.holdingPlace) this.input.setStyle('color', new Color(cs.placeholderColor).toHEX());
		else this.input.setStyle('color', new Color(cs.fontColor).toHEX());
		if (sheet.fontSize) this.input.setStyle('font-size', sheet.fontSize + 'px');

		if (sheet.shadowColor) this.shadowLayer.fill.apply(this.shadowLayer, $splat(cs.shadowColor));
		if (sheet.borderColor) this.borderLayer.fill.apply(this.borderLayer, $splat(cs.borderColor));
		if (sheet.reflectionColor) this.reflectionLayer.fill.apply(this.reflectionLayer, $splat(cs.reflectionColor));
		if (sheet.backgroundColor) this.backgroundLayer.fill.apply(this.backgroundLayer, $splat(cs.backgroundColor));
		if (sheet.glyphColor && this.glyphLayer) this.glyphLayer.fill.apply(this.glyphLayer, $splat(cs.glyphColor));

		return this;

	}

});

})();
<commit_msg>removed errant dependancy.<commit_after>/*
---
name: ART.Input
description: Base Input Class
requires: [ART.Sheet, ART.Widget, ART/ART.Rectangle]
provides: ART.Input
...
*/

(function(){

ART.Sheet.define('input.art', {
	'width': 150,
	'height': 22,
	'border-color': 'hsb(0, 0, 0, 0.4)',
	'reflection-color': ['hsb(0, 0, 83)', 'hsb(0, 0, 0, 0)'],
	'background-color': 'hsb(0, 0, 100)',
	'shadow-color': 'hsb(0, 0, 0, 0.18)',
	'border-radius': [2, 2, 2, 2],
	'font-family': 'Arial',
	'font-variant': 'normal',
	'font-size': 12,
	'font-color': 'hsb(0, 0, 5)',
	'placeholder-color': 'hsb(0, 0, 60)',
	'padding': [2, 6, 2, 6]
});

ART.Sheet.define('input.art:focused', {
	'border-color': ['hsb(205, 80, 100)', 'hsb(205, 100, 95)']
});

var Input = ART.Input = new Class({

	Extends: ART.Widget,

	name: 'input',

	options: {
		placeholder: null,
		tabIndex: null,
		inputElement: null,
		blurOnElementBlur: true,
		placeholder: null,
		useChange: true,
		changeTimeout: 500
	},

	initialize: function(options){
		this.parent($merge(options, {useFocus: false}));

		this.shadowLayer = new ART.Rectangle;
		this.borderLayer = new ART.Rectangle;
		this.reflectionLayer = new ART.Rectangle;
		this.backgroundLayer = new ART.Rectangle;
		this.canvas.grab(this.shadowLayer, this.borderLayer, this.reflectionLayer, this.backgroundLayer);

		this.input = (this.options.inputElement || new Element('input')).setStyles({
			border: 0, outline: "none", padding: 0, margin: 0, position: 'absolute', top: 0, left: 0, background: 'transparent',
			tabIndex: this.options.tabIndex
		});

		this.input.inject(this.element);

		this.lastChange = this.input.value;

		if (this.options.placeholder) this._holdPlace();

		var self = this;

		this.input.addEvents({

			focus: function(){
				if (self.holdingPlace) this.value = '';
				self.holdingPlace = false;
			},

			blur: function(){
				self._holdPlace();
			}

		});

		var change = null;

		if (this.options.useChange) this.input.addEvent('keydown', function(){
			var input = this;
			if (change != null) clearTimeout(change);
			change = function(){
				if (input.value != self.lastChange){
					self.fireEvent('change', input.value);
					self.lastChange = input.value;
				}
			}.delay(self.options.changeTimeout);
		});

		this._setFocusEvents(this.input);
	},

	_holdPlace: function(){
		if (this.input.value == ''){
			this.input.value = this.options.placeholder;
			this.holdingPlace = true;
		}
	},

	draw: function(newSheet){
		var sheet = this.parent(newSheet), cs = this.currentSheet;
		var boxChanged = !!(sheet.width || sheet.height || sheet.padding || sheet.borderRadius);

		if (cs.glyph && !this.glyphLayer){
			this.glyphLayer = new ART.Shape(cs.glyph);
			this.canvas.grab(this.glyphLayer);
		} else if (!cs.glyph && this.glyphLayer){
			this.glyphLayer.eject();
			this.glyphLayer = null;
		}

		if (boxChanged){
			this.resize(cs.width, cs.height + 1);

			var brt = cs.borderRadius[0], brr = cs.borderRadius[1];
			var brb = cs.borderRadius[2], brl = cs.borderRadius[3];

			var pill = ((cs.width < cs.height) ? cs.width : cs.height) / 2;
			this.shadowLayer.draw(cs.width, cs.height, cs.pill ? pill : cs.borderRadius).translate(0, 1);
			this.borderLayer.draw(cs.width, cs.height, cs.pill ? pill : cs.borderRadius);
			this.reflectionLayer.draw(cs.width - 2, cs.height - 2, cs.pill ? pill - 1 : [brt - 1, brr - 1, brb - 1, brl - 1]).translate(1, 1);
			this.backgroundLayer.draw(cs.width - 2, cs.height - 3, cs.pill ? pill - 1 : [brt - 1, brr - 1, brb - 1, brl - 1]).translate(1, 2);

			this.input.setStyles({
				width: cs.width - cs.padding[1] - cs.padding[3],
				height: cs.height - cs.padding[0] - cs.padding[2],
				top: cs.padding[0],
				left: cs.padding[3]
			});
			if (this.glyphLayer) this.glyphLayer.translate(cs.glyphLeft, cs.glyphTop);
		}

		if (sheet.fontFamily) this.input.setStyle('font-family', sheet.fontFamily);
		if (this.holdingPlace) this.input.setStyle('color', new Color(cs.placeholderColor).toHEX());
		else this.input.setStyle('color', new Color(cs.fontColor).toHEX());
		if (sheet.fontSize) this.input.setStyle('font-size', sheet.fontSize + 'px');

		if (sheet.shadowColor) this.shadowLayer.fill.apply(this.shadowLayer, $splat(cs.shadowColor));
		if (sheet.borderColor) this.borderLayer.fill.apply(this.borderLayer, $splat(cs.borderColor));
		if (sheet.reflectionColor) this.reflectionLayer.fill.apply(this.reflectionLayer, $splat(cs.reflectionColor));
		if (sheet.backgroundColor) this.backgroundLayer.fill.apply(this.backgroundLayer, $splat(cs.backgroundColor));
		if (sheet.glyphColor && this.glyphLayer) this.glyphLayer.fill.apply(this.glyphLayer, $splat(cs.glyphColor));

		return this;

	}

});

})();
<|endoftext|>


<commit_before>
(function() {
  // 'use strict';

  /* global ripple: false, angular: false, _: false, jQuery: false, store: false, Options: false */

  function AddressPopover($timeout, id, $filter, $parse, scope, element, attr) {
    this.$timeout = $timeout;
    this.$parse = $parse;
    this.scope = scope;
    this.element = element;

    this.cancelHidePopoverTimeout = null;
    this.cancelShowPopoverTimeout = null;
    this.tip = null;
    this.shown = false;
    this.identity = '';
    this.summ = '';
    this.rippleName = '';
    this.rpamountFilter = $filter('rpamount');
    this.popoverCreated = false;
    this.rpAddressPopoverSum = attr.rpAddressPopoverSum;
    this.rpAddressPopoverSumMinus = attr.rpAddressPopoverSumMinus;

    if (attr.rpAddressPopover && attr.rpAddressPopover != 'rp-address-popover') {
      this.identity = $parse(attr.rpAddressPopover)(scope);
    }

    this.onPopoverEnterBound = null;
    this.onPopoverLeaveBound = null;
    this.onElemLeaveBound = null;
    this.onElemEnterBound = this.onElemEnter.bind(this);
    element.bind('mouseenter', this.onElemEnterBound);

    var _this = this;
    if (attr.rpAddressPopoverLinkToCharts) {
      id.resolveName(this.identity, { tilde: true }).then(function(name) {
        _this.rippleName = name;
        if (_this.popoverCreated) {
          var data = element.data('popover');
          if (data) {
            data.options.content = _this.makeContent();
            data.setContent();
          }
        }
      });
    }

    // Make sure popover is destroyed and removed.
    scope.$on('$destroy', function onDestroyPopover() {
      $timeout.cancel(_this.cancelHidePopoverTimeout);
      _this.cancelHidePopoverTimeout = null;
      $timeout.cancel(_this.cancelShowPopoverTimeout);
      _this.cancelShowPopoverTimeout = null;
      _this.unbindHanlders();
      if (_this.tip) {
        _this.tip.remove();
        _this.tip = null;
      }
      this.scope = null;
      this.element = null;
      this.onPopoverEnterBound = null;
      this.onPopoverLeaveBound = null;
      this.onElemLeaveBound = null;
      this.onElemEnterBound = null;
    });
  }

  AddressPopover.popupDelay = 800;
  AddressPopover.hideDelay =  700;
  AddressPopover.summFilterOpts = { force_precision: 100, min_precision: 2 };

  AddressPopover.prototype.create = function() {
    if (this.rpAddressPopoverSum) {
      var nowSumm = this.$parse(this.rpAddressPopoverSum)(this.scope);
      nowSumm = this.rpamountFilter(nowSumm, AddressPopover.summFilterOpts);
      if (nowSumm != this.summ) {
        if (this.rpAddressPopoverSumMinus && nowSumm != 'n/a') {
          nowSumm = '-' + nowSumm;
        }
        this.summ = nowSumm;
      }
    }

    var options = {
      content: this.makeContent(),
      html: true,
      trigger: 'manual', placement: 'top',
      container: 'body',
      template: '

'
    };

    var popover = this.element.popover(options);
    this.tip = this.element.data('popover').tip();
    this.onPopoverEnterBound = this.onPopoverEnter.bind(this);
    this.tip.bind('mouseenter', this.onPopoverEnterBound);
    this.onPopoverLeaveBound = this.onPopoverLeave.bind(this);
    this.tip.bind('mouseleave', this.onPopoverLeaveBound);
    this.popoverCreated = true;
  }

  AddressPopover.prototype.makeContent = function() {
    var htmlContent = ['
'];
    if (this.summ) {
      htmlContent.push('
', String(this.summ), '
');
    }

    if (this.rippleName) {
      if (this.rippleName !== this.identity) {
        htmlContent.push('
', this.rippleName, '
');
      }
      htmlContent.push('', this.identity, '', '
');
      htmlContent.push('', AddressPopover.textShowInGraph, '');
    } else if (this.identity) {
      htmlContent.push(AddressPopover.textRippleAddress, ' ', this.identity);
    }
    htmlContent.push('
');
    return htmlContent.join('');
  }

  AddressPopover.prototype.showPopover = function() {
    if (!this.popoverCreated) {
      this.create();
    }

    var _this = this;
    // allow $compile to bind values to template
    this.$timeout(function() {
      _this.element.popover('show');
      _this.shown = true;
    }, 10, false);
  }

  AddressPopover.prototype.hidePopover = function() {
    if (!this.cancelHidePopoverTimeout) {
      var _this = this;
      this.cancelHidePopoverTimeout = this.$timeout(function() {
        _this.element.popover('hide');
        _this.shown = false;
      }, AddressPopover.hideDelay, false);
      this.cancelHidePopoverTimeout['finally'](function() {
        _this.cancelHidePopoverTimeout = null;
      });
    }
  }

  AddressPopover.prototype.onPopoverEnter = function() {
    if (this.cancelShowPopoverTimeout) {
      this.$timeout.cancel(this.cancelShowPopoverTimeout);
      this.cancelShowPopoverTimeout = null;
    }
    if (this.cancelHidePopoverTimeout) {
      this.$timeout.cancel(this.cancelHidePopoverTimeout);
      this.cancelHidePopoverTimeout = null;
    }
  }

  AddressPopover.prototype.onPopoverLeave = function() {
    this.hidePopover();
  }

  AddressPopover.prototype.onElemEnter = function() {
    if (!this.onElemLeaveBound) {
      this.onElemLeaveBound = this.onElemLeave.bind(this)
      this.element.bind('mouseleave', this.onElemLeaveBound);
    }

    if (this.cancelHidePopoverTimeout) {
      this.$timeout.cancel(this.cancelHidePopoverTimeout);
      this.cancelHidePopoverTimeout = null;
    } else if (!this.cancelShowPopoverTimeout) {
      this.cancelShowPopoverTimeout = this.$timeout(this.showPopover.bind(this), AddressPopover.popupDelay, false);
      this.cancelShowPopoverTimeout['finally'](this.onCancelShowPopoverTimeoutFinally.bind(this));
    }
  }

  AddressPopover.prototype.onCancelShowPopoverTimeoutFinally = function() {
    this.cancelShowPopoverTimeout = null;
  }

  AddressPopover.prototype.onElemLeave = function() {
    if (this.cancelShowPopoverTimeout) {
      this.$timeout.cancel(this.cancelShowPopoverTimeout);
      this.cancelShowPopoverTimeout = null;
    } else if (this.shown) {
      this.hidePopover();
    }
  }

  AddressPopover.prototype.unbindHanlders = function() {
    this.element.unbind('mouseenter', this.onElemEnterBound);
    this.element.unbind('mouseleave', this.onElemLeaveBound);

    if (this.tip) {
      this.tip.unbind('mouseenter', this.onPopoverEnterBound);
      this.tip.unbind('mouseleave', this.onPopoverLeaveBound);
    }
  }

  var myTemplate = require('../../templates/directives/addresspopover.jade')();
  var texts = myTemplate.split('
');

  AddressPopover.textRippleAddress = texts[0];
  AddressPopover.textShowInGraph = texts.length > 1 ? texts[1] : 'Show in graph';

  /**
   * Special popover to show ripple address with ability to double click on address to select.
   * Also can link to www.ripplecharts.com.
   * rp-address-popover-link-to-charts - show ling to ripple charts
   * rp-address-popover-sum - show full sum of according model in popover
   * rp-address-popover-sum-minus - put minus sign before sum
   */
  angular.module('directives').directive('rpAddressPopover', rpAddressPopover);

  rpAddressPopover.$inject = ['$timeout', 'rpId', '$filter', '$parse'];

  function rpAddressPopover($timeout, id, $filter, $parse) {
    return {
      restrict: 'A',
      replace: false,
      compile: function (element, attr, linker) {
        return function (scope, element, attr) {
          var p = new AddressPopover($timeout, id, $filter, $parse, scope, element, attr);
        };
      }
    };
  }
})();
<commit_msg>[FIX] addressPopover: use $templateRequest (RT-3357)<commit_after>
(function() {
  // 'use strict';

  /* global ripple: false, angular: false, _: false, jQuery: false, store: false, Options: false */

  function AddressPopover($timeout, id, $filter, $parse, scope, element, attr) {
    this.$timeout = $timeout;
    this.$parse = $parse;
    this.scope = scope;
    this.element = element;

    this.cancelHidePopoverTimeout = null;
    this.cancelShowPopoverTimeout = null;
    this.tip = null;
    this.shown = false;
    this.identity = '';
    this.summ = '';
    this.rippleName = '';
    this.rpamountFilter = $filter('rpamount');
    this.popoverCreated = false;
    this.rpAddressPopoverSum = attr.rpAddressPopoverSum;
    this.rpAddressPopoverSumMinus = attr.rpAddressPopoverSumMinus;

    if (attr.rpAddressPopover && attr.rpAddressPopover != 'rp-address-popover') {
      this.identity = $parse(attr.rpAddressPopover)(scope);
    }

    this.onPopoverEnterBound = null;
    this.onPopoverLeaveBound = null;
    this.onElemLeaveBound = null;
    this.onElemEnterBound = this.onElemEnter.bind(this);
    element.bind('mouseenter', this.onElemEnterBound);

    var _this = this;
    if (attr.rpAddressPopoverLinkToCharts) {
      id.resolveName(this.identity, { tilde: true }).then(function(name) {
        _this.rippleName = name;
        if (_this.popoverCreated) {
          var data = element.data('popover');
          if (data) {
            data.options.content = _this.makeContent();
            data.setContent();
          }
        }
      });
    }

    // Make sure popover is destroyed and removed.
    scope.$on('$destroy', function onDestroyPopover() {
      $timeout.cancel(_this.cancelHidePopoverTimeout);
      _this.cancelHidePopoverTimeout = null;
      $timeout.cancel(_this.cancelShowPopoverTimeout);
      _this.cancelShowPopoverTimeout = null;
      _this.unbindHanlders();
      if (_this.tip) {
        _this.tip.remove();
        _this.tip = null;
      }
      this.scope = null;
      this.element = null;
      this.onPopoverEnterBound = null;
      this.onPopoverLeaveBound = null;
      this.onElemLeaveBound = null;
      this.onElemEnterBound = null;
    });
  }

  AddressPopover.popupDelay = 800;
  AddressPopover.hideDelay =  700;
  AddressPopover.summFilterOpts = { force_precision: 100, min_precision: 2 };

  AddressPopover.prototype.create = function() {
    if (this.rpAddressPopoverSum) {
      var nowSumm = this.$parse(this.rpAddressPopoverSum)(this.scope);
      nowSumm = this.rpamountFilter(nowSumm, AddressPopover.summFilterOpts);
      if (nowSumm != this.summ) {
        if (this.rpAddressPopoverSumMinus && nowSumm != 'n/a') {
          nowSumm = '-' + nowSumm;
        }
        this.summ = nowSumm;
      }
    }

    var options = {
      content: this.makeContent(),
      html: true,
      trigger: 'manual', placement: 'top',
      container: 'body',
      template: '

'
    };

    var popover = this.element.popover(options);
    this.tip = this.element.data('popover').tip();
    this.onPopoverEnterBound = this.onPopoverEnter.bind(this);
    this.tip.bind('mouseenter', this.onPopoverEnterBound);
    this.onPopoverLeaveBound = this.onPopoverLeave.bind(this);
    this.tip.bind('mouseleave', this.onPopoverLeaveBound);
    this.popoverCreated = true;
  }

  AddressPopover.prototype.makeContent = function() {
    var htmlContent = ['
'];
    if (this.summ) {
      htmlContent.push('
', String(this.summ), '
');
    }

    if (this.rippleName) {
      if (this.rippleName !== this.identity) {
        htmlContent.push('
', this.rippleName, '
');
      }
      htmlContent.push('', this.identity, '', '
');
      htmlContent.push('', AddressPopover.textShowInGraph, '');
    } else if (this.identity) {
      htmlContent.push(AddressPopover.textRippleAddress, ' ', this.identity);
    }
    htmlContent.push('
');
    return htmlContent.join('');
  }

  AddressPopover.prototype.showPopover = function() {
    if (!this.popoverCreated) {
      this.create();
    }

    var _this = this;
    // allow $compile to bind values to template
    this.$timeout(function() {
      _this.element.popover('show');
      _this.shown = true;
    }, 10, false);
  }

  AddressPopover.prototype.hidePopover = function() {
    if (!this.cancelHidePopoverTimeout) {
      var _this = this;
      this.cancelHidePopoverTimeout = this.$timeout(function() {
        _this.element.popover('hide');
        _this.shown = false;
      }, AddressPopover.hideDelay, false);
      this.cancelHidePopoverTimeout['finally'](function() {
        _this.cancelHidePopoverTimeout = null;
      });
    }
  }

  AddressPopover.prototype.onPopoverEnter = function() {
    if (this.cancelShowPopoverTimeout) {
      this.$timeout.cancel(this.cancelShowPopoverTimeout);
      this.cancelShowPopoverTimeout = null;
    }
    if (this.cancelHidePopoverTimeout) {
      this.$timeout.cancel(this.cancelHidePopoverTimeout);
      this.cancelHidePopoverTimeout = null;
    }
  }

  AddressPopover.prototype.onPopoverLeave = function() {
    this.hidePopover();
  }

  AddressPopover.prototype.onElemEnter = function() {
    if (!this.onElemLeaveBound) {
      this.onElemLeaveBound = this.onElemLeave.bind(this)
      this.element.bind('mouseleave', this.onElemLeaveBound);
    }

    if (this.cancelHidePopoverTimeout) {
      this.$timeout.cancel(this.cancelHidePopoverTimeout);
      this.cancelHidePopoverTimeout = null;
    } else if (!this.cancelShowPopoverTimeout) {
      this.cancelShowPopoverTimeout = this.$timeout(this.showPopover.bind(this), AddressPopover.popupDelay, false);
      this.cancelShowPopoverTimeout['finally'](this.onCancelShowPopoverTimeoutFinally.bind(this));
    }
  }

  AddressPopover.prototype.onCancelShowPopoverTimeoutFinally = function() {
    this.cancelShowPopoverTimeout = null;
  }

  AddressPopover.prototype.onElemLeave = function() {
    if (this.cancelShowPopoverTimeout) {
      this.$timeout.cancel(this.cancelShowPopoverTimeout);
      this.cancelShowPopoverTimeout = null;
    } else if (this.shown) {
      this.hidePopover();
    }
  }

  AddressPopover.prototype.unbindHanlders = function() {
    this.element.unbind('mouseenter', this.onElemEnterBound);
    this.element.unbind('mouseleave', this.onElemLeaveBound);

    if (this.tip) {
      this.tip.unbind('mouseenter', this.onPopoverEnterBound);
      this.tip.unbind('mouseleave', this.onPopoverLeaveBound);
    }
  }

  AddressPopover.textRippleAddress = 'span(l10n) Ripple address';
  AddressPopover.textShowInGraph = 'span(l10n) Show in graph';

  /**
   * Special popover to show ripple address with ability to double click on address to select.
   * Also can link to www.ripplecharts.com.
   * rp-address-popover-link-to-charts - show ling to ripple charts
   * rp-address-popover-sum - show full sum of according model in popover
   * rp-address-popover-sum-minus - put minus sign before sum
   */
  angular.module('directives').directive('rpAddressPopover', rpAddressPopover);

  rpAddressPopover.$inject = ['$timeout', 'rpId', '$filter', '$parse', '$templateRequest'];

  function rpAddressPopover($timeout, id, $filter, $parse, $templateRequest) {
    $templateRequest('templates/' + window.lang + '/directives/addresspopover.html', false).then(function(template) {
      var texts = template.split('
');
      AddressPopover.textRippleAddress = texts[0];
      AddressPopover.textShowInGraph = texts.length > 1 ? texts[1] : AddressPopover.textShowInGraph;
    });

    return {
      restrict: 'A',
      replace: false,
      compile: function (element, attr, linker) {
        return function (scope, element, attr) {
          var p = new AddressPopover($timeout, id, $filter, $parse, scope, element, attr);
        };
      }
    };
  }
})();
<|endoftext|>


<commit_before>import React from 'react'
import { View, TouchableWithoutFeedback, Text, Animated, Easing, ScrollView, StyleSheet } from 'react-native'
import {initData, drawYAxis, drawGuideLine, drawYAxisLabels, numberWithCommas, drawXAxis, drawXAxisLabels} from '../common'

class LineChart extends React.Component {
  constructor (props) {
    super(props)
    let newState = initData(this.props.data, this.props.height, this.props.gap, this.props.numberOfYAxisGuideLine)
    this.state = {
      loading: false,
      sortedData: newState.sortedData,
      selectedIndex: null,
      nowHeight: 200,
      nowWidth: 200,
      scrollPosition: 0,
      nowX: 0,
      nowY: 0,
      max: newState.max,
      fadeAnim: new Animated.Value(0),
      guideArray: newState.guideArray
    }

    this.drawCoordinates = this.drawCoordinates.bind(this)
    this.drawCoordinate = this.drawCoordinate.bind(this)
    this.drawSelected = this.drawSelected.bind(this)
  }

  shouldComponentUpdate (nextProps, nextState) {
    if (nextState.sortedData !== this.state.sortedData ||
      nextState.selectedIndex !== this.state.selectedIndex ||
      nextState.scrollPosition !== this.state.scrollPosition) {
      return true
    } else {
      return false
    }
  }

  componentDidMount () {
    Animated.timing(this.state.fadeAnim, { toValue: 1, easing: Easing.bounce, duration: 1000, useNativeDriver: true }).start()
  }

  componentWillReceiveProps (nextProps) {
    if (nextProps.data !== this.props.data) {
      this.setState(Object.assign({
        fadeAnim: new Animated.Value(0)
      }, initData(nextProps.data, this.props.height, this.props.gap, this.props.numberOfYAxisGuideLine)), () => {
        Animated.timing(this.state.fadeAnim, { toValue: 1, easing: Easing.bounce, duration: 1000, useNativeDriver: true }).start()
      })
    }
  }

  getTransform (rad, width) {
    let x = (0 - width / 2) * Math.cos(rad) - (0 - width / 2) * Math.sin(rad)
    let y = (0 - width / 2) * Math.sin(rad) + (0 - width / 2) * Math.cos(rad)

    return [ {translateX: (-1 * x) - width / 2}, {translateY: (-1 * y) + width / 2}, { rotate: rad + 'rad' } ]
  }

  drawCoordinate (index, start, end, backgroundColor, lineStyle, isBlank, lastCoordinate, seriesIndex) {
    let key = 'line' + index
    let dx = end.gap - start.gap
    let dy = end.ratioY - start.ratioY
    let size = Math.sqrt(dx * dx + dy * dy)
    let angleRad = -1 * Math.atan2(dy, dx)
    let height
    let top
    let topMargin = 20

    if (start.ratioY > end.ratioY) {
      height = start.ratioY
      top = -1 * size
    } else {
      height = end.ratioY
      top = -1 * (size - Math.abs(dy))
    }

    return (
      <View key={key} style={{
        height: this.props.height + topMargin,
        justifyContent: 'flex-end'
      }}>

        <View style={StyleSheet.flatten([{
          width: dx,
          height: height,
          marginTop: topMargin
        }, styles.coordinateWrapper])}>
          <View style={StyleSheet.flatten([{
            top: top,
            width: size,
            height: size,
            borderColor: isBlank ? backgroundColor : this.props.primaryColor,
            borderTopWidth: 1,
            transform: this.getTransform(angleRad, size)
          }, styles.lineBox, lineStyle])} />
          <View style={StyleSheet.flatten([styles.absolute, {
            height: height - Math.abs(dy) - 2,
            backgroundColor: lastCoordinate ? '#FFFFFF00' : backgroundColor,
            marginTop: Math.abs(dy) + 2
          }])} />
        </View>
        {!lastCoordinate && seriesIndex === 0 ? (
          <View style={StyleSheet.flatten([styles.guideLine, {
            width: dx,
            borderRightColor: this.props.xAxisGridLineColor
          }])} />
        ) : null}
        {seriesIndex === this.state.sortedData.length - 1 && (
          <TouchableWithoutFeedback onPress={() => {
            let selectedIndex = lastCoordinate ? index - 1 : index

            let emptyCount = 0
            this.state.sortedData.map((series) => {
              if (series.data[selectedIndex].isEmpty) emptyCount++
            })
            if (emptyCount === this.state.sortedData.length) {
              return null
            }
            // console.log('point', selectedIndex, point)

            this.setState({
              selectedIndex: selectedIndex
            }, () => {
              if (typeof this.props.onPress === 'function') {
                this.props.onPress(selectedIndex)
              }
            })
          }}>
            <View style={{
              width: dx,
              height: '100%',
              position: 'absolute',
              marginLeft: -1 * dx / 2,
              backgroundColor: '#FFFFFF01'
            }} />
          </TouchableWithoutFeedback>
        )}

      </View>
    )
  }

  drawPoint (index, point, seriesColor) {
    let key = 'point' + index
    let size = 8
    let color = !seriesColor ? this.props.primaryColor : seriesColor
    if (this.state.selectedIndex === index) {
      color = this.props.selectedColor
    }

    if (point.isEmpty || this.props.hidePoints) return null

    return (
      <TouchableWithoutFeedback key={key} onPress={() => {
        this.setState({selectedIndex: index})
      }}>

        <View style={StyleSheet.flatten([styles.pointWrapper, {
          width: size,
          height: size,

          left: point.gap - size / 2,
          bottom: point.ratioY - size / 2,

          borderColor: color,
          backgroundColor: color

        }])} />
      </TouchableWithoutFeedback>
    )
  }
  drawValue (index, point) {
    let key = 'pointvalue' + index
    let size = 200
    return (

      <View key={key} style={{
        position: 'absolute',
        left: index === 0 ? point.gap : point.gap - size / 2,
        bottom: point.ratioY + 10,
        backgroundColor: 'transparent',
        width: index !== 0 ? 200 : undefined

      }} >
        {this.drawCustomValue(index, point)}

      </View>

    )
  }

  drawCustomValue (index, point) {
    if (this.props.customValueRenderer) {
      return this.props.customValueRenderer(index, point)
    } else {
      return null
    }
  }

  drawCoordinates (data, seriesColor, seriesIndex) {
    let result = []
    let lineStyle = {
      borderColor: !seriesColor ? this.props.primaryColor : seriesColor
    }
    let dataLength = data.length

    for (let i = 0; i < dataLength - 1; i++) {
      result.push(this.drawCoordinate(i, data[i], data[i + 1], '#FFFFFF00', lineStyle, false, false, seriesIndex))
    }

    if (dataLength > 0) {
      result.push(this.drawPoint(0, data[0], seriesColor))
      result.push(this.drawValue(0, data[0], seriesColor))
    }

    for (let i = 0; i < dataLength - 1; i++) {
      result.push(this.drawPoint((i + 1), data[i + 1], seriesColor))
      result.push(this.drawValue((i + 1), data[i + 1], seriesColor))
    }

    let lastData = Object.assign({}, data[dataLength - 1])
    let lastCoordinate = Object.assign({}, data[dataLength - 1])
    lastCoordinate.gap = lastCoordinate.gap + this.props.gap
    result.push(this.drawCoordinate((dataLength), lastData, lastCoordinate, '#FFFFFF', {}, true, true, seriesIndex))

    return result
  }

  getDistance (p1, p2) {
    return Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2))
  }

  drawSelected (index) {
    if (this.state.sortedData.length === 0) return null
    let data = this.state.sortedData[0].data
    let dataObject = data[index]
    if (typeof (this.state.selectedIndex) === 'number' && this.state.selectedIndex >= 0) {
      if (!dataObject) {
        return null
      }
      let reverse = true
      let bottom = dataObject.ratioY

      let left = dataObject.gap
      let gap = 0
      if (index === data.length - 1 && index !== 0) {
        left = data[index - 1].gap
        gap = dataObject.gap - left
      }
      if (bottom > this.props.height * 2 / 3) {
        reverse = false
      }

      return (
        <View style={StyleSheet.flatten([styles.selectedWrapper, {
          left: left,
          justifyContent: 'center'
        }])}>
          <View style={StyleSheet.flatten([styles.selectedLine, {
            backgroundColor: this.props.selectedColor,
            marginLeft: gap
          }])} />

          <View style={StyleSheet.flatten([styles.selectedBox])}>
            {this.state.sortedData.map((series) => {
              let dataObject = series.data[this.state.selectedIndex]
              return (
                <View key={series.seriesName}>
                  {dataObject.x ? (
                    <Text style={styles.tooltipTitle}>{dataObject.x}</Text>
                ) : null}
                  <View style={{flexDirection: 'row', paddingLeft: 5, alignItems: 'center'}}>
                    <View style={{
                      width: 10,
                      height: 5,
                      marginRight: 3,
                      borderRadius: 2,
                      backgroundColor: !series.seriesColor ? this.props.primaryColor : series.seriesColor
                    }} />
                    <Text style={styles.tooltipValue}>{numberWithCommas(dataObject.y, false)}</Text>
                  </View>
                </View>
              )
            })}

          </View>

        </View>
      )
    } else {
      return null
    }
  }

  render () {
    let {fadeAnim} = this.state
    return (
      this.state.sortedData.length > 0 ? (
        <View style={StyleSheet.flatten([styles.wrapper, {
          backgroundColor: this.props.backgroundColor
        }])}>
          <View style={styles.yAxisLabelsWrapper}>
            {drawYAxisLabels(this.state.guideArray, this.props.height + 20, this.props.minValue, this.props.labelColor)}

          </View>

          <View>
            <ScrollView horizontal>
              <View>

                <View ref='chartView' style={styles.chartViewWrapper}>

                  {drawYAxis(this.props.yAxisColor)}
                  {drawGuideLine(this.state.guideArray, this.props.yAxisGridLineColor)}
                  {this.state.sortedData.map((obj, index) => {
                    return (
                      <Animated.View key={'animated_' + index} style={{
                        transform: [{scaleY: fadeAnim}],
                        flexDirection: 'row',
                        alignItems: 'flex-end',
                        height: '100%',
                        position: index === 0 ? 'relative' : 'absolute',
                        minWidth: 200,
                        marginBottom: this.props.minValue && this.state.guideArray && this.state.guideArray.length > 0 ? -1 * this.state.guideArray[0][2] * this.props.minValue : null
                      }} >
                        {this.drawCoordinates(obj.data, obj.seriesColor, index)}
                      </Animated.View>
                    )
                  })}
                  {this.drawSelected(this.state.selectedIndex)}

                </View>

                {drawXAxis(this.props.xAxisColor)}
                {drawXAxisLabels(this.state.sortedData[0].data, this.props.gap, this.props.labelColor, this.props.showEvenNumberXaxisLabel)}
              </View>

            </ScrollView>
          </View>

        </View>
      ) : null

    )
  }
}

LineChart.defaultProps = {
  data: [],
  primaryColor: '#297AB1',
  selectedColor: '#FF0000',
  height: 100,
  gap: 60,
  showEvenNumberXaxisLabel: true,
  onPointClick: (point) => {

  },
  numberOfYAxisGuideLine: 5
}

const styles = StyleSheet.create({
  wrapper: {
    flexDirection: 'row',
    overflow: 'hidden'
  },
  yAxisLabelsWrapper: {
    paddingRight: 5
  },
  chartViewWrapper: {
    flexDirection: 'row',
    alignItems: 'flex-end',
    margin: 0,
    paddingRight: 0,
    overflow: 'hidden'
  },
  coordinateWrapper: {
    overflow: 'hidden',
    justifyContent: 'flex-start',
    alignContent: 'flex-start'
  },
  lineBox: {
    overflow: 'hidden',
    justifyContent: 'flex-start'
  },
  guideLine: {
    position: 'absolute',
    height: '100%',
    borderRightColor: '#e0e0e050',
    borderRightWidth: 1
  },
  absolute: {
    position: 'absolute',
    width: '100%'
  },
  pointWrapper: {
    position: 'absolute',
    borderRadius: 10,
    borderWidth: 1
  },
  selectedWrapper: {
    position: 'absolute',
    height: '100%',
    alignItems: 'flex-start'
  },
  selectedLine: {
    position: 'absolute',
    width: 1,
    height: '100%'
  },
  selectedBox: {
    backgroundColor: '#FFFFFF',
    borderRadius: 5,
    opacity: 0.8,
    borderColor: '#AAAAAA',
    borderWidth: 1,
    position: 'absolute',
    padding: 3,
    marginLeft: 5,
    justifyContent: 'center'
  },
  tooltipTitle: {fontSize: 10},
  tooltipValue: {fontWeight: 'bold', fontSize: 15}
})

export default LineChart
<commit_msg>Add a new prop to enable scroll to end of a line chart. This is helpful in case of a long line chart and the user may eb interested in seeing the latest data.<commit_after>import React from 'react'
import { View, TouchableWithoutFeedback, Text, Animated, Easing, ScrollView, StyleSheet } from 'react-native'
import {initData, drawYAxis, drawGuideLine, drawYAxisLabels, numberWithCommas, drawXAxis, drawXAxisLabels} from '../common'

class LineChart extends React.Component {
  constructor (props) {
    super(props)
    let newState = initData(this.props.data, this.props.height, this.props.gap, this.props.numberOfYAxisGuideLine)
    this.state = {
      loading: false,
      sortedData: newState.sortedData,
      selectedIndex: null,
      nowHeight: 200,
      nowWidth: 200,
      scrollPosition: 0,
      nowX: 0,
      nowY: 0,
      max: newState.max,
      fadeAnim: new Animated.Value(0),
      guideArray: newState.guideArray
    }

    this.drawCoordinates = this.drawCoordinates.bind(this)
    this.drawCoordinate = this.drawCoordinate.bind(this)
    this.drawSelected = this.drawSelected.bind(this)
  }

  shouldComponentUpdate (nextProps, nextState) {
    if (nextState.sortedData !== this.state.sortedData ||
      nextState.selectedIndex !== this.state.selectedIndex ||
      nextState.scrollPosition !== this.state.scrollPosition) {
      return true
    } else {
      return false
    }
  }

  componentDidMount () {
    Animated.timing(this.state.fadeAnim, { toValue: 1, easing: Easing.bounce, duration: 1000, useNativeDriver: true }).start()
  }

  componentWillReceiveProps (nextProps) {
    if (nextProps.data !== this.props.data) {
      this.setState(Object.assign({
        fadeAnim: new Animated.Value(0)
      }, initData(nextProps.data, this.props.height, this.props.gap, this.props.numberOfYAxisGuideLine)), () => {
        Animated.timing(this.state.fadeAnim, { toValue: 1, easing: Easing.bounce, duration: 1000, useNativeDriver: true }).start()
      })
    }
  }

  getTransform (rad, width) {
    let x = (0 - width / 2) * Math.cos(rad) - (0 - width / 2) * Math.sin(rad)
    let y = (0 - width / 2) * Math.sin(rad) + (0 - width / 2) * Math.cos(rad)

    return [ {translateX: (-1 * x) - width / 2}, {translateY: (-1 * y) + width / 2}, { rotate: rad + 'rad' } ]
  }

  drawCoordinate (index, start, end, backgroundColor, lineStyle, isBlank, lastCoordinate, seriesIndex) {
    let key = 'line' + index
    let dx = end.gap - start.gap
    let dy = end.ratioY - start.ratioY
    let size = Math.sqrt(dx * dx + dy * dy)
    let angleRad = -1 * Math.atan2(dy, dx)
    let height
    let top
    let topMargin = 20

    if (start.ratioY > end.ratioY) {
      height = start.ratioY
      top = -1 * size
    } else {
      height = end.ratioY
      top = -1 * (size - Math.abs(dy))
    }

    return (
      <View key={key} style={{
        height: this.props.height + topMargin,
        justifyContent: 'flex-end'
      }}>

        <View style={StyleSheet.flatten([{
          width: dx,
          height: height,
          marginTop: topMargin
        }, styles.coordinateWrapper])}>
          <View style={StyleSheet.flatten([{
            top: top,
            width: size,
            height: size,
            borderColor: isBlank ? backgroundColor : this.props.primaryColor,
            borderTopWidth: 1,
            transform: this.getTransform(angleRad, size)
          }, styles.lineBox, lineStyle])} />
          <View style={StyleSheet.flatten([styles.absolute, {
            height: height - Math.abs(dy) - 2,
            backgroundColor: lastCoordinate ? '#FFFFFF00' : backgroundColor,
            marginTop: Math.abs(dy) + 2
          }])} />
        </View>
        {!lastCoordinate && seriesIndex === 0 ? (
          <View style={StyleSheet.flatten([styles.guideLine, {
            width: dx,
            borderRightColor: this.props.xAxisGridLineColor
          }])} />
        ) : null}
        {seriesIndex === this.state.sortedData.length - 1 && (
          <TouchableWithoutFeedback onPress={() => {
            let selectedIndex = lastCoordinate ? index - 1 : index

            let emptyCount = 0
            this.state.sortedData.map((series) => {
              if (series.data[selectedIndex].isEmpty) emptyCount++
            })
            if (emptyCount === this.state.sortedData.length) {
              return null
            }
            // console.log('point', selectedIndex, point)

            this.setState({
              selectedIndex: selectedIndex
            }, () => {
              if (typeof this.props.onPress === 'function') {
                this.props.onPress(selectedIndex)
              }
            })
          }}>
            <View style={{
              width: dx,
              height: '100%',
              position: 'absolute',
              marginLeft: -1 * dx / 2,
              backgroundColor: '#FFFFFF01'
            }} />
          </TouchableWithoutFeedback>
        )}

      </View>
    )
  }

  drawPoint (index, point, seriesColor) {
    let key = 'point' + index
    let size = 8
    let color = !seriesColor ? this.props.primaryColor : seriesColor
    if (this.state.selectedIndex === index) {
      color = this.props.selectedColor
    }

    if (point.isEmpty || this.props.hidePoints) return null

    return (
      <TouchableWithoutFeedback key={key} onPress={() => {
        this.setState({selectedIndex: index})
      }}>

        <View style={StyleSheet.flatten([styles.pointWrapper, {
          width: size,
          height: size,

          left: point.gap - size / 2,
          bottom: point.ratioY - size / 2,

          borderColor: color,
          backgroundColor: color

        }])} />
      </TouchableWithoutFeedback>
    )
  }
  drawValue (index, point) {
    let key = 'pointvalue' + index
    let size = 200
    return (

      <View key={key} style={{
        position: 'absolute',
        left: index === 0 ? point.gap : point.gap - size / 2,
        bottom: point.ratioY + 10,
        backgroundColor: 'transparent',
        width: index !== 0 ? 200 : undefined

      }} >
        {this.drawCustomValue(index, point)}

      </View>

    )
  }

  drawCustomValue (index, point) {
    if (this.props.customValueRenderer) {
      return this.props.customValueRenderer(index, point)
    } else {
      return null
    }
  }

  drawCoordinates (data, seriesColor, seriesIndex) {
    let result = []
    let lineStyle = {
      borderColor: !seriesColor ? this.props.primaryColor : seriesColor
    }
    let dataLength = data.length

    for (let i = 0; i < dataLength - 1; i++) {
      result.push(this.drawCoordinate(i, data[i], data[i + 1], '#FFFFFF00', lineStyle, false, false, seriesIndex))
    }

    if (dataLength > 0) {
      result.push(this.drawPoint(0, data[0], seriesColor))
      result.push(this.drawValue(0, data[0], seriesColor))
    }

    for (let i = 0; i < dataLength - 1; i++) {
      result.push(this.drawPoint((i + 1), data[i + 1], seriesColor))
      result.push(this.drawValue((i + 1), data[i + 1], seriesColor))
    }

    let lastData = Object.assign({}, data[dataLength - 1])
    let lastCoordinate = Object.assign({}, data[dataLength - 1])
    lastCoordinate.gap = lastCoordinate.gap + this.props.gap
    result.push(this.drawCoordinate((dataLength), lastData, lastCoordinate, '#FFFFFF', {}, true, true, seriesIndex))

    return result
  }

  getDistance (p1, p2) {
    return Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2))
  }

  drawSelected (index) {
    if (this.state.sortedData.length === 0) return null
    let data = this.state.sortedData[0].data
    let dataObject = data[index]
    if (typeof (this.state.selectedIndex) === 'number' && this.state.selectedIndex >= 0) {
      if (!dataObject) {
        return null
      }
      let reverse = true
      let bottom = dataObject.ratioY

      let left = dataObject.gap
      let gap = 0
      if (index === data.length - 1 && index !== 0) {
        left = data[index - 1].gap
        gap = dataObject.gap - left
      }
      if (bottom > this.props.height * 2 / 3) {
        reverse = false
      }

      return (
        <View style={StyleSheet.flatten([styles.selectedWrapper, {
          left: left,
          justifyContent: 'center'
        }])}>
          <View style={StyleSheet.flatten([styles.selectedLine, {
            backgroundColor: this.props.selectedColor,
            marginLeft: gap
          }])} />

          <View style={StyleSheet.flatten([styles.selectedBox])}>
            {this.state.sortedData.map((series) => {
              let dataObject = series.data[this.state.selectedIndex]
              return (
                <View key={series.seriesName}>
                  {dataObject.x ? (
                    <Text style={styles.tooltipTitle}>{dataObject.x}</Text>
                ) : null}
                  <View style={{flexDirection: 'row', paddingLeft: 5, alignItems: 'center'}}>
                    <View style={{
                      width: 10,
                      height: 5,
                      marginRight: 3,
                      borderRadius: 2,
                      backgroundColor: !series.seriesColor ? this.props.primaryColor : series.seriesColor
                    }} />
                    <Text style={styles.tooltipValue}>{numberWithCommas(dataObject.y, false)}</Text>
                  </View>
                </View>
              )
            })}

          </View>

        </View>
      )
    } else {
      return null
    }
  }

  render () {
    let {fadeAnim} = this.state
    return (
      this.state.sortedData.length > 0 ? (
        <View style={StyleSheet.flatten([styles.wrapper, {
          backgroundColor: this.props.backgroundColor
        }])}>
          <View style={styles.yAxisLabelsWrapper}>
            {drawYAxisLabels(this.state.guideArray, this.props.height + 20, this.props.minValue, this.props.labelColor)}

          </View>

          <View>
          <ScrollView
              horizontal
              ref={ref => this.scrollView = ref}
              onContentSizeChange={() => {
                if(this.props.lineChartScrollToEnd) this.scrollView.scrollToEnd({ animated: false });
              }}
          >
              <View>

                <View ref='chartView' style={styles.chartViewWrapper}>

                  {drawYAxis(this.props.yAxisColor)}
                  {drawGuideLine(this.state.guideArray, this.props.yAxisGridLineColor)}
                  {this.state.sortedData.map((obj, index) => {
                    return (
                      <Animated.View key={'animated_' + index} style={{
                        transform: [{scaleY: fadeAnim}],
                        flexDirection: 'row',
                        alignItems: 'flex-end',
                        height: '100%',
                        position: index === 0 ? 'relative' : 'absolute',
                        minWidth: 200,
                        marginBottom: this.props.minValue && this.state.guideArray && this.state.guideArray.length > 0 ? -1 * this.state.guideArray[0][2] * this.props.minValue : null
                      }} >
                        {this.drawCoordinates(obj.data, obj.seriesColor, index)}
                      </Animated.View>
                    )
                  })}
                  {this.drawSelected(this.state.selectedIndex)}

                </View>

                {drawXAxis(this.props.xAxisColor)}
                {drawXAxisLabels(this.state.sortedData[0].data, this.props.gap, this.props.labelColor, this.props.showEvenNumberXaxisLabel)}
              </View>

            </ScrollView>
          </View>

        </View>
      ) : null

    )
  }
}

LineChart.defaultProps = {
  data: [],
  primaryColor: '#297AB1',
  selectedColor: '#FF0000',
  height: 100,
  gap: 60,
  showEvenNumberXaxisLabel: true,
  onPointClick: (point) => {

  },
  numberOfYAxisGuideLine: 5
}

const styles = StyleSheet.create({
  wrapper: {
    flexDirection: 'row',
    overflow: 'hidden'
  },
  yAxisLabelsWrapper: {
    paddingRight: 5
  },
  chartViewWrapper: {
    flexDirection: 'row',
    alignItems: 'flex-end',
    margin: 0,
    paddingRight: 0,
    overflow: 'hidden'
  },
  coordinateWrapper: {
    overflow: 'hidden',
    justifyContent: 'flex-start',
    alignContent: 'flex-start'
  },
  lineBox: {
    overflow: 'hidden',
    justifyContent: 'flex-start'
  },
  guideLine: {
    position: 'absolute',
    height: '100%',
    borderRightColor: '#e0e0e050',
    borderRightWidth: 1
  },
  absolute: {
    position: 'absolute',
    width: '100%'
  },
  pointWrapper: {
    position: 'absolute',
    borderRadius: 10,
    borderWidth: 1
  },
  selectedWrapper: {
    position: 'absolute',
    height: '100%',
    alignItems: 'flex-start'
  },
  selectedLine: {
    position: 'absolute',
    width: 1,
    height: '100%'
  },
  selectedBox: {
    backgroundColor: '#FFFFFF',
    borderRadius: 5,
    opacity: 0.8,
    borderColor: '#AAAAAA',
    borderWidth: 1,
    position: 'absolute',
    padding: 3,
    marginLeft: 5,
    justifyContent: 'center'
  },
  tooltipTitle: {fontSize: 10},
  tooltipValue: {fontWeight: 'bold', fontSize: 15}
})

export default LineChart
<|endoftext|>


<commit_before>import axios from "axios";
import React from "react";

import Resolver from "../../../src";

class Stargazers extends React.Component {
  render() {
    return (

            Stargazers

              These are all of the cool people who've starred this project!

        {this.renderUsers(this.props.users, 4)}

    );
  }

  renderGroup(cols, group, i) {
    const size = `s${12 / cols}`;

    return (
      <div key={`group-${i}`} className="row">
        {group.map(user => (
          <div className={`col ${size}`}>
            {this.renderUser(user)}

        ))}

    );
  }

  renderUser(user) {
    return (

          {user.login}

    );
  }

  renderUsers(users, cols) {
    const groups = [];

    while (users.length) {
      groups.push(users.splice(0, cols));
    }

    return groups.map(this.renderGroup.bind(this, cols));
  }
}

Stargazers.propTypes = {
  users: React.PropTypes.array.isRequired,
};

export default Resolver.createContainer(Stargazers, {
  resolve: {
    users: function(props) {
      const url = `https://api.github.com/repos/${props.user}/${props.repo}/stargazers`;

      return axios.get(url).then(response => response.data);
    },
  },
});
<commit_msg>Add name to Stargazers<commit_after>import axios from "axios";
import React from "react";

import Resolver from "../../../src";

class Stargazers extends React.Component {
  render() {
    return (

            Stargazers

              These are all of the cool people who've starred this project!

        {this.renderUsers(this.props.users, 4)}

    );
  }

  renderGroup(cols, group, i) {
    const size = `s${12 / cols}`;

    return (
      <div key={`group-${i}`} className="row">
        {group.map(user => (
          <div className={`col ${size}`}>
            {this.renderUser(user)}

        ))}

    );
  }

  renderUser(user) {
    return (

          {user.login}

    );
  }

  renderUsers(users, cols) {
    const groups = [];

    while (users.length) {
      groups.push(users.splice(0, cols));
    }

    return groups.map(this.renderGroup.bind(this, cols));
  }
}

Stargazers.displayName = "Stargazers";

Stargazers.propTypes = {
  users: React.PropTypes.array.isRequired,
};

export default Resolver.createContainer(Stargazers, {
  resolve: {
    users: function(props) {
      const url = `https://api.github.com/repos/${props.user}/${props.repo}/stargazers`;

      return axios.get(url).then(response => response.data);
    },
  },
});
<|endoftext|>


<commit_before><commit_msg>Set desired timeouts on all hoc2015 levels<commit_after><|endoftext|>


<commit_before><commit_msg>Change starwars to play music as soon as audio is unlocked, after the instructions show.<commit_after><|endoftext|>


<commit_before><commit_msg>param validate itemClass on addItem,setItemActivity,setItemSpeed<commit_after><|endoftext|>


<commit_before>/*!
 * numeral.js
 * version : 1.5.3
 * author : Adam Draper
 * license : MIT
 * http://adamwdraper.github.com/Numeral-js/
 */

define(["underscore"], function(_) {

    var languages = {};
    var defaultFormat = '0,0';
    var defaultLanguage = 'en';

    /**
     * Implementation of toFixed() that treats floats more like decimals
     *
     * Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present
     * problems for accounting- and finance-related software.
     */
    function toFixed(value, precision, roundingFunction, optionals) {
        var power = Math.pow(10, precision),
            optionalsRegExp,
            output;

        // roundingFunction = (roundingFunction !== undefined ? roundingFunction : Math.round);
        // Multiply up by precision, round accurately, then divide and use native toFixed():
        output = (roundingFunction(value * power) / power).toFixed(precision);

        if (optionals) {
            optionalsRegExp = new RegExp('0{1,' + optionals + '}$');
            output = output.replace(optionalsRegExp, '');
        }

        return output;
    }

    // determine what type of formatting we need to do
    function formatNumeral(value, format, language, roundingFunction) {
        var output;

        // figure out what kind of format we are dealing with
        if (format.indexOf('$') > -1) { // currency!!!!!
            output = formatCurrency(value, format, language, roundingFunction);
        } else if (format.indexOf('%') > -1) { // percentage
            output = formatPercentage(value, format, language, roundingFunction);
        } else if (format.indexOf(':') > -1) { // time
            output = formatTime(value, format, language);
        } else { // plain ol' numbers or bytes
            output = formatNumber(value, format, language, roundingFunction);
        }

        return output;
    }

    function formatCurrency(value, format, language, roundingFunction) {
        var symbolIndex = format.indexOf('$'),
            openParenIndex = format.indexOf('('),
            minusSignIndex = format.indexOf('-'),
            space = '',
            spliceIndex,
            output;

        // check for space before or after currency
        if (format.indexOf(' $') > -1) {
            space = ' ';
            format = format.replace(' $', '');
        } else if (format.indexOf('$ ') > -1) {
            space = ' ';
            format = format.replace('$ ', '');
        } else {
            format = format.replace('$', '');
        }

        // format the number
        output = formatNumber(value, format, language, roundingFunction);

        // position the symbol
        if (symbolIndex <= 1) {
            if (output.indexOf('(') > -1 || output.indexOf('-') > -1) {
                output = output.split('');
                spliceIndex = 1;
                if (symbolIndex < openParenIndex || symbolIndex < minusSignIndex){
                    // the symbol appears before the "(" or "-"
                    spliceIndex = 0;
                }
                output.splice(spliceIndex, 0, language.currency.symbol + space);
                output = output.join('');
            } else {
                output = language.currency.symbol + space + output;
            }
        } else {
            if (output.indexOf(')') > -1) {
                output = output.split('');
                output.splice(-1, 0, space + language.currency.symbol);
                output = output.join('');
            } else {
                output = output + space + language.currency.symbol;
            }
        }

        return output;
    }

    function formatPercentage(value, format, language, roundingFunction) {
        var space = '',
            output,
            value = value * 100;

        // check for space before %
        if (format.indexOf(' %') > -1) {
            space = ' ';
            format = format.replace(' %', '');
        } else {
            format = format.replace('%', '');
        }

        output = formatNumber(value, format, language, roundingFunction);

        if (output.indexOf(')') > -1 ) {
            output = output.split('');
            output.splice(-1, 0, space + '%');
            output = output.join('');
        } else {
            output = output + space + '%';
        }

        return output;
    }

    function formatTime(value, language) {
        var hours = Math.floor(value/60/60),
            minutes = Math.floor((value - (hours * 60 * 60))/60),
            seconds = Math.round(value - (hours * 60 * 60) - (minutes * 60));
        return hours + ':' + ((minutes < 10) ? '0' + minutes : minutes) + ':' + ((seconds < 10) ? '0' + seconds : seconds);
    }

    function formatNumber(value, format, language, roundingFunction) {
        var negP = false,
            signed = false,
            optDec = false,
            abbr = '',
            abbrK = false, // force abbreviation to thousands
            abbrM = false, // force abbreviation to millions
            abbrB = false, // force abbreviation to billions
            abbrT = false, // force abbreviation to trillions
            abbrForce = false, // force abbreviation
            bytes = '',
            ord = '',
            abs = Math.abs(value),
            suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
            min,
            max,
            power,
            w,
            precision,
            thousands,
            d = '',
            neg = false;

        // see if we should use parentheses for negative number or if we should prefix with a sign
        // if both are present we default to parentheses
        if (format.indexOf('(') > -1) {
            negP = true;
            format = format.slice(1, -1);
        } else if (format.indexOf('+') > -1) {
            signed = true;
            format = format.replace(/\+/g, '');
        }

        // see if abbreviation is wanted
        if (format.indexOf('a') > -1) {
            // check if abbreviation is specified
            abbrK = format.indexOf('aK') >= 0;
            abbrM = format.indexOf('aM') >= 0;
            abbrB = format.indexOf('aB') >= 0;
            abbrT = format.indexOf('aT') >= 0;
            abbrForce = abbrK || abbrM || abbrB || abbrT;

            // check for space before abbreviation
            if (format.indexOf(' a') > -1) {
                abbr = ' ';
                format = format.replace(' a', '');
            } else {
                format = format.replace('a', '');
            }

            if (abs >= Math.pow(10, 12) && !abbrForce || abbrT) {
                // trillion
                abbr = abbr + language.abbreviations.trillion;
                value = value / Math.pow(10, 12);
            } else if (abs < Math.pow(10, 12) && abs >= Math.pow(10, 9) && !abbrForce || abbrB) {
                // billion
                abbr = abbr + language.abbreviations.billion;
                value = value / Math.pow(10, 9);
            } else if (abs < Math.pow(10, 9) && abs >= Math.pow(10, 6) && !abbrForce || abbrM) {
                // million
                abbr = abbr + language.abbreviations.million;
                value = value / Math.pow(10, 6);
            } else if (abs < Math.pow(10, 6) && abs >= Math.pow(10, 3) && !abbrForce || abbrK) {
                // thousand
                abbr = abbr + language.abbreviations.thousand;
                value = value / Math.pow(10, 3);
            }
        }

        // see if we are formatting bytes
        if (format.indexOf('b') > -1) {
            // check for space before
            if (format.indexOf(' b') > -1) {
                bytes = ' ';
                format = format.replace(' b', '');
            } else {
                format = format.replace('b', '');
            }

            for (power = 0; power <= suffixes.length; power++) {
                min = Math.pow(1024, power);
                max = Math.pow(1024, power+1);

                if (value >= min && value < max) {
                    bytes = bytes + suffixes[power];
                    if (min > 0) {
                        value = value / min;
                    }
                    break;
                }
            }
        }

        // see if ordinal is wanted
        if (format.indexOf('o') > -1) {
            // check for space before
            if (format.indexOf(' o') > -1) {
                ord = ' ';
                format = format.replace(' o', '');
            } else {
                format = format.replace('o', '');
            }

            ord = ord + language.ordinal(value);
        }

        if (format.indexOf('[.]') > -1) {
            optDec = true;
            format = format.replace('[.]', '.');
        }

        w = value.toString().split('.')[0];
        precision = format.split('.')[1];
        thousands = format.indexOf(',');

        if (precision) {
            if (precision.indexOf('[') > -1) {
                precision = precision.replace(']', '');
                precision = precision.split('[');
                d = toFixed(value, (precision[0].length + precision[1].length), roundingFunction, precision[1].length);
            } else {
                d = toFixed(value, precision.length, roundingFunction);
            }

            w = d.split('.')[0];

            if (d.split('.')[1].length) {
                d = language.delimiters.decimal + d.split('.')[1];
            } else {
                d = '';
            }

            if (optDec && Number(d.slice(1)) === 0) {
                d = '';
            }
        } else {
            w = toFixed(value, null, roundingFunction);
        }

        // format number
        if (w.indexOf('-') > -1) {
            w = w.slice(1);
            neg = true;
        }

        if (thousands > -1) {
            w = w.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + language.delimiters.thousands);
        }

        if (format.indexOf('.') === 0) {
            w = '';
        }

        return
            ((negP && neg) ? '(' : '') +
            ((!negP && neg) ? '-' : '') +
            ((!neg && signed) ? '+' : '') +
            w +
            d +
            ((ord) ? ord : '') +
            ((abbr) ? abbr : '') +
            ((bytes) ? bytes : '') +
            ((negP && neg) ? ')' : '');
    }

    function addLanguage(key, spec) {
        languages[key] = spec;
    }

    addLanguage('en', {
        delimiters: {
            thousands: ',',
            decimal:   '.'
        },
        abbreviations: {
            thousand: 'k',
            million:  'm',
            billion:  'b',
            trillion: 't'
        },
        ordinal: function (number) {
            var b = number % 10;
            return (~~ (number % 100 / 10) === 1) ? 'th' :
                (b === 1) ? 'st' :
                (b === 2) ? 'nd' :
                (b === 3) ? 'rd' : 'th';
        },
        currency: {
            symbol: '$'
        }
    });

    function format(input, formatString, language, roundingFunction) {
        return formatNumeral(
            Number(input),
            _.isString(formatString)        ? formatString        : defaultFormat,
            _.isString(language)            ? languages[language] : languages[defaultLanguage],
            _.isUndefined(roundingFunction) ? Math.round          : roundingFunction);
    }

    return {"format": format};
});
<commit_msg>Deal with JS' semicolon inference<commit_after>/*!
 * numeral.js
 * version : 1.5.3
 * author : Adam Draper
 * license : MIT
 * http://adamwdraper.github.com/Numeral-js/
 */

define(["underscore"], function(_) {

    var languages = {};
    var defaultFormat = '0,0';
    var defaultLanguage = 'en';

    /**
     * Implementation of toFixed() that treats floats more like decimals
     *
     * Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present
     * problems for accounting- and finance-related software.
     */
    function toFixed(value, precision, roundingFunction, optionals) {
        var power = Math.pow(10, precision),
            optionalsRegExp,
            output;

        // roundingFunction = (roundingFunction !== undefined ? roundingFunction : Math.round);
        // Multiply up by precision, round accurately, then divide and use native toFixed():
        output = (roundingFunction(value * power) / power).toFixed(precision);

        if (optionals) {
            optionalsRegExp = new RegExp('0{1,' + optionals + '}$');
            output = output.replace(optionalsRegExp, '');
        }

        return output;
    }

    // determine what type of formatting we need to do
    function formatNumeral(value, format, language, roundingFunction) {
        var output;

        // figure out what kind of format we are dealing with
        if (format.indexOf('$') > -1) { // currency!!!!!
            output = formatCurrency(value, format, language, roundingFunction);
        } else if (format.indexOf('%') > -1) { // percentage
            output = formatPercentage(value, format, language, roundingFunction);
        } else if (format.indexOf(':') > -1) { // time
            output = formatTime(value, format, language);
        } else { // plain ol' numbers or bytes
            output = formatNumber(value, format, language, roundingFunction);
        }

        return output;
    }

    function formatCurrency(value, format, language, roundingFunction) {
        var symbolIndex = format.indexOf('$'),
            openParenIndex = format.indexOf('('),
            minusSignIndex = format.indexOf('-'),
            space = '',
            spliceIndex,
            output;

        // check for space before or after currency
        if (format.indexOf(' $') > -1) {
            space = ' ';
            format = format.replace(' $', '');
        } else if (format.indexOf('$ ') > -1) {
            space = ' ';
            format = format.replace('$ ', '');
        } else {
            format = format.replace('$', '');
        }

        // format the number
        output = formatNumber(value, format, language, roundingFunction);

        // position the symbol
        if (symbolIndex <= 1) {
            if (output.indexOf('(') > -1 || output.indexOf('-') > -1) {
                output = output.split('');
                spliceIndex = 1;
                if (symbolIndex < openParenIndex || symbolIndex < minusSignIndex){
                    // the symbol appears before the "(" or "-"
                    spliceIndex = 0;
                }
                output.splice(spliceIndex, 0, language.currency.symbol + space);
                output = output.join('');
            } else {
                output = language.currency.symbol + space + output;
            }
        } else {
            if (output.indexOf(')') > -1) {
                output = output.split('');
                output.splice(-1, 0, space + language.currency.symbol);
                output = output.join('');
            } else {
                output = output + space + language.currency.symbol;
            }
        }

        return output;
    }

    function formatPercentage(value, format, language, roundingFunction) {
        var space = '',
            output,
            value = value * 100;

        // check for space before %
        if (format.indexOf(' %') > -1) {
            space = ' ';
            format = format.replace(' %', '');
        } else {
            format = format.replace('%', '');
        }

        output = formatNumber(value, format, language, roundingFunction);

        if (output.indexOf(')') > -1 ) {
            output = output.split('');
            output.splice(-1, 0, space + '%');
            output = output.join('');
        } else {
            output = output + space + '%';
        }

        return output;
    }

    function formatTime(value, language) {
        var hours = Math.floor(value/60/60),
            minutes = Math.floor((value - (hours * 60 * 60))/60),
            seconds = Math.round(value - (hours * 60 * 60) - (minutes * 60));
        return hours + ':' + ((minutes < 10) ? '0' + minutes : minutes) + ':' + ((seconds < 10) ? '0' + seconds : seconds);
    }

    function formatNumber(value, format, language, roundingFunction) {
        var negP = false,
            signed = false,
            optDec = false,
            abbr = '',
            abbrK = false, // force abbreviation to thousands
            abbrM = false, // force abbreviation to millions
            abbrB = false, // force abbreviation to billions
            abbrT = false, // force abbreviation to trillions
            abbrForce = false, // force abbreviation
            bytes = '',
            ord = '',
            abs = Math.abs(value),
            suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
            min,
            max,
            power,
            w,
            precision,
            thousands,
            d = '',
            neg = false;

        // see if we should use parentheses for negative number or if we should prefix with a sign
        // if both are present we default to parentheses
        if (format.indexOf('(') > -1) {
            negP = true;
            format = format.slice(1, -1);
        } else if (format.indexOf('+') > -1) {
            signed = true;
            format = format.replace(/\+/g, '');
        }

        // see if abbreviation is wanted
        if (format.indexOf('a') > -1) {
            // check if abbreviation is specified
            abbrK = format.indexOf('aK') >= 0;
            abbrM = format.indexOf('aM') >= 0;
            abbrB = format.indexOf('aB') >= 0;
            abbrT = format.indexOf('aT') >= 0;
            abbrForce = abbrK || abbrM || abbrB || abbrT;

            // check for space before abbreviation
            if (format.indexOf(' a') > -1) {
                abbr = ' ';
                format = format.replace(' a', '');
            } else {
                format = format.replace('a', '');
            }

            if (abs >= Math.pow(10, 12) && !abbrForce || abbrT) {
                // trillion
                abbr = abbr + language.abbreviations.trillion;
                value = value / Math.pow(10, 12);
            } else if (abs < Math.pow(10, 12) && abs >= Math.pow(10, 9) && !abbrForce || abbrB) {
                // billion
                abbr = abbr + language.abbreviations.billion;
                value = value / Math.pow(10, 9);
            } else if (abs < Math.pow(10, 9) && abs >= Math.pow(10, 6) && !abbrForce || abbrM) {
                // million
                abbr = abbr + language.abbreviations.million;
                value = value / Math.pow(10, 6);
            } else if (abs < Math.pow(10, 6) && abs >= Math.pow(10, 3) && !abbrForce || abbrK) {
                // thousand
                abbr = abbr + language.abbreviations.thousand;
                value = value / Math.pow(10, 3);
            }
        }

        // see if we are formatting bytes
        if (format.indexOf('b') > -1) {
            // check for space before
            if (format.indexOf(' b') > -1) {
                bytes = ' ';
                format = format.replace(' b', '');
            } else {
                format = format.replace('b', '');
            }

            for (power = 0; power <= suffixes.length; power++) {
                min = Math.pow(1024, power);
                max = Math.pow(1024, power+1);

                if (value >= min && value < max) {
                    bytes = bytes + suffixes[power];
                    if (min > 0) {
                        value = value / min;
                    }
                    break;
                }
            }
        }

        // see if ordinal is wanted
        if (format.indexOf('o') > -1) {
            // check for space before
            if (format.indexOf(' o') > -1) {
                ord = ' ';
                format = format.replace(' o', '');
            } else {
                format = format.replace('o', '');
            }

            ord = ord + language.ordinal(value);
        }

        if (format.indexOf('[.]') > -1) {
            optDec = true;
            format = format.replace('[.]', '.');
        }

        w = value.toString().split('.')[0];
        precision = format.split('.')[1];
        thousands = format.indexOf(',');

        if (precision) {
            if (precision.indexOf('[') > -1) {
                precision = precision.replace(']', '');
                precision = precision.split('[');
                d = toFixed(value, (precision[0].length + precision[1].length), roundingFunction, precision[1].length);
            } else {
                d = toFixed(value, precision.length, roundingFunction);
            }

            w = d.split('.')[0];

            if (d.split('.')[1].length) {
                d = language.delimiters.decimal + d.split('.')[1];
            } else {
                d = '';
            }

            if (optDec && Number(d.slice(1)) === 0) {
                d = '';
            }
        } else {
            w = toFixed(value, null, roundingFunction);
        }

        // format number
        if (w.indexOf('-') > -1) {
            w = w.slice(1);
            neg = true;
        }

        if (thousands > -1) {
            w = w.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + language.delimiters.thousands);
        }

        if (format.indexOf('.') === 0) {
            w = '';
        }

        return ((negP && neg) ? '(' : '') +
               ((!negP && neg) ? '-' : '') +
               ((!neg && signed) ? '+' : '') +
               w +
               d +
               ((ord) ? ord : '') +
               ((abbr) ? abbr : '') +
               ((bytes) ? bytes : '') +
               ((negP && neg) ? ')' : '');
    }

    function addLanguage(key, spec) {
        languages[key] = spec;
    }

    addLanguage('en', {
        delimiters: {
            thousands: ',',
            decimal:   '.'
        },
        abbreviations: {
            thousand: 'k',
            million:  'm',
            billion:  'b',
            trillion: 't'
        },
        ordinal: function (number) {
            var b = number % 10;
            return (~~ (number % 100 / 10) === 1) ? 'th' :
                (b === 1) ? 'st' :
                (b === 2) ? 'nd' :
                (b === 3) ? 'rd' : 'th';
        },
        currency: {
            symbol: '$'
        }
    });

    function format(input, formatString, language, roundingFunction) {
        return formatNumeral(
            Number(input),
            _.isString(formatString)        ? formatString        : defaultFormat,
            _.isString(language)            ? languages[language] : languages[defaultLanguage],
            _.isUndefined(roundingFunction) ? Math.round          : roundingFunction);
    }

    return {"format": format};
});
<|endoftext|>