<commit_before>define(['app', 'text!views/forms/view/record-loader.directive.html',
	'scbd-angularjs-services', 'ngSmoothScroll',
	'scbd-angularjs-filters',
	'./view-history-directive',
    'js/common',
    'views/directives/document-metadata-directive',
    'views/directives/internal-record-details',
    'views/directives/party-status',
    'views/forms/view/view-default-reference.directive',
    'views/forms/view/view-contact-reference.directive',
	'services/search-service',
	'views/directives/block-region-directive'
], function (app, template) {
	app.directive('recordLoader', [function () {
		return {
			restrict: 'EAC',
			template: template,
			replace: true,
			transclude: false,
			scope: {
				linkTarget: "@",
				document: "=",
				locale: "=",
				hide: "@",
				showDetails: "=",
				api: '=?'
			},
			link: function ($scope) {

				if (!$scope.linkTarget || $scope.linkTarget == '')
					$scope.linkTarget = '_new';
				//debugger;
				$scope.internalDocument = undefined;
				$scope.internalDocumentInfo = undefined;

				if (!$scope.document)
					$scope.init();
			},
			controller: ['$scope', "$route", 'IStorage', "authentication", "$q", "$location", "commonjs", "$timeout",
				"$filter", "$http", "$http", "realm", "$element", '$compile', 'searchService', "IWorkflows",
				function ($scope, $route, storage, authentication, $q, $location, commonjs, $timeout, $filter,
					$http, $httpAWS, realm, $element, $compile, searchService, IWorkflows) {

					var schemaMapping = {
						news: 'views/forms/view/view-news.directive',
						absnationalreport: 'views/forms/view/view-abs-national-report.directive',
						abscheckpoint: 'views/forms/view/view-abs-checkpoint.directive',
						abscheckpointcommunique: 'views/forms/view/view-abs-checkpoint-communique.directive',
						abspermit: 'views/forms/view/view-abs-permit.directive',
						authority: 'views/forms/view/view-authority.directive',
						authorityreference: 'views/forms/view/view-authority-reference.directive',
						contact: 'views/forms/view/view-contact.directive',
						contactreference: 'views/forms/view/view-contact-reference.directive',
						database: 'views/forms/view/view-database.directive',
						measure: 'views/forms/view/view-measure.directive',
						organization: 'views/forms/view/view-organization.directive',
						organizationreference: 'views/forms/view/view-organization-reference.directive',
						resource: 'views/forms/view/view-resource.directive',
						focalpoint: 'views/forms/view/view-focalpoint.directive',
						meeting: 'views/forms/view/view-meeting.directive',
						statement: 'views/forms/view/view-statement.directive',
						pressrelease: 'views/forms/view/view-pressrelease.directive',
						new: 'views/forms/view/view-new.directive',
						notification: 'views/forms/view/view-notification.directive',
						capacitybuildinginitiative: 'views/forms/view/view-capacity-building-initiative.directive',
						capacitybuildingresource: 'views/forms/view/view-capacity-building-resource.directive'
					}

					$scope.$watch("document", function (_new) {
						$scope.error = null;
						$scope.internalDocument = _new;
						if ($scope.internalDocument && ($scope.internalDocument.schema || $scope.internalDocument.header)) {
							loadViewDirective($scope.internalDocument.schema || $scope.internalDocument.header.schema);
							checkIfPermitRevoked();
						}
					});

					$scope.getUserCountry = function (id) {
                        var term = {};
                        term.identifier = id
                        return $filter('term')(term);
					}
					//==================================
					//
					//==================================
					$scope.init = function () {

						if ($scope.internalDocument && !$scope.revisionNo)
							return;

						if ($scope.document || $scope.schema)
							return;

						var documentSchema = $route.current.params.documentSchema;
						var documentRevision = $route.current.params.revision;

						var documentID = $route.current.params.documentID
						//documentSchema ? commonjs.integerToHex($route.current.params.documentID, documentSchema) : $route.current.params.documentID;

						if ($scope.revisionNo)
							documentRevision = $scope.revisionNo;

						if ($route.current.params.documentNumber)
							var documentID = $route.current.params.documentNumber;

						if (documentID && documentID.toLowerCase().indexOf('absch') == 0) {
							var docNum = documentID.split('-');
							if (docNum.length == 5) {
								documentID = documentID.toLowerCase();//.replace('absch','ABSCH');
								$scope.documentUID = documentID.toUpperCase();
								var schemaFolder = $filter("mapSchema")(docNum[1]);
								$scope.documentUrl = "https://s3.amazonaws.com/absch.documents." + realm.value.toLowerCase() + "/" + schemaFolder + '/' + documentID + '.pdf?id=' + new Date();

								$httpAWS.head($scope.documentUrl, { cache: false }).then(function (success) {
									$scope.documentSuccess = true;
									window.location.href = $scope.documentUrl;
									closeWindow();
								},
									function (error) {
										$scope.documentError = true;
										console.log(error);
									});

								return;
							}
							if (docNum.length <= 4)
								documentID = docNum[docNum.length - 1];

						}
						documentID = commonjs.integerToHex(documentID, documentSchema);

						$scope.loadDocument(documentSchema, documentID, documentRevision);
						// else
						// 	$scope.error = "documentID not specified";

					}

					//==================================
					//
					//==================================
					$scope.loadDocument = function (documentSchema, documentID, documentRevision) {

						if (documentSchema &&
							_.contains(["MEETING", "NOTIFICATION", "PRESSRELEASE", "STATEMENT", "NEWS", "NEW", "ST", "NT", "MT", "PR", "MTD"], documentSchema.toUpperCase())) {
							$scope.loading = true;
							commonjs.getReferenceRecordIndex(documentSchema, documentID)
								.then(function (data) {
									$scope.internalDocument = data.data;
									$scope.loading = false;
								});
							loadViewDirective(documentSchema);
						}
						else if (documentID) {
							$scope.load(documentID, documentRevision);
						}
					};

					$scope.timeLaspe = 20;
					function closeWindow() {
						if ($scope.timeLaspe == 0)
							window.close();
						$scope.timeLaspe--;
						$timeout(function () { closeWindow(); }, 1000)
					}

					//==================================
					//
					//==================================
					$scope.load = function (identifier, version) {

						$scope.error = undefined;
						var qDocument;
						var qDocumentInfo;

						var config = {};

						if (version == 'draft') {
							qDocument = storage.drafts.get(identifier, undefined, config).then(function (result) { return result.data || result });
							qDocumentInfo = storage.drafts.get(identifier, { info: true }, config).then(function (result) { return result.data || result });
						}
						else if (version == undefined) {
							config.params = {skipRealmHeader : true};
							qDocument = storage.documents.get(identifier, {'include-deleted':true}, config).then(function (result) { return result.data || result });
							qDocumentInfo = storage.documents.get(identifier, { info: true, 'include-deleted':true }, config).then(function (result) { return result.data || result });
						}
						else {
							config.params = {skipRealmHeader : true};
							qDocument = storage.documents.get(identifier + '@' + version, {'include-deleted':true}, config).then(function (result) { return result.data || result });
							qDocumentInfo = storage.documents.get(identifier + '@' + version, {'include-deleted':true, info: true }, config).then(function (result) { return result.data || result });

						}
						$scope.loading = true;
						$q.all([qDocument, qDocumentInfo]).then(function (results) {

							$scope.internalDocument = results[0];
							$scope.internalDocumentInfo = results[1];
							$scope.internalDocument.info = results[1];
							checkIfPermitRevoked();

							if (version)
								$scope.revisionNo = version

							checkIfPermitRevoked();

							if ($scope.internalDocumentInfo.workingDocumentLock) {
								IWorkflows.get($scope.internalDocumentInfo.workingDocumentLock.lockID.replace('workflow-', ''))
									.then(function (workflow) {
										if (workflow && workflow.type.name == 'delete-record')
											$scope.workflowRequestType = "deletion";
										else
											$scope.workflowRequestType = "publishing";
									});
							}
							if (version)
								$scope.revisionNo = version

							loadViewDirective($scope.internalDocument.header.schema);

						}).catch(function (error) {
							if (error.status == 404 && version != 'draft') {
								$scope.load(identifier, 'draft');
							}
						})
							.finally(function () {
								$scope.loading = false;
							})

					};

					//==================================
					//
					//==================================
					$scope.getUser = function () {

						if (!$scope.user)
							$q.when(authentication.getUser(), function (user) { $scope.user = user; });

						return $scope.user
					};

					//==================================
					//
					//==================================
					$scope.edit = function () {
						if (!$scope.canEdit())
							throw "Cannot edit form";

						var schema = $scope.internalDocumentInfo.type;
						var identifier = $scope.internalDocumentInfo.identifier;
						$timeout(function () {
							$location.path("/register/" + $filter("urlSchemaShortName")(schema) + "/" + identifier + '/edit');
						}, 1);

					}

					//==================================
					//
					//==================================
					$scope.canEdit = function () {

						if ($scope.getUser() && !$scope.getUser().isAuthenticated)
							return false;

						if (!$scope.internalDocumentInfo && $scope.internalDocument && $scope.internalDocument.info) {
							$scope.internalDocumentInfo = $scope.internalDocument.info;
						}

						if (!$scope.internalDocumentInfo)
							return false;
						if ($scope.internalCanEdit === undefined) {

							$scope.internalCanEdit = null; // avoid recall => null !== undefined

							var hasDraft = !!$scope.internalDocumentInfo.workingDocumentCreatedOn;
							var identifier = $scope.internalDocumentInfo.identifier;
							var schema = $scope.internalDocumentInfo.type;

							var qCanEdit = hasDraft
								? storage.drafts.security.canUpdate(identifier, schema)  // has draft
								: storage.drafts.security.canCreate(identifier, schema); // has no draft

							qCanEdit.then(function (isAllowed) {

								$scope.internalCanEdit = isAllowed || false;

							}).then(null, function (error) {

								$scope.internalCanEdit = false;
							});
						}

						return $scope.internalCanEdit === true;
					};

					$scope.loadRevision = function (val) {

						if ($scope.revisionNo != val) {
							$scope.revisionNo = val;
							//$scope.internalDocument = null
							$scope.init();
						}
					}

					$scope.$on('loadDocument', function (evt, evtData) {

						if (evtData.documentId && evtData.schema && !$scope.document) {

							$scope.loadDocument(evtData.schema, evtData.documentId);
						}
						if ($scope.document) {
							loadViewDirective(evtData.schema)
						}

					});

					function loadViewDirective(schema) {

						if (!schema)
							return;

						var lschema = _.clone(schema);

						if (schema.toLowerCase() == 'modelcontractualclause' || schema.toLowerCase() == 'communityprotocol')
							lschema = 'resource';

						if (_.contains(["NEWS", "NEW",], lschema.toUpperCase()))
							lschema = lschema.toLowerCase();
						else if (_.contains(["NFP", "ST", "NT", "MT", "PR", "MTD"], lschema.toUpperCase()))
							lschema = $filter("mapSchema")(lschema);

						var schemaDetails = schemaMapping[lschema.toLowerCase()];

						require([schemaDetails], function () {
							var name = snake_case(lschema);
							var directiveHtml =
								"<DIRECTIVE ng-show='internalDocument' ng-model='internalDocument' document-info='internalDocumentInfo' link-target={{linkTarget}}></DIRECTIVE>"
									.replace(/DIRECTIVE/g, 'view-' + name);
							$scope.$apply(function () {
								$element.find('#schemaView')
									.empty()
									.append($compile(directiveHtml)($scope));
							});
						});

					}
					function snake_case(name, separator) {

						separator = separator || '-';
						return name.replace(/[A-Z]/g, function (letter, pos) {
							return (pos ? separator : '') + letter.toLowerCase();
						});
					}

					function checkIfPermitRevoked() {

						if ($scope.internalDocument && $scope.internalDocument.header.schema == 'absPermit') {
							if ($scope.internalDocument.amendmentIntent == 1)
								$scope.isIRCCRevoked = true;
						}
					}

					$scope.api = {
						loadDocument: $scope.loadDocument,
						getDocument: function(){return $scope.internalDocument},
						getDocumentInfo : function(){$scope.internalDocumentInfo}
					}

					var queryString = $location.search();
					if(queryString && queryString.print){
						$scope.printMode = true;
						require(['css!/app/css/print-friendly'])
					}
				}]
		}
	}]);
});
<commit_msg>convert nfp id to hex<commit_after>define(['app', 'text!views/forms/view/record-loader.directive.html',
	'scbd-angularjs-services', 'ngSmoothScroll',
	'scbd-angularjs-filters',
	'./view-history-directive',
    'js/common',
    'views/directives/document-metadata-directive',
    'views/directives/internal-record-details',
    'views/directives/party-status',
    'views/forms/view/view-default-reference.directive',
    'views/forms/view/view-contact-reference.directive',
	'services/search-service',
	'views/directives/block-region-directive'
], function (app, template) {
	app.directive('recordLoader', [function () {
		return {
			restrict: 'EAC',
			template: template,
			replace: true,
			transclude: false,
			scope: {
				linkTarget: "@",
				document: "=",
				locale: "=",
				hide: "@",
				showDetails: "=",
				api: '=?'
			},
			link: function ($scope) {

				if (!$scope.linkTarget || $scope.linkTarget == '')
					$scope.linkTarget = '_new';
				//debugger;
				$scope.internalDocument = undefined;
				$scope.internalDocumentInfo = undefined;

				if (!$scope.document)
					$scope.init();
			},
			controller: ['$scope', "$route", 'IStorage', "authentication", "$q", "$location", "commonjs", "$timeout",
				"$filter", "$http", "$http", "realm", "$element", '$compile', 'searchService', "IWorkflows",
				function ($scope, $route, storage, authentication, $q, $location, commonjs, $timeout, $filter,
					$http, $httpAWS, realm, $element, $compile, searchService, IWorkflows) {

					var schemaMapping = {
						news: 'views/forms/view/view-news.directive',
						absnationalreport: 'views/forms/view/view-abs-national-report.directive',
						abscheckpoint: 'views/forms/view/view-abs-checkpoint.directive',
						abscheckpointcommunique: 'views/forms/view/view-abs-checkpoint-communique.directive',
						abspermit: 'views/forms/view/view-abs-permit.directive',
						authority: 'views/forms/view/view-authority.directive',
						authorityreference: 'views/forms/view/view-authority-reference.directive',
						contact: 'views/forms/view/view-contact.directive',
						contactreference: 'views/forms/view/view-contact-reference.directive',
						database: 'views/forms/view/view-database.directive',
						measure: 'views/forms/view/view-measure.directive',
						organization: 'views/forms/view/view-organization.directive',
						organizationreference: 'views/forms/view/view-organization-reference.directive',
						resource: 'views/forms/view/view-resource.directive',
						focalpoint: 'views/forms/view/view-focalpoint.directive',
						meeting: 'views/forms/view/view-meeting.directive',
						statement: 'views/forms/view/view-statement.directive',
						pressrelease: 'views/forms/view/view-pressrelease.directive',
						new: 'views/forms/view/view-new.directive',
						notification: 'views/forms/view/view-notification.directive',
						capacitybuildinginitiative: 'views/forms/view/view-capacity-building-initiative.directive',
						capacitybuildingresource: 'views/forms/view/view-capacity-building-resource.directive'
					}

					$scope.$watch("document", function (_new) {
						$scope.error = null;
						$scope.internalDocument = _new;
						if ($scope.internalDocument && ($scope.internalDocument.schema || $scope.internalDocument.header)) {
							loadViewDirective($scope.internalDocument.schema || $scope.internalDocument.header.schema);
							checkIfPermitRevoked();
						}
					});

					$scope.getUserCountry = function (id) {
                        var term = {};
                        term.identifier = id
                        return $filter('term')(term);
					}
					//==================================
					//
					//==================================
					$scope.init = function () {

						if ($scope.internalDocument && !$scope.revisionNo)
							return;

						if ($scope.document || $scope.schema)
							return;

						var documentSchema = $route.current.params.documentSchema;
						var documentRevision = $route.current.params.revision;

						var documentID = $route.current.params.documentID
						//documentSchema ? commonjs.integerToHex($route.current.params.documentID, documentSchema) : $route.current.params.documentID;

						if ($scope.revisionNo)
							documentRevision = $scope.revisionNo;

						if ($route.current.params.documentNumber)
							var documentID = $route.current.params.documentNumber;

						if (documentID && documentID.toLowerCase().indexOf('absch') == 0) {
							var docNum = documentID.split('-');
							if (docNum.length == 5) {
								documentID = documentID.toLowerCase();//.replace('absch','ABSCH');
								$scope.documentUID = documentID.toUpperCase();
								var schemaFolder = $filter("mapSchema")(docNum[1]);
								$scope.documentUrl = "https://s3.amazonaws.com/absch.documents." + realm.value.toLowerCase() + "/" + schemaFolder + '/' + documentID + '.pdf?id=' + new Date();

								$httpAWS.head($scope.documentUrl, { cache: false }).then(function (success) {
									$scope.documentSuccess = true;
									window.location.href = $scope.documentUrl;
									closeWindow();
								},
									function (error) {
										$scope.documentError = true;
										console.log(error);
									});

								return;
							}
							if (docNum.length <= 4)
								documentID = docNum[docNum.length - 1];

						}
						documentID = commonjs.integerToHex(documentID, documentSchema);

						$scope.loadDocument(documentSchema, documentID, documentRevision);
						// else
						// 	$scope.error = "documentID not specified";

					}

					//==================================
					//
					//==================================
					$scope.loadDocument = function (documentSchema, documentID, documentRevision) {

						if (documentSchema &&
							_.contains(["MEETING", "NOTIFICATION", "PRESSRELEASE", "STATEMENT", "NEWS", "NEW", "ST", "NT", "MT", "PR", "MTD"], documentSchema.toUpperCase())) {
							$scope.loading = true;
							commonjs.getReferenceRecordIndex(documentSchema, documentID)
								.then(function (data) {
									$scope.internalDocument = data.data;
									$scope.loading = false;
								});
							loadViewDirective(documentSchema);
						}
						else if (documentID) {
							if(_.contains(['FOCALPOINT', 'NFP'], documentSchema.toUpperCase()))
								documentID = commonjs.integerToHex(documentID);

							$scope.load(documentID, documentRevision);
						}
					};

					$scope.timeLaspe = 20;
					function closeWindow() {
						if ($scope.timeLaspe == 0)
							window.close();
						$scope.timeLaspe--;
						$timeout(function () { closeWindow(); }, 1000)
					}

					//==================================
					//
					//==================================
					$scope.load = function (identifier, version) {

						$scope.error = undefined;
						var qDocument;
						var qDocumentInfo;

						var config = {};

						if (version == 'draft') {
							qDocument = storage.drafts.get(identifier, undefined, config).then(function (result) { return result.data || result });
							qDocumentInfo = storage.drafts.get(identifier, { info: true }, config).then(function (result) { return result.data || result });
						}
						else if (version == undefined) {
							config.params = {skipRealmHeader : true};
							qDocument = storage.documents.get(identifier, {'include-deleted':true}, config).then(function (result) { return result.data || result });
							qDocumentInfo = storage.documents.get(identifier, { info: true, 'include-deleted':true }, config).then(function (result) { return result.data || result });
						}
						else {
							config.params = {skipRealmHeader : true};
							qDocument = storage.documents.get(identifier + '@' + version, {'include-deleted':true}, config).then(function (result) { return result.data || result });
							qDocumentInfo = storage.documents.get(identifier + '@' + version, {'include-deleted':true, info: true }, config).then(function (result) { return result.data || result });

						}
						$scope.loading = true;
						$q.all([qDocument, qDocumentInfo]).then(function (results) {

							$scope.internalDocument = results[0];
							$scope.internalDocumentInfo = results[1];
							$scope.internalDocument.info = results[1];
							checkIfPermitRevoked();

							if (version)
								$scope.revisionNo = version

							checkIfPermitRevoked();

							if ($scope.internalDocumentInfo.workingDocumentLock) {
								IWorkflows.get($scope.internalDocumentInfo.workingDocumentLock.lockID.replace('workflow-', ''))
									.then(function (workflow) {
										if (workflow && workflow.type.name == 'delete-record')
											$scope.workflowRequestType = "deletion";
										else
											$scope.workflowRequestType = "publishing";
									});
							}
							if (version)
								$scope.revisionNo = version

							loadViewDirective($scope.internalDocument.header.schema);

						}).catch(function (error) {
							if (error.status == 404 && version != 'draft') {
								$scope.load(identifier, 'draft');
							}
						})
							.finally(function () {
								$scope.loading = false;
							})

					};

					//==================================
					//
					//==================================
					$scope.getUser = function () {

						if (!$scope.user)
							$q.when(authentication.getUser(), function (user) { $scope.user = user; });

						return $scope.user
					};

					//==================================
					//
					//==================================
					$scope.edit = function () {
						if (!$scope.canEdit())
							throw "Cannot edit form";

						var schema = $scope.internalDocumentInfo.type;
						var identifier = $scope.internalDocumentInfo.identifier;
						$timeout(function () {
							$location.path("/register/" + $filter("urlSchemaShortName")(schema) + "/" + identifier + '/edit');
						}, 1);

					}

					//==================================
					//
					//==================================
					$scope.canEdit = function () {

						if ($scope.getUser() && !$scope.getUser().isAuthenticated)
							return false;

						if (!$scope.internalDocumentInfo && $scope.internalDocument && $scope.internalDocument.info) {
							$scope.internalDocumentInfo = $scope.internalDocument.info;
						}

						if (!$scope.internalDocumentInfo)
							return false;
						if ($scope.internalCanEdit === undefined) {

							$scope.internalCanEdit = null; // avoid recall => null !== undefined

							var hasDraft = !!$scope.internalDocumentInfo.workingDocumentCreatedOn;
							var identifier = $scope.internalDocumentInfo.identifier;
							var schema = $scope.internalDocumentInfo.type;

							var qCanEdit = hasDraft
								? storage.drafts.security.canUpdate(identifier, schema)  // has draft
								: storage.drafts.security.canCreate(identifier, schema); // has no draft

							qCanEdit.then(function (isAllowed) {

								$scope.internalCanEdit = isAllowed || false;

							}).then(null, function (error) {

								$scope.internalCanEdit = false;
							});
						}

						return $scope.internalCanEdit === true;
					};

					$scope.loadRevision = function (val) {

						if ($scope.revisionNo != val) {
							$scope.revisionNo = val;
							//$scope.internalDocument = null
							$scope.init();
						}
					}

					$scope.$on('loadDocument', function (evt, evtData) {

						if (evtData.documentId && evtData.schema && !$scope.document) {

							$scope.loadDocument(evtData.schema, evtData.documentId);
						}
						if ($scope.document) {
							loadViewDirective(evtData.schema)
						}

					});

					function loadViewDirective(schema) {

						if (!schema)
							return;

						var lschema = _.clone(schema);

						if (schema.toLowerCase() == 'modelcontractualclause' || schema.toLowerCase() == 'communityprotocol')
							lschema = 'resource';

						if (_.contains(["NEWS", "NEW",], lschema.toUpperCase()))
							lschema = lschema.toLowerCase();
						else if (_.contains(["NFP", "ST", "NT", "MT", "PR", "MTD"], lschema.toUpperCase()))
							lschema = $filter("mapSchema")(lschema);

						var schemaDetails = schemaMapping[lschema.toLowerCase()];

						require([schemaDetails], function () {
							var name = snake_case(lschema);
							var directiveHtml =
								"<DIRECTIVE ng-show='internalDocument' ng-model='internalDocument' document-info='internalDocumentInfo' link-target={{linkTarget}}></DIRECTIVE>"
									.replace(/DIRECTIVE/g, 'view-' + name);
							$scope.$apply(function () {
								$element.find('#schemaView')
									.empty()
									.append($compile(directiveHtml)($scope));
							});
						});

					}
					function snake_case(name, separator) {

						separator = separator || '-';
						return name.replace(/[A-Z]/g, function (letter, pos) {
							return (pos ? separator : '') + letter.toLowerCase();
						});
					}

					function checkIfPermitRevoked() {

						if ($scope.internalDocument && $scope.internalDocument.header.schema == 'absPermit') {
							if ($scope.internalDocument.amendmentIntent == 1)
								$scope.isIRCCRevoked = true;
						}
					}

					$scope.api = {
						loadDocument: $scope.loadDocument,
						getDocument: function(){return $scope.internalDocument},
						getDocumentInfo : function(){$scope.internalDocumentInfo}
					}

					var queryString = $location.search();
					if(queryString && queryString.print){
						$scope.printMode = true;
						require(['css!/app/css/print-friendly'])
					}
				}]
		}
	}]);
});
<|endoftext|>


