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

	var accessibleAutocompleteProvider = [function () {
		var defaultOptions = {
			template: '<ul class="rs-autocomplete" role="listbox" aria-expanded="{{showSuggestions}}" ng-show="showSuggestions" id="{{suggestionsListId}}"> ' +
				'<li ng-repeat="suggestion in suggestions" ' +
				'    id="{{suggestionsListId + \'-\' + $index}}" ' +
				'    role="option" aria-selected="{{$index == selectedSuggestionIndex}}" ' +
				'    ng-bind="suggestion" ' +
				'    ng-click="selectSuggestion(suggestion)" ' +
				'></li>' +
				'</ul>',
			templateUrl: null,
			minimumLength: 3,
			delay: 100
		};

		this.setDefaultOptions = function(options) {
			angular.extend(defaultOptions, options);
		};

		var provider = this;

		this.$get = function() {
			return defaultOptions;
		};
	}];

	var accessibleAutocompleteDirective = ['$http', '$compile', '$templateCache', '$q', 'accessibleAutocomplete', 'accessibleAutocompleteKeyProcessor', 
								  function ($http, $compile, $templateCache, $q, accessibleAutocomplete, accessibleAutocompleteKeyProcessor) {

		var stripHttpData = function(resp) {
			return resp.data;
		};

		return {
			restrict: 'A',
			scope: {
				selectedHandler: '&accessibleAutocompleteSelected',
				suggestionsSelector: '&accessibleAutocomplete',
				templateUrl: '@accessibleAutocompleteTemplateUrl',
				minimumLength: '&accessibleAutocompleteMinimumLength'
			},
			link: function(scope, element, attrs) {
				// TODO: Apply aria attributes if missing

				var ariaAutocomplete = element.attr('aria-autocomplete'),
					ariaRole = element.attr('role');

				if (!ariaAutocomplete) {
					ariaAutocomplete = (ariaRole == 'textbox') ? 'inline' : 'list';
					element.attr('aria-autocomplete', ariaAutocomplete);
				}

				if (!attrs.role) {
					ariaRole = (ariaAutocomplete == 'list' || ariaAutocomplete == 'both')
						? 'combobox' : 'textbox';

					element.attr('role', ariaRole);
				}

				// TODO: Accessible 'activation'
				element.on('keydown', function(event) {
					scope.$apply(function() {
						if (accessibleAutocompleteKeyProcessor.isEscape(event)) {
							scope.hideSuggestions();
							scope.setSelectionSuggestionIndex(-1);
							event.preventDefault();
						} else if (accessibleAutocompleteKeyProcessor.isDown(event)) {
							scope.moveSelectionSuggestionIndex(1);
							event.preventDefault();
						} else if (accessibleAutocompleteKeyProcessor.isUp(event)) {
							scope.moveSelectionSuggestionIndex(-1);
							event.preventDefault();
						} else if (accessibleAutocompleteKeyProcessor.isTab(event)) {
							if (scope.showSuggestions && scope.selectedSuggestionIndex != -1) {
								scope.selectSuggestion(scope.selectedSuggestion);

								event.preventDefault();
							}
						} else if (accessibleAutocompleteKeyProcessor.isEnter(event)) {
							if (scope.showSuggestions) {
								scope.selectSuggestion(scope.selectedSuggestion);

								event.preventDefault();
							}
						}
					});
				});

				element.on('keyup input', function() {
					scope.$apply(function() {
						if (element.val() != scope.textInput + scope.textInputSuffix)
							scope.textChanged(element.val());
					});
				});

				if (ariaAutocomplete == 'list' || ariaAutocomplete == 'both') {

					var templatePromise = scope.options.templateUrl ?
						$http.get(scope.options.templateUrl, {cache: $templateCache}).then(stripHttpData) :
						$q.when(scope.options.template);

					templatePromise.then(function(template) {
						scope.suggestionsListId = 'accessible-autocomplete-' + (new Date()).getTime();
						scope.suggestionsList = $compile(template)(scope);

						element.after(scope.suggestionsList);

						element.attr('aria-owns', scope.suggestionsListId);
					}, function(err) {
						// TODO: err
						throw err;
					});
				}

				scope.$watch('selectedSuggestionIndex', function(newValue) {
					if (newValue == -1) {
						element.attr('aria-activedescendant', null);
					} else {
						element.attr('aria-activedescendant', scope.getSuggestionId(newValue));
					}
				});

				scope.$watch('isLoadingSuggestions', function(newValue) {
					element.attr('aria-busy', newValue === true);<commit_msg>Suggestions are now hidden when the input loses focus<commit_after>(function() {
	'use strict';

	var accessibleAutocompleteProvider = [function () {
		var defaultOptions = {
			template: '<ul class="rs-autocomplete" role="listbox" aria-expanded="{{showSuggestions}}" ng-show="showSuggestions" id="{{suggestionsListId}}"> ' +
				'<li ng-repeat="suggestion in suggestions" ' +
				'    id="{{suggestionsListId + \'-\' + $index}}" ' +
				'    role="option" aria-selected="{{$index == selectedSuggestionIndex}}" ' +
				'    ng-bind="suggestion" ' +
				'    ng-click="selectSuggestion(suggestion)" ' +
				'></li>' +
				'</ul>',
			templateUrl: null,
			minimumLength: 3,
			delay: 100
		};

		this.setDefaultOptions = function(options) {
			angular.extend(defaultOptions, options);
		};

		var provider = this;

		this.$get = function() {
			return defaultOptions;
		};
	}];

	var accessibleAutocompleteDirective = ['$http', '$compile', '$templateCache', '$q', 'accessibleAutocomplete', 'accessibleAutocompleteKeyProcessor', '$timeout',
								  function ($http, $compile, $templateCache, $q, accessibleAutocomplete, accessibleAutocompleteKeyProcessor, $timeout) {

		var stripHttpData = function(resp) {
			return resp.data;
		};

		function containsElement(domParent, domElement) {
			while(domElement) {
				if (domParent === domElement)
					return true;

				domElement = domElement.parentNode;
			}

			return false;
		}

		return {
			restrict: 'A',
			scope: {
				selectedHandler: '&accessibleAutocompleteSelected',
				suggestionsSelector: '&accessibleAutocomplete',
				templateUrl: '@accessibleAutocompleteTemplateUrl',
				minimumLength: '&accessibleAutocompleteMinimumLength'
			},
			link: function(scope, element, attrs) {

				var ariaAutocomplete = element.attr('aria-autocomplete'),
					ariaRole = element.attr('role');

				if (!ariaAutocomplete) {
					ariaAutocomplete = (ariaRole == 'textbox') ? 'inline' : 'list';
					element.attr('aria-autocomplete', ariaAutocomplete);
				}

				if (!attrs.role) {
					ariaRole = (ariaAutocomplete == 'list' || ariaAutocomplete == 'both')
						? 'combobox' : 'textbox';

					element.attr('role', ariaRole);
				}

				var knownBlurTarget = false;

				element.on('focus', function() {
					knownBlurTarget = false
				});

				element.on('blur', function(event) {
					if (!knownBlurTarget) {
						scope.$apply(function() {
							scope.showSuggestions = false;
						});
					}
				});

				element.on('keydown', function(event) {
					scope.$apply(function() {
						if (accessibleAutocompleteKeyProcessor.isEscape(event)) {
							scope.hideSuggestions();
							scope.setSelectionSuggestionIndex(-1);
							event.preventDefault();
						} else if (accessibleAutocompleteKeyProcessor.isDown(event)) {
							scope.moveSelectionSuggestionIndex(1);
							event.preventDefault();
						} else if (accessibleAutocompleteKeyProcessor.isUp(event)) {
							scope.moveSelectionSuggestionIndex(-1);
							event.preventDefault();
						} else if (accessibleAutocompleteKeyProcessor.isTab(event)) {
							if (scope.showSuggestions && scope.selectedSuggestionIndex != -1) {
								scope.selectSuggestion(scope.selectedSuggestion);

								event.preventDefault();
							}
						} else if (accessibleAutocompleteKeyProcessor.isEnter(event)) {
							if (scope.showSuggestions) {
								scope.selectSuggestion(scope.selectedSuggestion);

								event.preventDefault();
							}
						}
					});
				});

				element.on('keyup input', function() {
					scope.$apply(function() {
						if (element.val() != scope.textInput + scope.textInputSuffix)
							scope.textChanged(element.val());
					});
				});

				if (ariaAutocomplete == 'list' || ariaAutocomplete == 'both') {

					var templatePromise = scope.options.templateUrl ?
						$http.get(scope.options.templateUrl, {cache: $templateCache}).then(stripHttpData) :
						$q.when(scope.options.template);

					templatePromise.then(function(template) {
						scope.suggestionsListId = 'accessible-autocomplete-' + (new Date()).getTime();
						scope.suggestionsList = $compile(template)(scope);

						scope.suggestionsList.on('mousedown touchdown', function() {
							knownBlurTarget = true;
						});

						element.after(scope.suggestionsList);

						element.attr('aria-owns', scope.suggestionsListId);
					}, function(err) {
						// TODO: err
						throw err;
					});
				}

				scope.$watch('selectedSuggestionIndex', function(newValue) {
					if (newValue == -1) {
						element.attr('aria-activedescendant', null);
					} else {
						element.attr('aria-activedescendant', scope.getSuggestionId(newValue));
					}
				});

				scope.$watch('isLoadingSuggestions', function(newValue) {
					element.attr('aria-busy', newValue === true);
{'fraction_non_alphanumeric': 0.14739304812834225, 'fraction_numerical': 0.002005347593582888, 'mean_word_length': 3.4885, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4013586', 'n_tokens_mistral': 3590, 'n_tokens_neox': 2572, 'n_words': 432}