<commit_before>/* ==================================================================
 AngularJS Datatype Editor - List
 A directive to pick a new value from a list of values

 Usage:
 <div ade-list='{id":"1234"}' ng-model="data">{{data}}</div>

 Config:
 "id" will be used in messages broadcast to the app on state changes.

 Messages:
 name: ADE-start
 data: id from config

 name: ADE-finish
 data: {id from config, old value, new value, exit value}

 ------------------------------------------------------------------*/
adeModule.directive('adeList', ['ADE', '$compile', '$rootScope', function(ADE, $compile, $rootScope) {
	return {
		require: '?ngModel', //optional dependency for ngModel
		restrict: 'A', //Attribute declaration eg: <div ade-list=""></div>

		//The link step (after compile)
		link: function($scope, element, attrs, controller) {
			var options = {}; //The passed in options to the directive.
			var editing = false; //are we in edit mode or not
			var input = null; //a reference to the input DOM object
			var value = "";
			var oldValue = "";
			var exit = 0; //0=click, 1=tab, -1= shift tab, 2=return, -2=shift return, 3=esc. controls if you exited the field so you can focus the next field if appropriate

			//whenever the model changes, we get called so we can update our value
			if (controller) {
				controller.$render = function() {
					oldValue = value = controller.$modelValue;
					if (value == undefined || value == null) value = "";
					return controller.$viewValue;
				};
			}

			//called once the edit is done, so we can save the new data and remove edit mode
			var saveEdit = function(exited) {
				oldValue = value;
				exit = exited;

                console.log("saveEdit");
				if (exited != 3) { //don't save value on esc
					value = input.data().select2.data();
					var v="";
					if (angular.isArray(value) && value.length > 0) {

						angular.forEach(value, function(val, key) {
							val = (key < value.length-1) ? val.text +"," : val.text;
							v += val;
						});
						value = v;
					} else if (angular.isObject(value) && value.text !== "") {
						value = value.text;
					} else {
						value = (value) ? value.text : "";
					}

					controller.$setViewValue(value);
				}

                if (exited !== 0) {
                    if (v) element[0].innerHTML = v;
                    element.show();
                    input.select2('destroy'); //TODO: resolve console error when destroying this the second time for the same input
                    input.remove();
                    editing = false;
                } else if (exited == 0) {
                    setTimeout(function() {
                        input.select2('open');
                    });
                }

				ADE.done(options, oldValue, value, exit);

				if (!$scope.$$phase) {
					return $scope.$apply(); //This is necessary to get the model to match the value of the input
				}
			};

            $("body").bind("keyup", function(e) {
                $(document).find("div.select2-drop-active").each(function () {
                    if (e.keyCode == 27) { //esc
                        e.preventDefault();
                        e.stopPropagation();
                        var activeContainer = $(document).find('.select2-container-active');
                        var activeInput = activeContainer.next();
                        activeContainer.remove();
                        activeInput.remove();
                        element.show();
                        editing=false;
                    }
                });
            });

			//handles clicks on the read version of the data
			element.bind('click', function() {
				if (editing) return;
				editing = true;
				exit = 0;

				ADE.begin(options);
				element.hide();

				var multi = '';
				var placeholder = '';

				if (options.multiple) {
					multi = 'multiple="multiple"';
				} else {
					placeholder = ',placeholder:\'List...\'';
				}
				
				var query = '';
				if(options.query) query = ",query:" + options.query; //the user's query function for providing the list data
				var passthru = '';
				if(options.passthru) passthru = ",passthru:'" + options.passthru + "'"; //data that is passed through to the query function

				$compile('<input type="hidden" ui-select2={width:\'resolve\',allowClear:true,openOnEnter:false,allowAddNewValues:true'+query+passthru+',initSelection:selection'+placeholder+'} ' + multi + ' />')($scope)
					.insertAfter(element);
				input = element.next('input');

				var data = [], stringData=value;
				var cleanValue = (value) ? value.split(',') : [];

				angular.forEach(cleanValue, function(value, key) {
					$scope.listOptions.map(function(v,i) {
						if (value === v) {
							data.push({'id':i,'text':v });
						}
					});
				});

				if (!options.multiple) data = data[0];

				setTimeout(function() {
					input.select2("data", data);
					input.select2("open");
				});

				input.on("change", function(e) {
					if (!options.multiple) {
                        saveEdit();
                    } else {
                        console.log("calling saveEdit");
                        saveEdit(0);
                    }
				});

				//make sure we aren't already digesting/applying before we apply the changes
				if (!$scope.$$phase) {
					return $scope.$apply(); //This is necessary to get the model to match the value of the input
				}
			});

			// Watches for changes to the element
			// TODO: understand why I have to return the observer and why the observer returns element
			return attrs.$observe('adeList', function(settings) { //settings is the contents of the ade-list="" string
				options = ADE.parseSettings(settings, {
					multiple: false
				});
				return element;
			});
		}
	};
}]);