<commit_before>define([

], function() {
	var TriggerField = function(world, aabb) {
		this.aabb = aabb;
		this._world = world;
		world.addTriggerField(this);
	};

	TriggerField.prototype.update = function() {
		// overlap Body (one pointMass should be inside the AABB)
		if(this._overlapBodyCallback || this._containBodyCallback) {
			for(var i = 0; i < this._world.mBodies.length; i++) {
				var body = this._world.getBody(i);

				var containsAllPointMasses = true;
				var containsAPointMass = false;
				// iterate each pointMass in given body
				for(var j = 0; j < body.getBoundaryCount(); j++) {
					if(this.aabb.contains(body.getPointMass(j).Position))
						containsAPointMass = true;
					else
						containsAllPointMasses = false;
				}
				if(containsAPointMass && this._overlapBodyCallback)
					this._overlapBodyCallback(body);
				if(containsAllPointMasses && this._containBodyCallback)
					this._containBodyCallback(body);
			}
		}
	};

	TriggerField.prototype.onOverlapBody = function(callback) {
		this._overlapBodyCallback = callback;
		return this;
	};

	TriggerField.prototype.onContainBody = function(callback) {
		this._containBodyCallback = callback;
		return this;
	};

	TriggerField.prototype.debugDraw = function(debugDraw) {
		this.aabb.debugDraw(debugDraw);
	};

	return TriggerField;
});
<commit_msg>added Signals to TriggerFields<commit_after>define([

], function() {
	var TriggerField = function(world, aabb) {
		this.aabb = aabb;
		this._world = world;

		this._overlapSignal = env.eventManager.signal("overlap");
		this._containsSignal = env.eventManager.signal("contains");

		world.addTriggerField(this);
	};

	TriggerField.prototype.update = function() {
		// overlap Body (one pointMass should be inside the AABB)
		if(this._overlapBodyCallback || this._containBodyCallback) {
			// TODO: use Quadtree and Bitmask for optimization
			for(var i = 0; i < this._world.mBodies.length; i++) {
				var body = this._world.getBody(i);

				var containsAllPointMasses = true;
				var containsAPointMass = false;
				// iterate each pointMass in given body
				for(var j = 0; j < body.getBoundaryCount(); j++) {
					if(this.aabb.contains(body.getPointMass(j).Position))
						containsAPointMass = true;
					else
						containsAllPointMasses = false;
				}
				if(containsAPointMass && this._overlapBodyCallback)
					this._overlapBodyCallback(body);
				if(containsAllPointMasses && this._containBodyCallback)
					this._containBodyCallback(body);
				if(containsAPointMass)
					this._overlapSignal.emit(this, body);
				if(containsAllPointMasses)
					this._containsSignal.emit(this, body);
			}
		}
	};

	TriggerField.prototype.onOverlapBody = function(callback) {
		this._overlapBodyCallback = callback;
		return this;
	};

	TriggerField.prototype.onContainBody = function(callback) {
		this._containBodyCallback = callback;
		return this;
	};

	TriggerField.prototype.debugDraw = function(debugDraw) {
		this.aabb.debugDraw(debugDraw);
	};

	return TriggerField;
});
<|endoftext|>


<commit_before>'use strict';

var passport     = require( 'passport' ),
    LocalStorage = require( 'passport-local' ).Strategy;

/**
 * Authentication plugin
 * @param {Route} route
 * @param {Object} opts
 * @returns {Function}
 */
function authenticate( route, opts ) {

    passport.serializeUser( function( user, done ) {
        done( null, user._id );
    } );

    passport.deserializeUser( function( id, done ) {
        opts.model.findById( id, function( err, user ) {
            done( err, user );
        } );
    } );

    route.pre( 'dispatch', function( req, res ) {

    } );

}

module.exports = authenticate;
<commit_msg>fix: lint issues<commit_after>'use strict';

var passport = require( 'passport' );

/**
 * Authentication plugin
 * @param {Route} route
 * @param {Object} opts
 * @returns {Function}
 */
function authenticate( route, opts ) {

    passport.serializeUser( function( user, done ) {
        done( null, user._id );
    } );

    passport.deserializeUser( function( id, done ) {
        opts.model.findById( id, function( err, user ) {
            done( err, user );
        } );
    } );

    route.pre( 'dispatch', function() {
    } );

}

module.exports = authenticate;
<|endoftext|>


<commit_before>const consoleLogger = require('../../util/logger.js')
const http = require('http')
const extractTokenRegEx = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/
const tokenFormatRegEx = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/
const TokenBlacklist = require('../../util/token-blacklist.js')

function jsonParse (text) {
  try {
    return JSON.parse(text)
  } catch (err) {
    return null
  }
}

function extractJson (line, source) {
  var parsed = {}
  if (/^\[{0,1}\{.*\}]{0,1}$/.test(line)) {
    parsed = jsonParse(line)
    if (!parsed) {
      return null
    }
    return parsed
  }
}

function InputHeroku (config, eventEmitter) {
  this.config = config
  this.eventEmitter = eventEmitter
  if (config.useIndexFromUrlPath === undefined) {
    config.useIndexFromUrlPath = true
  }
  this.tokenBlackList = new TokenBlacklist(eventEmitter)
  this.config.port = this.config.heroku || config.port
  if (config.workers) {
    this.config.herokuWorkers = config.workers
  } else {
    this.config.herokuWorkers = undefined
  }
}
InputHeroku.prototype.start = function () {
  if (this.config.port) {
    this.throng = require('throng')
    this.throng(
      {
        workers: this.config.herokuWorkers || this.WORKERS || 2,
        lifetime: Infinity
      },
      this.startHerokuServer.bind(this)
    )
  }
}

InputHeroku.prototype.stop = function (cb) {
  if (this.server) {
    this.server.close(cb)
  }
}

InputHeroku.prototype.getHttpServer = function (aport, handler) {
  var _port = aport || process.env.PORT
  if (aport === true) {
    // a command line flag was set but no port given
    _port = process.env.PORT
  }
  var server = http.createServer(handler)

  // Increase the connection timeout to equal the Nginx Ingress timeout of 1min.
  server.on('connection', socket => socket.setTimeout(60 * 1000))

  this.server = server
  try {
    server = server.listen(_port)
    consoleLogger.log(
      'Logagent listening (http): ' + _port + ', process id: ' + process.pid
    )
    return server
  } catch (err) {
    consoleLogger.log('Port in use (' + _port + '): ' + err)
  }
}

function filterHerokuMessage (data, context) {
  if (data) {
    data._type = context.sourceName.replace('_' + context.index, '')
    data.logSource = ('' + data.logSource).replace('_' + context.index, '')
    var msg = {
      message: data.message,
      app: data.app,
      host: data.host,
      process_type: data.process_type,
      originalLine: data.originalLine,
      severity: data.severity,
      facility: data.facility
    }
    msg.json = extractJson(msg.message)
    var optionalFields = [
      'method',
      'path',
      'host',
      'request_id',
      'fwd',
      'dyno',
      'connect',
      'service',
      'status',
      'bytes'
    ]
    optionalFields.forEach(function (f) {
      if (data[f]) {
        msg[f] = data[f]
      }
    })
    if (!data['@timestamp']) {
      msg['@timestamp'] = new Date()
    }
    return msg
  }
}