// Taken from Angular-UI and modified for our uses
// https://github.com/angular-ui/angular-ui
adeModule.directive('uiSelect2', ['$http', function($http) {
	var options = {};

	return {
		require: '?ngModel',
		compile: function(tElm, tAttrs) {
			var watch,<commit_msg>Issue #25: added closeOnSelect option<commit_after>/* ==================================================================
 AngularJS Datatype Editor - List
 A directive to pick a new value from a list of values

 Usage:
 <div ade-list='{id":"1234"}' ng-model="data">{{data}}</div>

 Config:
 "id" will be used in messages broadcast to the app on state changes.

 Messages:
 name: ADE-start
 data: id from config

 name: ADE-finish
 data: {id from config, old value, new value, exit value}

 ------------------------------------------------------------------*/
adeModule.directive('adeList', ['ADE', '$compile', '$rootScope', function(ADE, $compile, $rootScope) {
	return {
		require: '?ngModel', //optional dependency for ngModel
		restrict: 'A', //Attribute declaration eg: <div ade-list=""></div>

		//The link step (after compile)
		link: function($scope, element, attrs, controller) {
			var options = {}; //The passed in options to the directive.
			var editing = false; //are we in edit mode or not
			var input = null; //a reference to the input DOM object
			var value = "";
			var oldValue = "";
			var exit = 0; //0=click, 1=tab, -1= shift tab, 2=return, -2=shift return, 3=esc. controls if you exited the field so you can focus the next field if appropriate

			//whenever the model changes, we get called so we can update our value
			if (controller) {
				controller.$render = function() {
					oldValue = value = controller.$modelValue;
					if (value == undefined || value == null) value = "";
					return controller.$viewValue;
				};
			}

			//called once the edit is done, so we can save the new data and remove edit mode
			var saveEdit = function(exited) {
				oldValue = value;
				exit = exited;

				if (exited != 3) { //don't save value on esc
					value = input.data().select2.data();
					var v="";
					if (angular.isArray(value) && value.length > 0) {

						angular.forEach(value, function(val, key) {
							val = (key < value.length-1) ? val.text +"," : val.text;
							v += val;
						});
						value = v;
					} else if (angular.isObject(value) && value.text !== "") {
						value = value.text;
					} else {
						value = (value) ? value.text : "";
					}

					controller.$setViewValue(value);
				}

                if (exited !== 0) {
                    if (v) element[0].innerHTML = v;
                    element.show();
                    input.select2('destroy'); //TODO: resolve console error when destroying this the second time for the same input
                    input.remove();
                    editing = false;
                }

				ADE.done(options, oldValue, value, exit);

				if (!$scope.$$phase) {
					return $scope.$apply(); //This is necessary to get the model to match the value of the input
				}
			};

            $("body").bind("keyup", function(e) {
                $(document).find("div.select2-drop-active").each(function () {
                    if (e.keyCode == 27) { //esc
                        e.preventDefault();
                        e.stopPropagation();
                        var activeContainer = $(document).find('.select2-container-active');
                        var activeInput = activeContainer.next();
                        activeContainer.remove();
                        activeInput.remove();
                        element.show();
                        editing=false;
                    }
                });
            });

			//handles clicks on the read version of the data
			element.bind('click', function() {
				if (editing) return;
				editing = true;
				exit = 0;

				ADE.begin(options);
				element.hide();

				var multi = '';
				var placeholder = '';

				if (options.multiple) {
					multi = 'multiple="multiple"';
				} else {
					placeholder = ',placeholder:\'List...\'';
				}
				
				var query = '';
				if(options.query) query = ",query:" + options.query; //the user's query function for providing the list data
				var passthru = '';
				if(options.passthru) passthru = ",passthru:'" + options.passthru + "'"; //data that is passed through to the query function

				$compile('<input type="hidden" ui-select2={width:\'resolve\',allowClear:true,openOnEnter:false,closeOnSelect:false,allowAddNewValues:true'+query+passthru+',initSelection:selection'+placeholder+'} ' + multi + ' />')($scope)
					.insertAfter(element);
				input = element.next('input');

				var data = [], stringData=value;
				var cleanValue = (value) ? value.split(',') : [];

				angular.forEach(cleanValue, function(value, key) {
					$scope.listOptions.map(function(v,i) {
						if (value === v) {
							data.push({'id':i,'text':v });
						}
					});
				});

				if (!options.multiple) data = data[0];

				setTimeout(function() {
					input.select2("data", data);
					input.select2("open");
				});

				input.on("change", function(e) {
					if (!options.multiple) {
                        saveEdit();
                    }
				});

                input.on("close", function(e) {
                   saveEdit();
                });

				//make sure we aren't already digesting/applying before we apply the changes
				if (!$scope.$$phase) {
					return $scope.$apply(); //This is necessary to get the model to match the value of the input
				}
			});

			// Watches for changes to the element
			// TODO: understand why I have to return the observer and why the observer returns element
			return attrs.$observe('adeList', function(settings) { //settings is the contents of the ade-list="" string
				options = ADE.parseSettings(settings, {
					multiple: false
				});
				return element;
			});
		}
	};
}]);

// Taken from Angular-UI and modified for our uses
// https://github.com/angular-ui/angular-ui
adeModule.directive('uiSelect2', ['$http', function($http) {
	var options = {};

	return {
		require: '?ngModel',
		compile: function(tElm, tAttrs) {
			var watch,
{'fraction_non_alphanumeric': 0.1617363613508757, 'fraction_numerical': 0.005111874633369647, 'mean_word_length': 2.158814187400741, 'pattern_counts': {'":': 2, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 2, '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': '2237619', 'n_tokens_mistral': 4036, 'n_tokens_neox': 3263, 'n_words': 995}