InputHeroku.prototype.herokuHandler = function (req, res) {
  try {
    var self = this
    var path = req.url.split('/')
    var token = null
    if (path.length > 1) {
      if (path[1] && path[1].length > 31 && tokenFormatRegEx.test(path[1])) {
        const match = path[1].match(extractTokenRegEx)
        if (match && match.length > 1) {
          token = match[1]
        }
      } else if (path[1] === 'health' || path[1] === 'ping') {
        res.statusCode = 200
        res.end('ok\n')
        return
      }
    }

    if (self.config.useIndexFromUrlPath && !token) {
      res.statusCode = 404
      res.end(
        '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
Error: Missing Logsene Token ' +
          req.url +
          '. Please use /LOGSENE_TOKEN. More info:

Heroku Log Drain for Logsene

Logsene Log Management by Sematext

'
      )
      return
    }

    if (
      (self.config.useIndexFromUrlPath === true && !token) ||
      self.tokenBlackList.isTokenInvalid(token)
    ) {
      res.statusCode = self.config.invalidTokenStatus || 403
      res.end(`invalid logs token in url ${req.url}\n`)
      return
    }

    var body = ''
    req.on('data', function (data) {
      body += data
    })
    req.on('end', function endHandler () {
      var lines = body.split('\n')
      lines.forEach(function (line) {
        if (!line) {
          return
        }
        self.eventEmitter.emit('data.raw', line, {
          sourceName: 'heroku_' + token,
          index: token,
          filter: filterHerokuMessage
        })
      })
      res.end('ok\n')
    })
  } catch (err) {
    consoleLogger.error('Error in Heroku (http): ' + err)
  }
}
// heroku start function for WEB_CONCURENCY
InputHeroku.prototype.startHerokuServer = function (id) {
  consoleLogger.log('start heroku worker: ' + id + ', pid:' + process.pid)
  this.getHttpServer(Number(this.config.port), this.herokuHandler.bind(this))
  var exitInProgress = false
  var terminate = function (reason) {
    return function () {
      if (exitInProgress) {
        return
      }
      exitInProgress = true
      consoleLogger.log(
        'stop heroku worker: ' +
          id +
          ', pid:' +
          process.pid +
          ', terminate reason: ' +
          reason +
          ' memory rss: ' +
          (process.memoryUsage().rss / (1024 * 1024)).toFixed(2) +
          ' MB'
      )
      setTimeout(process.exit, 250)
    }
  }
  process.once('SIGTERM', terminate('SIGTERM'))
  process.once('SIGINT', terminate('SIGINT'))
  process.once('exit', terminate('exit'))
}

module.exports = InputHeroku
<commit_msg>removed filter from heroku input plugin<commit_after>const consoleLogger = require('../../util/logger.js')
const http = require('http')
const extractTokenRegEx = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/
const tokenFormatRegEx = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/
const TokenBlacklist = require('../../util/token-blacklist.js')

function InputHeroku (config, eventEmitter) {
  this.config = config
  this.eventEmitter = eventEmitter
  if (config.useIndexFromUrlPath === undefined) {
    config.useIndexFromUrlPath = true
  }
  this.tokenBlackList = new TokenBlacklist(eventEmitter)
  this.config.port = this.config.heroku || config.port
  if (config.workers) {
    this.config.herokuWorkers = config.workers
  } else {
    this.config.herokuWorkers = undefined
  }
}
InputHeroku.prototype.start = function () {
  if (this.config.port) {
    this.throng = require('throng')
    this.throng(
      {
        workers: this.config.herokuWorkers || this.WORKERS || 2,
        lifetime: Infinity
      },
      this.startHerokuServer.bind(this)
    )
  }
}

InputHeroku.prototype.stop = function (cb) {
  if (this.server) {
    this.server.close(cb)
  }
}

InputHeroku.prototype.getHttpServer = function (aport, handler) {
  var _port = aport || process.env.PORT
  if (aport === true) {
    // a command line flag was set but no port given
    _port = process.env.PORT
  }
  var server = http.createServer(handler)

  // Increase the connection timeout to equal the Nginx Ingress timeout of 1min.
  server.on('connection', socket => socket.setTimeout(60 * 1000))

  this.server = server
  try {
    server = server.listen(_port)
    consoleLogger.log(
      'Logagent listening (http): ' + _port + ', process id: ' + process.pid
    )
    return server
  } catch (err) {
    consoleLogger.log('Port in use (' + _port + '): ' + err)
  }
}

InputHeroku.prototype.herokuHandler = function (req, res) {
  try {
    var self = this
    var path = req.url.split('/')
    var token = null
    if (path.length > 1) {
      if (path[1] && path[1].length > 31 && tokenFormatRegEx.test(path[1])) {
        const match = path[1].match(extractTokenRegEx)
        if (match && match.length > 1) {
          token = match[1]
        }
      } else if (path[1] === 'health' || path[1] === 'ping') {
        res.statusCode = 200
        res.end('ok\n')
        return
      }
    }

    if (self.config.useIndexFromUrlPath && !token) {
      res.statusCode = 404
      res.end(
        '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
Error: Missing Logsene Token ' +
          req.url +
          '. Please use /LOGSENE_TOKEN. More info:

Heroku Log Drain for Logsene

Logsene Log Management by Sematext

'
      )
      return
    }

    if (
      (self.config.useIndexFromUrlPath === true && !token) ||
      self.tokenBlackList.isTokenInvalid(token)
    ) {
      res.statusCode = self.config.invalidTokenStatus || 403
      res.end(`invalid logs token in url ${req.url}\n`)
      return
    }

    var body = ''
    req.on('data', function (data) {
      body += data
    })
    req.on('end', function endHandler () {
      var lines = body.split('\n')
      lines.forEach(function (line) {
        if (!line) {
          return
        }
        self.eventEmitter.emit('data.raw', line, {
          sourceName: 'heroku_' + token,
          index: token
        })
      })
      res.end('ok\n')
    })
  } catch (err) {
    consoleLogger.error('Error in Heroku (http): ' + err)
  }
}
// heroku start function for WEB_CONCURENCY
InputHeroku.prototype.startHerokuServer = function (id) {
  consoleLogger.log('start heroku worker: ' + id + ', pid:' + process.pid)
  this.getHttpServer(Number(this.config.port), this.herokuHandler.bind(this))
  var exitInProgress = false
  var terminate = function (reason) {
    return function () {
      if (exitInProgress) {
        return
      }
      exitInProgress = true
      consoleLogger.log(
        'stop heroku worker: ' +
          id +
          ', pid:' +
          process.pid +
          ', terminate reason: ' +
          reason +
          ' memory rss: ' +
          (process.memoryUsage().rss / (1024 * 1024)).toFixed(2) +
          ' MB'
      )
      setTimeout(process.exit, 250)
    }
  }
  process.once('SIGTERM', terminate('SIGTERM'))
  process.once('SIGINT', terminate('SIGINT'))
  process.once('exit', terminate('exit'))
}

module.exports = InputHeroku
<|endoftext|>


<commit_before>const mongodb = require('mongodb');

const Plugin = require('../plugin');

module.exports = Plugin.define('mongo', [], {
  defaultConfig: {
    'uri': null,
    'prefix': '',
  },
}, {
  async start (config) {
    if (!config.uri) {
      throw new Error('MongoDB URI (config path: "uri") not set');
    }

    const mongo = await mongodb.MongoClient.connect(config.uri);

    this.mongo = mongo;
    this.bot.mongo = {
      collection (name, ...rest) {
        return mongo.collection(`${config.prefix}${name}`, ...rest);
      },
    };
  },

  async stop (config) {
    await this.mongo.close();
  },
});

module.exports = mongodb.ObjectId;
<commit_msg>Fix mongo plugin<commit_after>const mongodb = require('mongodb');

const Plugin = require('../plugin');

module.exports = Plugin.define('mongo', [], {
  defaultConfig: {
    'uri': null,
    'prefix': '',
  },
}, {
  async start (config) {
    if (!config.uri) {
      throw new Error('MongoDB URI (config path: "uri") not set');
    }

    const mongo = await mongodb.MongoClient.connect(config.uri);

    this.mongo = mongo;
    this.bot.mongo = {
      collection (name, ...rest) {
        return mongo.collection(`${config.prefix}${name}`, ...rest);
      },
    };
  },

  async stop (config) {
    await this.mongo.close();
  },
});

module.exports.ObjectId = mongodb.ObjectId;
<|endoftext|>


<commit_before>(function($) {
  Sammy = Sammy || {};

  // Sammy.OAuth2 is a plugin for using OAuth 2.0 to authenticate users and
  // access your application's API. Requires Sammy.Session.
  //
  // Triggers the following events:
  //
  // * `oauth.connected` - Access token set and ready to use. Triggered when new
  // access token acquired, of when application starts and already has access
  // token.
  // * `oauth.disconnected` - Access token reset. Triggered by
  // loseAccessToken().
  // * `oauth.denied` - Authorization attempt rejected.
  //
  // ### Example
  //
  //       this.use('Storage');
  //       this.use('OAuth2');
  //       this.oauthorize = "/oauth/authorize";
  //
  //       // The quick & easy way
  //       this.requireOAuth();
  //       // Specific path
  //       this.requireOAuth("/private");
  //       // Filter you can apply to specific URLs
  //       this.before(function(context) { return context.requireOAuth(); })
  //       // Apply to specific request
  //       this.get("/private", function(context) {
  //         this.requireOAuth(function() {
  //           // Do something
  //         });
  //       });
  //
  //      // Sign in/sign out.
  //      this.bind("oauth.connected", function() { $("#signin").hide() });
  //      this.bind("oauth.disconnected", function() { $("#signin").show() });
  //
  //      // Handle access denied and other errors
  //      this.bind("oauth.denied", function(evt, error) {
  //        this.partial("admin/views/no_access.tmpl", { error: error.message });
  //      });
  //
  //      // Sign out.
  //      this.get("#/signout", function(context) {
  //        context.loseAccessToken();
  //        context.redirect("#/");
  //      });
  //
  Sammy.OAuth2 = function(app) {
    app.use('JSON');
    this.authorize = "/oauth/authorize";

    // Use this on request that require OAuth token. You can use this in a
    // filter: it will redirect and return false if the access token is missing.
    // You can use it in a route, it will redirect to get the access token, or
    // call the callback function if it has an access token.
    this.helper("requireOAuth", function(cb) {
      if (this.app.getAccessToken()) {
        if (cb) {
          cb.apply(this);
        }
      } else {
        this.redirect(this.app.authorize + "?state=" + escape(this.path));
        return false;
      }
    });

    // Use this to sign out.
    this.helper("loseAccessToken", function() {
      this.app.loseAccessToken();
    });

    // Use this in your application to require an OAuth access token on all, or
    // the specified paths. It sets up a before filter on the specified paths.
    this.requireOAuth = function(options) {
      this.before(options || {}, function(context) {
        return context.requireOAuth();
      });
    }

    // Returns the access token. Uses Sammy.Session to store the token.
    this.getAccessToken = function() {
      return this.session("oauth.token");
    }
    // Stores the access token in the session.
    this.setAccessToken = function(token) {
      this.session("oauth.token", token);
      this.trigger("oauth.connected");
    }
    // Lose access token: use this to sign out.
    this.loseAccessToken = function() {
      this.session("oauth.token", null);
      this.trigger("oauth.disconnected");
    }

    // Add OAuth 2.0 access token to all XHR requests.
    $(document).ajaxSend(function(evt, xhr) {
      var token = app.getAccessToken();
      if (token) {
        xhr.setRequestHeader("Authorization", "OAuth " + token);
      }
    });

    // Converts query string parameters in fragment identifier to object.
    function parseParams(path) {
      var hash = path.match(/#(.*)$/)[1];
      var pairs = hash.split("&"), params = {};
      for (var i in pairs) {
        var splat = pairs[i].split("=");
        params[splat[0]] = splat[1].replace(/\+/g, " ");
      }
      return params;
    }

    var start_url;
    // Capture the application's start URL, we'll need that later on for
    // redirection.
    this.bind("run", function(evt, params) {
      start_url = params.start_url || "#";
      if (this.app.getAccessToken()) {
        this.trigger("oauth.connected");
      }
    });

    // Intercept OAuth authorization response with access token, stores it and
    // redirects to original URL, or application root.
    this.before(/#(access_token=|[^\\].*\&access_token=)/, function(context) {
      var params = parseParams(context.path);
      this.app.setAccessToken(params.access_token);
      // When the filter redirected the original request, it passed the original
      // request's URL in the state parameter, which we get back after
      // authorization.
      context.redirect(params.state.length === 0 ? this.app.start_url : unescape(params.state));
      return false;
    }).get(/#(access_token=|[^\\].*\&access_token=)/, function(context) { });

    // Intercept OAuth authorization response with error (typically access
    // denied).
    this.before(/#(error=|[^\\].*\&error=)/, function(context) {
      var params = parseParams(context.path);
      var message = params.error_description || "Access denined";
      context.trigger("oauth.denied", { code: params.error, message: message });
      return false;
    }).get(/#(error=|[^\\].*\&error=)/, function(context) { });

  }
})(jQuery);
<commit_msg>fix oauth plugin for IE8<commit_after>(function($) {
  Sammy = Sammy || {};

  // Sammy.OAuth2 is a plugin for using OAuth 2.0 to authenticate users and
  // access your application's API. Requires Sammy.Session.
  //
  // Triggers the following events:
  //
  // * `oauth.connected` - Access token set and ready to use. Triggered when new
  // access token acquired, of when application starts and already has access
  // token.
  // * `oauth.disconnected` - Access token reset. Triggered by
  // loseAccessToken().
  // * `oauth.denied` - Authorization attempt rejected.
  //
  // ### Example
  //
  //       this.use('Storage');
  //       this.use('OAuth2');
  //       this.oauthorize = "/oauth/authorize";
  //
  //       // The quick & easy way
  //       this.requireOAuth();
  //       // Specific path
  //       this.requireOAuth("/private");
  //       // Filter you can apply to specific URLs
  //       this.before(function(context) { return context.requireOAuth(); })
  //       // Apply to specific request
  //       this.get("/private", function(context) {
  //         this.requireOAuth(function() {
  //           // Do something
  //         });
  //       });
  //
  //      // Sign in/sign out.
  //      this.bind("oauth.connected", function() { $("#signin").hide() });
  //      this.bind("oauth.disconnected", function() { $("#signin").show() });
  //
  //      // Handle access denied and other errors
  //      this.bind("oauth.denied", function(evt, error) {
  //        this.partial("admin/views/no_access.tmpl", { error: error.message });
  //      });
  //
  //      // Sign out.
  //      this.get("#/signout", function(context) {
  //        context.loseAccessToken();
  //        context.redirect("#/");
  //      });
  //
  Sammy.OAuth2 = function(app) {
    app.use('JSON');
    this.authorize = "/oauth/authorize";

    // Use this on request that require OAuth token. You can use this in a
    // filter: it will redirect and return false if the access token is missing.
    // You can use it in a route, it will redirect to get the access token, or
    // call the callback function if it has an access token.
    this.helper("requireOAuth", function(cb) {
      if (this.app.getAccessToken()) {
        if (cb) {
          cb.apply(this);
        }
      } else {
        this.redirect(this.app.authorize + "?state=" + escape(this.path));
        return false;
      }
    });

    // Use this to sign out.
    this.helper("loseAccessToken", function() {
      this.app.loseAccessToken();
    });

    // Use this in your application to require an OAuth access token on all, or
    // the specified paths. It sets up a before filter on the specified paths.
    this.requireOAuth = function(options) {
      this.before(options || {}, function(context) {
        return context.requireOAuth();
      });
    }

    // Returns the access token. Uses Sammy.Session to store the token.
    this.getAccessToken = function() {
      return this.session("oauth.token");
    }
    // Stores the access token in the session.
    this.setAccessToken = function(token) {
      this.session("oauth.token", token);
      this.trigger("oauth.connected");
    }
    // Lose access token: use this to sign out.
    this.loseAccessToken = function() {
      this.session("oauth.token", null);
      this.trigger("oauth.disconnected");
    }

    // Add OAuth 2.0 access token to all XHR requests.
    $(document).ajaxSend(function(evt, xhr) {
      var token = app.getAccessToken();
      if (token) {
        xhr.setRequestHeader("Authorization", "OAuth " + token);
      }
    });

    // Converts query string parameters in fragment identifier to object.
    function parseParams(path) {
      var hash = path.match(/#(.*)$/)[1];
      var pairs = hash.split("&"), params = {};
      var i, len = pairs.length;

      for (i = 0; i < len; i += 1) {
        var splat = pairs[i].split("=");
        params[splat[0]] = splat[1].replace(/\+/g, " ");
      }
      return params;
    }

    var start_url;
    // Capture the application's start URL, we'll need that later on for
    // redirection.
    this.bind("run", function(evt, params) {
      start_url = params.start_url || "#";
      if (this.app.getAccessToken()) {
        this.trigger("oauth.connected");
      }
    });

    // Intercept OAuth authorization response with access token, stores it and
    // redirects to original URL, or application root.
    this.before(/#(access_token=|[^\\].*\&access_token=)/, function(context) {
      var params = parseParams(context.path);
      this.app.setAccessToken(params.access_token);
      // When the filter redirected the original request, it passed the original
      // request's URL in the state parameter, which we get back after
      // authorization.
      context.redirect(params.state.length === 0 ? this.app.start_url : unescape(params.state));
      return false;
    }).get(/#(access_token=|[^\\].*\&access_token=)/, function(context) { });

    // Intercept OAuth authorization response with error (typically access
    // denied).
    this.before(/#(error=|[^\\].*\&error=)/, function(context) {
      var params = parseParams(context.path);
      var message = params.error_description || "Access denined";
      context.trigger("oauth.denied", { code: params.error, message: message });
      return false;
    }).get(/#(error=|[^\\].*\&error=)/, function(context) { });

  }
})(jQuery);
<|endoftext|>


<commit_before>const {Range, CompositeDisposable, Disposable} = require('atom');
const ResultView = require('./result-view');
const ListView = require('./list-view');
const etch = require('etch');
const $ = require('../dom-helpers');
const resizeDetector = require('element-resize-detector')({strategy: 'scroll'});

const reverseDirections = {
  left: 'right',
  right: 'left',
  up: 'down',
  down: 'up'
};

module.exports =
class ResultsView {
  constructor({model}) {
    this.model = model;
    this.pixelOverdraw = 100;
    this.selectedResultIndex = 0;
    this.selectedMatchIndex = -1;
    this.collapsedResultIndices = [];
    this.heightForSearchResult = this.heightForSearchResult.bind(this);

    etch.initialize(this);

    resizeDetector.listenTo(this.element, this.invalidateItemHeights.bind(this));
    this.element.addEventListener('mousedown', this.handleClick.bind(this));

    this.subscriptions = new CompositeDisposable(
      atom.config.observe('editor.fontFamily', this.fontFamilyChanged.bind(this)),
      this.model.onDidAddResult(this.addResult.bind(this)),
      this.model.onDidRemoveResult(this.removeResult.bind(this)),
      this.model.onDidClearSearchState(this.clear.bind(this)),
      this.model.getFindOptions().onDidChangeReplacePattern(() => etch.update(this)),

      atom.commands.add(this.element, {
        'core:move-up': this.moveUp.bind(this),
        'core:move-down': this.moveDown.bind(this),
        'core:move-left': this.collapseResult.bind(this),
        'core:move-right': this.expandResult.bind(this),
        'core:page-up': this.pageUp.bind(this),
        'core:page-down': this.pageDown.bind(this),
        'core:move-to-top': this.moveToTop.bind(this),
        'core:move-to-bottom': this.moveToBottom.bind(this),
        'core:confirm': this.confirmResult.bind(this),
        'core:copy': this.copyResult.bind(this),
        'find-and-replace:copy-path': this.copyPath.bind(this)
      })
    );
  }

  update() {}

  destroy() {
    this.subscriptions.dispose();
  }

  clear() {
    this.selectedResultIndex = -1;
    this.selectedMatchIndex = -1;
    etch.update(this);
  }

  render () {
    let regex = null, replacePattern = null;
    if (this.model.replacedPathCount == null) {
      regex = this.model.regex;
      replacePattern = this.model.getFindOptions().replacePattern;
    }

    return $.div(
      {className: 'results-view'},

      $.ol(
        {
          className: 'list-tree has-collapsable-children',
          style: {visibility: 'hidden', position: 'absolute'}
        },
        $(ResultView, {
          ref: 'dummyResultView',
          top: 0,
          bottom: Infinity,
          item: {
            filePath: 'fake-file-path',
            matches: [{
              range: [[0, 1], [0, 2]],
              lineTextOffset: 1,
              lineText: 'fake-line-text',
              matchText: 'fake-match-text',
              isSelected: false,
            }],
            matchHeight: 1,
            pathDetailsHeight: 1,
            isSelected: false,
            isExpanded: true,
            previewStyle: this.previewStyle
          }
        })
      ),

      this.pathDetailsHeight != null ?
        $(ListView, {
          className: 'list-tree has-collapsable-children focusable-panel',
          itemComponent: ResultView,
          heightForItem: this.heightForSearchResult,
          items: this.model.getPaths().map((filePath, i) => {
            const isSelected = (i === this.selectedResultIndex);
            const isExpanded = !this.collapsedResultIndices[i];
            const selectedMatchIndex = isSelected && this.selectedMatchIndex;
            return Object.assign({
              isSelected,
              isExpanded,
              selectedMatchIndex,
              previewStyle: this.previewStyle,
              pathDetailsHeight: this.pathDetailsHeight,
              matchHeight: this.matchHeight
            }, this.model.results[filePath]);
          }),
        }) :
        $.div()
    );
  }

  heightForSearchResult(searchResult, i) {
    if (this.collapsedResultIndices[i]) {
      return this.pathDetailsHeight;
    } else {
      return this.pathDetailsHeight + searchResult.matches.length * this.matchHeight;
    }
  }

  invalidateItemHeights() {
    const pathDetailsHeight = this.refs.dummyResultView.refs.pathDetails.offsetHeight;
    const matchHeight = this.refs.dummyResultView.element.getElementsByClassName('search-result')[0].offsetHeight;
    if (pathDetailsHeight !== this.pathDetailsHeight || matchHeight !== this.matchHeight) {
      this.pathDetailsHeight = pathDetailsHeight;
      this.matchHeight = matchHeight;
      etch.update(this);
    }
  }

  addResult() {
    etch.update(this);
  }

  removeResult({filePath}) {
    etch.update(this);
  }

  handleClick(event) {
    const clickedResultElement = event.target.closest('.path');
    const clickedMatchElement = event.target.closest('.search-result');
    if (event.ctrlKey || !clickedResultElement) return;

    const clickedFilePath = clickedResultElement.dataset.path;
    this.selectedResultIndex = this.model.getPaths().indexOf(clickedFilePath);
    const clickedResult = this.model.getResult(clickedFilePath)

    if (clickedMatchElement) {
      const clickedRange = clickedMatchElement.dataset.range;
      this.selectedMatchIndex = clickedResult.matches.findIndex(match =>
        Range.fromObject(match.range).toString() === clickedRange
      );
      this.confirmResult({pending: event.detail === 1});
    } else {
      this.selectedMatchIndex = -1;
      this.confirmResult();
    }

    etch.update(this);
  }

  selectFirstResult() {
    this.selectedResultIndex = 0;
    if (this.collapsedResultIndices[0]) {
      this.selectedMatchIndex = -1;
    } else {
      this.selectedMatchIndex = 0;
    }
    etch.update(this);
  }

  moveToTop() {
    this.element.scrollTop = 0;
    this.selectFirstResult();
  }

  moveToBottom() {
    this.selectedResultIndex = this.model.getPathCount() - 1;
    if (this.collapsedResultIndices[this.selectedResultIndex]) {
      this.selectedMatchIndex = -1;
    } else {
      this.selectedMatchIndex = this.model.getResultAt(this.selectedResultIndex).matches.length - 1;
    }
    this.element.scrollTop = this.element.scrollHeight - this.element.offsetHeight;
    etch.update(this);
  }

  pageUp() {
    const pathDetailsElement = this.element.querySelector('.path-details');
    const matchElement = this.element.querySelector('.path:not(.collapsed) .search-result');
    const pathDetailsHeight = pathDetailsElement ? pathDetailsElement.offsetHeight : 0;
    const matchHeight = matchElement ? matchElement.offsetHeight : 0;

    const position = this.positionOfSelectedResult(pathDetailsHeight, matchHeight);
    this.element.scrollTop -= this.element.offsetHeight;
    this.selectResultAtPosition(
      position - this.element.offsetHeight,
      pathDetailsHeight,
      matchHeight
    );
  }

  pageDown() {
    const pathDetailsElement = this.element.querySelector('.path-details');
    const matchElement = this.element.querySelector('.path:not(.collapsed) .search-result');
    const pathDetailsHeight = pathDetailsElement ? pathDetailsElement.offsetHeight : 0;
    const matchHeight = matchElement ? matchElement.offsetHeight : 0;

    const position = this.positionOfSelectedResult(pathDetailsHeight, matchHeight);
    const newScrollTop = this.element.scrollTop + this.element.offsetHeight;
    this.element.scrollTop = newScrollTop;
    this.selectResultAtPosition(
      position + this.element.offsetHeight,
      pathDetailsHeight,
      matchHeight
    );
  }

  positionOfSelectedResult(pathDetailsHeight, matchHeight) {
    let result = 0;
    for (let i = 0; i < this.selectedResultIndex; i++) {
      result += pathDetailsHeight;
      if (!this.collapsedResultIndices[i]) {
        result += this.model.getResultAt(i).matches.length * matchHeight
      }
    }

    if (this.selectedMatchIndex !== -1) {
      result += pathDetailsHeight + this.selectedMatchIndex * matchHeight;
    }

    return result;
  }

  selectResultAtPosition(position, pathDetailsHeight, matchHeight) {
    this.selectedResultIndex = this.model.getPathCount() - 1;
    this.selectedMatchIndex = this.collapsedResultIndices[this.selectedResultIndex] ?
      -1 : this.getResultAt(this.selectedResultIndex).matches.length - 1;

    let top = 0, bottom = 0;
    for (let i = 0; i < this.model.getPathCount(); i++) {
      bottom = top + pathDetailsHeight;
      if (bottom > position) {
        this.selectedResultIndex = i;
        this.selectedMatchIndex = -1;
        break;
      }

      top = bottom;

      if (!this.collapsedResultIndices[i]) {
        const matchesBottom = top + this.model.getResultAt(i).matches.length * matchHeight;
        if (matchesBottom > position) {
          this.selectedResultIndex = i;
          this.selectedMatchIndex = Math.round((position - top) / matchHeight);
          top += this.selectedMatchIndex * matchHeight;
          bottom = top + matchHeight;
          break;
        }

        top = matchesBottom;
      }
    }

    if (this.element.scrollTop > top) {
      this.element.scrollTop = top;
    }

    if (this.element.scrollTop < bottom - this.element.offsetHeight) {
      this.element.scrollTop = bottom - this.element.offsetHeight;
    }

    etch.update(this);
  }

  moveDown() {
    if (this.selectedResultIndex === -1) {
      this.selectFirstResult();
      return;
    }

    this.userMovedSelection = true;
    const selectedResult = this.model.getResultAt(this.selectedResultIndex);
    if (this.selectedMatchIndex < selectedResult.matches.length - 1 &&
        !this.collapsedResultIndices[this.selectedResultIndex]) {
      this.selectedMatchIndex++;
    } else if (this.selectedResultIndex < this.model.getPathCount() - 1) {
      this.selectedResultIndex++;
      this.selectedMatchIndex = -1;
    }

    this.scrollToSelectedMatch();
  }

  moveUp() {
    if (this.selectedResultIndex === -1) {
      this.selectFirstResult();
      return;
    }

    this.userMovedSelection = true;
    if (this.selectedMatchIndex >= 0) {
      this.selectedMatchIndex--;
    } else if (this.selectedResultIndex > 0) {
      this.selectedResultIndex--;
      const selectedResult = this.model.getResultAt(this.selectedResultIndex);
      if (this.collapsedResultIndices[this.selectedResultIndex]) {
        this.selectedMatchIndex = -1;
      } else {
        this.selectedMatchIndex = selectedResult.matches.length - 1;
      }
    }

    etch.update(this).then(this.scrollToSelectedMatch.bind(this));
  }

  expandResult() {
    if (this.selectedResultIndex !== -1 && this.selectedMatchIndex == -1) {
      this.collapsedResultIndices[this.selectedResultIndex] = false;
      this.selectedMatchIndex = 0;
    }
  }

  collapseResult() {
    if (this.selectedResultIndex !== -1) {
      this.collapsedResultIndices[this.selectedResultIndex] = true;
      this.selectedMatchIndex = -1;
    }
  }

  confirmResult({pending} = {}) {
    if (this.selectedResultIndex !== -1) {
      if (this.selectedMatchIndex !== -1) {
        const result = this.model.getResultAt(this.selectedResultIndex);
        const match = result.matches[this.selectedMatchIndex];
        atom.workspace
          .open(result.filePath, {
            pending,
            split: reverseDirections[atom.config.get('find-and-replace.projectSearchResultsPaneSplitDirection')]
          })
          .then(editor => {
            editor.setSelectedBufferRange(match.range, {autoscroll: true})
          });
      } else {
        this.collapsedResultIndices[this.selectedResultIndex] = !this.collapsedResultIndices[this.selectedResultIndex];
      }
    }
  }

  copyResult() {
    if (this.selectedResultIndex !== -1) {
      if (this.selectedMatchIndex !== -1) {
        const result = this.model.getResultAt(this.selectedResultIndex);
        const match = result.matches[this.selectedMatchIndex];
        atom.clipboard.write(match.lineText);
      }
    }
  }

  copyPath() {
    const {filePath} = this.model.getResultAt(this.selectedResultIndex);
    let [rootPath, relativePath] = atom.project.relativizePath(filePath);
    if (rootPath && atom.project.getDirectories().length > 1) {
      relativePath = path.join(path.basename(rootPath), relativePath);
    }
    atom.clipboard.write(relativePath);
  }

  expandAllResults() {
    this.collapsedResultIndices = new Array(this.model.getPathCount());
    this.collapsedResultIndices.fill(false);
    this.element.scrollTop = 0
    etch.update(this)
  }

  collapseAllResults() {
    this.collapsedResultIndices = new Array(this.model.getPaths().length);
    this.collapsedResultIndices.fill(true);
    this.element.scrollTop = 0
    etch.update(this)
  }

  scrollToSelectedMatch() {
    const resultElement = this.element.children[this.selectedResultIndex];
    if (!resultElement) return;

    let element;
    if (this.selectedMatchIndex === -1) {
      element = resultElement.querySelector('.path-details');
    } else {
      element = resultElement.querySelectorAll('.search-result')[this.selectedMatchIndex];
    }

    const top = element.offsetTop;
    const bottom = top + element.offsetHeight;

    if (bottom > this.element.scrollTop + this.element.offsetHeight) {
      this.element.scrollTop = bottom - this.element.offsetHeight;
    }

    if (top < this.element.scrollTop) {
      this.element.scrollTop = top;
    }
  }

  scrollToBottom() {
    this.element.scrollTop = this.element.scrollHeight;
  }

  scrollToTop() {
    this.element.scrollTop = 0;
  }

  selectedResultView() {
    const element = this.selectedElement()
    if (element) return this.resultViewsByElement.get(element)
  }

  fontFamilyChanged(fontFamily) {
    this.previewStyle = {fontFamily};
    etch.update(this);
  }
};
<commit_msg>Improve keyboard navigation and scrolling<commit_after>const {Range, CompositeDisposable, Disposable} = require('atom');
const ResultView = require('./result-view');
const ListView = require('./list-view');
const etch = require('etch');
const $ = require('../dom-helpers');
const resizeDetector = require('element-resize-detector')({strategy: 'scroll'});

const reverseDirections = {
  left: 'right',
  right: 'left',
  up: 'down',
  down: 'up'
};

module.exports =
class ResultsView {
  constructor({model}) {
    this.model = model;
    this.pixelOverdraw = 100;
    this.selectedResultIndex = 0;
    this.selectedMatchIndex = -1;
    this.collapsedResultIndices = [];
    this.heightForSearchResult = this.heightForSearchResult.bind(this);

    etch.initialize(this);

    resizeDetector.listenTo(this.element, this.invalidateItemHeights.bind(this));
    this.element.addEventListener('mousedown', this.handleClick.bind(this));

    this.subscriptions = new CompositeDisposable(
      atom.config.observe('editor.fontFamily', this.fontFamilyChanged.bind(this)),
      this.model.onDidAddResult(this.didAddResult.bind(this)),
      this.model.onDidRemoveResult(this.didRemoveResult.bind(this)),
      this.model.onDidClearSearchState(this.didClearSearchState.bind(this)),
      this.model.getFindOptions().onDidChangeReplacePattern(() => etch.update(this)),

      atom.commands.add(this.element, {
        'core:move-up': this.moveUp.bind(this),
        'core:move-down': this.moveDown.bind(this),
        'core:move-left': this.collapseResult.bind(this),
        'core:move-right': this.expandResult.bind(this),
        'core:page-up': this.pageUp.bind(this),
        'core:page-down': this.pageDown.bind(this),
        'core:move-to-top': this.moveToTop.bind(this),
        'core:move-to-bottom': this.moveToBottom.bind(this),
        'core:confirm': this.confirmResult.bind(this),
        'core:copy': this.copyResult.bind(this),
        'find-and-replace:copy-path': this.copyPath.bind(this)
      })
    );
  }

  update() {}

  destroy() {
    this.subscriptions.dispose();
  }

  didClearSearchState() {
    this.selectedResultIndex = 0;
    this.selectedMatchIndex = -1;
    etch.update(this);
  }

  render () {
    let regex = null, replacePattern = null;
    if (this.model.replacedPathCount == null) {
      regex = this.model.regex;
      replacePattern = this.model.getFindOptions().replacePattern;
    }

    return $.div(
      {className: 'results-view focusable-panel', tabIndex: '-1'},

      $.ol(
        {
          className: 'list-tree has-collapsable-children',
          style: {visibility: 'hidden', position: 'absolute'}
        },
        $(ResultView, {
          ref: 'dummyResultView',
          top: 0,
          bottom: Infinity,
          item: {
            filePath: 'fake-file-path',
            matches: [{
              range: [[0, 1], [0, 2]],
              lineTextOffset: 1,
              lineText: 'fake-line-text',
              matchText: 'fake-match-text',
              isSelected: false,
            }],
            matchHeight: 1,
            pathDetailsHeight: 1,
            isSelected: false,
            isExpanded: true,
            previewStyle: this.previewStyle
          }
        })
      ),

      this.pathDetailsHeight != null ?
        $(ListView, {
          ref: 'listView',
          className: 'list-tree has-collapsable-children',
          itemComponent: ResultView,
          heightForItem: this.heightForSearchResult,
          items: this.model.getPaths().map((filePath, i) => {
            const isSelected = (i === this.selectedResultIndex);
            const isExpanded = !this.collapsedResultIndices[i];
            const selectedMatchIndex = isSelected && this.selectedMatchIndex;
            return Object.assign({
              isSelected,
              isExpanded,
              selectedMatchIndex,
              previewStyle: this.previewStyle,
              pathDetailsHeight: this.pathDetailsHeight,
              matchHeight: this.matchHeight
            }, this.model.results[filePath]);
          }),
        }) :
        $.div()
    );
  }

  heightForSearchResult(searchResult, i) {
    if (this.collapsedResultIndices[i]) {
      return this.pathDetailsHeight;
    } else {
      return this.pathDetailsHeight + searchResult.matches.length * this.matchHeight;
    }
  }

  invalidateItemHeights() {
    const pathDetailsHeight = this.refs.dummyResultView.refs.pathDetails.offsetHeight;
    const matchHeight = this.refs.dummyResultView.element.getElementsByClassName('search-result')[0].offsetHeight;
    if (pathDetailsHeight !== this.pathDetailsHeight || matchHeight !== this.matchHeight) {
      this.pathDetailsHeight = pathDetailsHeight;
      this.matchHeight = matchHeight;
      etch.update(this);
    }
  }

  didAddResult() {
    etch.update(this);
  }

  didRemoveResult() {
    etch.update(this);
  }

  handleClick(event) {
    const clickedResultElement = event.target.closest('.path');
    const clickedMatchElement = event.target.closest('.search-result');
    if (event.ctrlKey || !clickedResultElement) return;

    const clickedFilePath = clickedResultElement.dataset.path;
    this.selectedResultIndex = this.model.getPaths().indexOf(clickedFilePath);
    const clickedResult = this.model.getResult(clickedFilePath)

    if (clickedMatchElement) {
      const clickedRange = clickedMatchElement.dataset.range;
      this.selectedMatchIndex = clickedResult.matches.findIndex(match =>
        Range.fromObject(match.range).toString() === clickedRange
      );
      this.confirmResult({pending: event.detail === 1});
    } else {
      this.selectedMatchIndex = -1;
      this.confirmResult();
    }

    etch.update(this);
  }

  selectFirstResult() {
    this.selectedResultIndex = 0;
    if (this.collapsedResultIndices[0]) {
      this.selectedMatchIndex = -1;
    } else {
      this.selectedMatchIndex = 0;
    }

    this.scrollToSelectedMatch();
    etch.update(this);
  }

  moveToTop() {
    this.selectFirstResult();
  }

  moveToBottom() {
    this.selectedResultIndex = this.model.getPathCount() - 1;
    if (this.collapsedResultIndices[this.selectedResultIndex]) {
      this.selectedMatchIndex = -1;
    } else {
      this.selectedMatchIndex = this.model.getResultAt(this.selectedResultIndex).matches.length - 1;
    }

    this.scrollToSelectedMatch();
    etch.update(this);
  }

  pageUp() {
    if (this.refs.listView) {
      const position = this.positionOfSelectedResult(this.pathDetailsHeight, this.matchHeight);

      this.setScrollTop(this.getScrollTop() - this.refs.listView.element.clientHeight);
      this.selectResultAtPosition(
        position - this.refs.listView.element.clientHeight,
        pathDetailsHeight,
        matchHeight
      );
    }
  }

  pageDown() {
    if (this.refs.listView) {
      const position = this.positionOfSelectedResult(this.pathDetailsHeight, this.matchHeight);
      const newScrollTop = this.getScrollTop() + this.refs.listView.element.clientHeight;

      this.setScrollTop(newScrollTop);
      this.selectResultAtPosition(
        position + this.refs.listView.element.clientHeight,
        pathDetailsHeight,
        matchHeight
      );
    }
  }

  positionOfSelectedResult(pathDetailsHeight, matchHeight) {
    let result = 0;
    for (let i = 0; i < this.selectedResultIndex; i++) {
      result += pathDetailsHeight;
      if (!this.collapsedResultIndices[i]) {
        result += this.model.getResultAt(i).matches.length * matchHeight
      }
    }

    if (this.selectedMatchIndex !== -1) {
      result += pathDetailsHeight + this.selectedMatchIndex * matchHeight;
    }

    return result;
  }

  selectResultAtPosition(position, pathDetailsHeight, matchHeight) {
    if (this.refs.listView) {
      this.selectedResultIndex = this.model.getPathCount() - 1;
      this.selectedMatchIndex = this.collapsedResultIndices[this.selectedResultIndex] ?
        -1 : this.getResultAt(this.selectedResultIndex).matches.length - 1;

      let top = 0, bottom = 0;
      for (let i = 0; i < this.model.getPathCount(); i++) {
        bottom = top + pathDetailsHeight;
        if (bottom > position) {
          this.selectedResultIndex = i;
          this.selectedMatchIndex = -1;
          break;
        }

        top = bottom;

        if (!this.collapsedResultIndices[i]) {
          const matchesBottom = top + this.model.getResultAt(i).matches.length * matchHeight;
          if (matchesBottom > position) {
            this.selectedResultIndex = i;
            this.selectedMatchIndex = Math.round((position - top) / matchHeight);
            top += this.selectedMatchIndex * matchHeight;
            bottom = top + matchHeight;
            break;
          }

          top = matchesBottom;
        }
      }

      if (this.getScrollTop() > top) {
        this.setScrollTop(top);
      }

      if (this.getScrollTop() < bottom - this.refs.listView.clientHeight) {
        this.setScrollTop(bottom - this.refs.listView.clientHeight);
      }

      etch.update(this);
    }
  }

  moveDown() {
    if (this.selectedResultIndex === -1) {
      this.selectFirstResult();
      return;
    }

    const selectedResult = this.model.getResultAt(this.selectedResultIndex);
    if (this.selectedMatchIndex < selectedResult.matches.length - 1 &&
        !this.collapsedResultIndices[this.selectedResultIndex]) {
      this.selectedMatchIndex++;
    } else if (this.selectedResultIndex < this.model.getPathCount() - 1) {
      this.selectedResultIndex++;
      this.selectedMatchIndex = -1;
    }

    this.scrollToSelectedMatch();
    etch.update(this);
  }

  moveUp() {
    if (this.selectedResultIndex === -1) {
      this.selectFirstResult();
      return;
    }

    if (this.selectedMatchIndex >= 0) {
      this.selectedMatchIndex--;
    } else if (this.selectedResultIndex > 0) {
      this.selectedResultIndex--;
      const selectedResult = this.model.getResultAt(this.selectedResultIndex);
      if (this.collapsedResultIndices[this.selectedResultIndex]) {
        this.selectedMatchIndex = -1;
      } else {
        this.selectedMatchIndex = selectedResult.matches.length - 1;
      }
    }

    this.scrollToSelectedMatch();
    etch.update(this);
  }

  expandResult() {
    if (this.selectedResultIndex !== -1 && this.selectedMatchIndex == -1) {
      this.collapsedResultIndices[this.selectedResultIndex] = false;
      this.selectedMatchIndex = 0;
      etch.update(this);
    }
  }

  collapseResult() {
    if (this.selectedResultIndex !== -1) {
      this.collapsedResultIndices[this.selectedResultIndex] = true;
      this.selectedMatchIndex = -1;
      etch.update(this);
    }
  }

  confirmResult({pending} = {}) {
    if (this.selectedResultIndex !== -1) {
      if (this.selectedMatchIndex !== -1) {
        const result = this.model.getResultAt(this.selectedResultIndex);
        const match = result.matches[this.selectedMatchIndex];
        atom.workspace
          .open(result.filePath, {
            pending,
            split: reverseDirections[atom.config.get('find-and-replace.projectSearchResultsPaneSplitDirection')]
          })
          .then(editor => {
            editor.setSelectedBufferRange(match.range, {autoscroll: true})
          });
      } else {
        this.collapsedResultIndices[this.selectedResultIndex] = !this.collapsedResultIndices[this.selectedResultIndex];
      }
    }
  }

  copyResult() {
    if (this.selectedResultIndex !== -1) {
      if (this.selectedMatchIndex !== -1) {
        const result = this.model.getResultAt(this.selectedResultIndex);
        const match = result.matches[this.selectedMatchIndex];
        atom.clipboard.write(match.lineText);
      }
    }
  }

  copyPath() {
    const {filePath} = this.model.getResultAt(this.selectedResultIndex);
    let [rootPath, relativePath] = atom.project.relativizePath(filePath);
    if (rootPath && atom.project.getDirectories().length > 1) {
      relativePath = path.join(path.basename(rootPath), relativePath);
    }
    atom.clipboard.write(relativePath);
  }

  expandAllResults() {
    this.collapsedResultIndices = new Array(this.model.getPathCount());
    this.collapsedResultIndices.fill(false);
    this.setScrollTop(0);
    etch.update(this);
  }

  collapseAllResults() {
    this.collapsedResultIndices = new Array(this.model.getPaths().length);
    this.collapsedResultIndices.fill(true);
    this.setScrollTop(0);
    etch.update(this);
  }

  scrollToSelectedMatch() {
    if (this.refs.listView) {
      const top = this.positionOfSelectedResult(this.pathDetailsHeight, this.matchHeight);
      const bottom = top + this.matchHeight;

      if (bottom > this.getScrollTop() + this.refs.listView.element.clientHeight) {
        this.setScrollTop(bottom - this.refs.listView.element.clientHeight);
      } else if (top < this.getScrollTop()) {
        this.setScrollTop(top);
      }
    }
  }

  scrollToBottom() {
    this.setScrollTop(this.getScrollHeight());
  }

  scrollToTop() {
    this.setScrollTop(0);
  }

  setScrollTop (scrollTop) {
    if (this.refs.listView) {
      this.refs.listView.element.scrollTop = scrollTop;
    }
  }

  getScrollTop () {
    return this.refs.listView ? this.refs.listView.element.scrollTop : 0;
  }

  getScrollHeight () {
    return this.refs.listView ? this.refs.listView.element.scrollHeight : 0;
  }

  selectedResultView() {
    const element = this.selectedElement()
    if (element) return this.resultViewsByElement.get(element)
  }

  fontFamilyChanged(fontFamily) {
    this.previewStyle = {fontFamily};
    etch.update(this);
  }
};
<|endoftext|>


<commit_before>class animator {
  //using Web Animations API for now....will include a polyfill for unsupported browsers.
  //this provides a clean structure for all the animations....doing rotate for the demo.
  animateInterpolate(message) {
    let animationValues = message.animation;
    let keyframes = [];
    if (animationValues.animatedProperty) {
      switch (true) {
        case /opacity/.test(animationValues.animatedProperty):
        console.log(animationValues.value, animationValues.toValue)

          keyframes = [
            { opacity: animationValues.value },
            { opacity: animationValues.toValue },
          ];
          break;
        case /rotate|rotate[XYZ]/.test(animationValues.animatedProperty):
          keyframes = [
            {
              transform: `${animationValues.animatedProperty}(${
                animationValues.value
              }deg)`,
            },
            {
              transform: `${animationValues.animatedProperty}(${
                animationValues.toValue
              }deg)`,
            },
          ];
          break;
        //will need to include other cases for height,width, x, y transformations
      }
    } else {
      //default to z animations A.K.A rotate
      keyframes = [
        { transform: `rotateZ(${animationValues.value}deg)` },
        { transform: `rotateZ(${animationValues.toValue}deg)` },
      ];
    }

    let animation = document.getElementById(message.guid).animate(keyframes, {
      duration: animationValues.duration,
      iterations: 1,
    });
    animation.onfinish = () => {
      SyrEvents.emit({
        type: 'animationComplete',
        guid: message.guid,
        animation: message.animation,
      });
    };
  }

  animateComponentXY(message) {

    const animationValues = message.animation;

    const x = `${animationValues.x}px` || 0;
    const x2 = `${animationValues.x2}px` || 0;
    const y = `${animationValues.y}px` || 0;
    const y2 = `${animationValues.y2}px` || 0;

    let destinationY = (y > y2) ? y2 - y : y2 + y;
    let destinationX = (x > x2) ? x2 - y : x2 + x;

    const element = document.getElementById(message.guid);

    const animation = element.animate(
      [
        { transform: `translateX(${x}) translateY(${y})` },
        { transform: `translateX(${x2}) translateY(${y2})` },
      ],
      {
        duration: animationValues.duration,
        iterations: 1,
      }
    );

    animation.onfinish = () => {
      //setting the final postion of the element as the final XnY from the animation.
      element.style['top'] = y2 + 'px';
      element.style['left'] = x2 + 'px';
      SyrEvents.emit({
        type: 'animationComplete',
        guid: message.guid,
        animation: message.animation,
      });
    };
  }

  animate(message) {
    message.animation.value !== undefined
      ? this.animateInterpolate(message)
      : this.animateComponentXY(message);
  }
}

const Animator = new animator();

export { Animator };
<commit_msg>Including height animations  and fixing XY animations<commit_after>class animator {
  //using Web Animations API for now....will include a polyfill for unsupported browsers.
  //this provides a clean structure for all the animations....doing rotate for the demo.
  animateInterpolate(message) {
    let animationValues = message.animation;
    let keyframes = [];
    const element = document.getElementById(message.guid);
    if (animationValues.animatedProperty) {
      switch (true) {
        case /opacity/.test(animationValues.animatedProperty):

          keyframes = [
            { opacity: animationValues.value },
            { opacity: animationValues.toValue },
          ];
          break;
          case /height/.test(animationValues.animatedProperty):
          let fromValue = element.style.height;
          let toValue = animationValues.toValue !== 0 ? `${animationValues.toValue}px` : 0;
            keyframes = [
              { height: fromValue },
              { height: toValue },
            ];
            break;
        case /rotate|rotate[XYZ]/.test(animationValues.animatedProperty):
          keyframes = [
            {
              transform: `${animationValues.animatedProperty}(${
                animationValues.value
              }deg)`,
            },
            {
              transform: `${animationValues.animatedProperty}(${
                animationValues.toValue
              }deg)`,
            },
          ];
          break;
        //will need to include other cases for height,width, x, y transformations
      }
    } else {
      //default to z animations A.K.A rotate
      keyframes = [
        { transform: `rotateZ(${animationValues.value}deg)` },
        { transform: `rotateZ(${animationValues.toValue}deg)` },
      ];
    }

    let animation = element.animate(keyframes, {
      duration: animationValues.duration,
      iterations: 1,
    });
    animation.onfinish = () => {
      if(animationValues.animatedProperty == 'height' ||
         animationValues.animatedProperty == 'width'
       ) {
         element.style.height = `${animationValues.toValue}px`;
       }
      SyrEvents.emit({
        type: 'animationComplete',
        guid: message.guid,
        animation: message.animation,
      });
    };
  }

  animateComponentXY(message) {

    const animationValues = message.animation;

    const x = `${animationValues.x}px` || 0;
    const x2 = `${animationValues.x2}px` || 0;
    const y = `${animationValues.y}px` || 0;
    const y2 = `${animationValues.y2}px` || 0;

    // let destinationY = (y > y2) ? y2 - y : y2 + y;
    // let destinationX = (x > x2) ? x2 - y : x2 + x;

    const element = document.getElementById(message.guid);

    const animation = element.animate(
      [
        { transform: `translateX(${x}) translateY(${y})` },
        { transform: `translateX(${x2}) translateY(${y2})` },
      ],
      {
        duration: animationValues.duration,
        iterations: 1,
      }
    );

    animation.onfinish = () => {
      //setting the final postion of the element as the final XnY from the animation.
      element.style['top'] = y2 + 'px';
      element.style['left'] = x2 + 'px';
      SyrEvents.emit({
        type: 'animationComplete',
        guid: message.guid,
        animation: message.animation,
      });
    };
  }

  animate(message) {
    message.animation.value !== undefined
      ? this.animateInterpolate(message)
      : this.animateComponentXY(message);
  }
}

const Animator = new animator();

export { Animator };
<|endoftext|>


<commit_before>require('colors')

function BaseColorReporter () {
  this.USE_COLORS = true

  this.LOG_SINGLE_BROWSER = '%s: ' + '%s'.cyan + '\n'
  this.LOG_MULTI_BROWSER = '%s %s: ' + '%s'.cyan + '\n'

  this.SPEC_FAILURE = '%s %s FAILED'.red + '\n'
  this.SPEC_SLOW = '%s SLOW %s: %s'.yellow + '\n'
  this.ERROR = '%s ERROR'.red + '\n'

  this.FINISHED_ERROR = ' ERROR'.red
  this.FINISHED_SUCCESS = ' SUCCESS'.green
  this.FINISHED_DISCONNECTED = ' DISCONNECTED'.red

  this.X_FAILED = ' (%d FAILED)'.red

  this.TOTAL_SUCCESS = 'TOTAL: %d SUCCESS'.green + '\n'
  this.TOTAL_FAILED = 'TOTAL: %d FAILED, %d SUCCESS'.red + '\n'
}

// PUBLISH
module.exports = BaseColorReporter
<commit_msg>refactor: use colors/safe (#3548)<commit_after>const { red, yellow, green, cyan } = require('colors/safe')

function BaseColorReporter () {
  this.USE_COLORS = true

  this.LOG_SINGLE_BROWSER = '%s: ' + cyan('%s') + '\n'
  this.LOG_MULTI_BROWSER = '%s %s: ' + cyan('%s') + '\n'

  this.SPEC_FAILURE = red('%s %s FAILED') + '\n'
  this.SPEC_SLOW = yellow('%s SLOW %s: %s') + '\n'
  this.ERROR = red('%s ERROR') + '\n'

  this.FINISHED_ERROR = red(' ERROR')
  this.FINISHED_SUCCESS = green(' SUCCESS')
  this.FINISHED_DISCONNECTED = red(' DISCONNECTED')

  this.X_FAILED = red(' (%d FAILED)')

  this.TOTAL_SUCCESS = green('TOTAL: %d SUCCESS') + '\n'
  this.TOTAL_FAILED = red('TOTAL: %d FAILED, %d SUCCESS') + '\n'
}

// PUBLISH
module.exports = BaseColorReporter
<|endoftext|>