angular-autocomplete.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /* --- Made by justgoscha and licensed under MIT license --- */
  2. define(["libs/angular"], function(){
  3. var app = angular.module('autocomplete', []);
  4. app.directive('autocomplete', function() {
  5. var index = -1;
  6. console.log("helllo")
  7. return {
  8. restrict: 'E',
  9. scope: {
  10. searchParam: '=ngModel',
  11. suggestions: '=data',
  12. onType: '=onType',
  13. onSelect: '=onSelect'
  14. },
  15. controller: ['$scope', function($scope){
  16. // the index of the suggestions that's currently selected
  17. $scope.selectedIndex = -1;
  18. // set new index
  19. $scope.setIndex = function(i){
  20. $scope.selectedIndex = parseInt(i);
  21. };
  22. this.setIndex = function(i){
  23. $scope.setIndex(i);
  24. $scope.$apply();
  25. };
  26. $scope.getIndex = function(i){
  27. return $scope.selectedIndex;
  28. };
  29. // watches if the parameter filter should be changed
  30. var watching = true;
  31. // autocompleting drop down on/off
  32. $scope.completing = false;
  33. // starts autocompleting on typing in something
  34. $scope.$watch('searchParam', function(newValue, oldValue){
  35. if (oldValue === newValue) {
  36. return;
  37. }
  38. if(watching && $scope.searchParam) {
  39. $scope.completing = true;
  40. $scope.searchFilter = $scope.searchParam;
  41. $scope.selectedIndex = -1;
  42. }
  43. // function thats passed to on-type attribute gets executed
  44. if($scope.onType)
  45. $scope.onType($scope.searchParam);
  46. });
  47. // for hovering over suggestions
  48. this.preSelect = function(suggestion){
  49. watching = false;
  50. // this line determines if it is shown
  51. // in the input field before it's selected:
  52. //$scope.searchParam = suggestion;
  53. $scope.$apply();
  54. watching = true;
  55. };
  56. $scope.preSelect = this.preSelect;
  57. this.preSelectOff = function(){
  58. watching = true;
  59. };
  60. $scope.preSelectOff = this.preSelectOff;
  61. // selecting a suggestion with RIGHT ARROW or ENTER
  62. $scope.select = function(suggestion){
  63. if(suggestion){
  64. $scope.searchParam = suggestion;
  65. $scope.searchFilter = suggestion;
  66. if($scope.onSelect)
  67. $scope.onSelect(suggestion);
  68. }
  69. watching = false;
  70. $scope.completing = false;
  71. setTimeout(function(){watching = true;},1000);
  72. $scope.setIndex(-1);
  73. };
  74. }],
  75. link: function(scope, element, attrs){
  76. var attr = '';
  77. // Default atts
  78. scope.attrs = {
  79. "placeholder": "start typing...",
  80. "class": "",
  81. "id": "",
  82. "inputclass": "",
  83. "inputid": ""
  84. };
  85. for (var a in attrs) {
  86. attr = a.replace('attr', '').toLowerCase();
  87. // add attribute overriding defaults
  88. // and preventing duplication
  89. if (a.indexOf('attr') === 0) {
  90. scope.attrs[attr] = attrs[a];
  91. }
  92. }
  93. if (attrs.clickActivation) {
  94. element[0].onclick = function(e){
  95. if(!scope.searchParam){
  96. scope.completing = true;
  97. scope.$apply();
  98. }
  99. };
  100. }
  101. var key = {left: 37, up: 38, right: 39, down: 40 , enter: 13, esc: 27};
  102. document.addEventListener("keydown", function(e){
  103. var keycode = e.keyCode || e.which;
  104. switch (keycode){
  105. case key.esc:
  106. // disable suggestions on escape
  107. scope.select();
  108. scope.setIndex(-1);
  109. scope.$apply();
  110. e.preventDefault();
  111. }
  112. }, true);
  113. document.addEventListener("blur", function(e){
  114. // disable suggestions on blur
  115. // we do a timeout to prevent hiding it before a click event is registered
  116. setTimeout(function() {
  117. scope.select();
  118. scope.setIndex(-1);
  119. scope.$apply();
  120. }, 200);
  121. }, true);
  122. element[0].addEventListener("keydown",function (e){
  123. var keycode = e.keyCode || e.which;
  124. var l = angular.element(this).find('li').length;
  125. // implementation of the up and down movement in the list of suggestions
  126. switch (keycode){
  127. case key.up:
  128. index = scope.getIndex()-1;
  129. if(index<-1){
  130. index = l-1;
  131. } else if (index >= l ){
  132. index = -1;
  133. scope.setIndex(index);
  134. scope.preSelectOff();
  135. break;
  136. }
  137. scope.setIndex(index);
  138. if(index!==-1)
  139. scope.preSelect(angular.element(angular.element(this).find('li')[index]).text());
  140. scope.$apply();
  141. break;
  142. case key.down:
  143. index = scope.getIndex()+1;
  144. if(index<-1){
  145. index = l-1;
  146. } else if (index >= l ){
  147. index = -1;
  148. scope.setIndex(index);
  149. scope.preSelectOff();
  150. scope.$apply();
  151. break;
  152. }
  153. scope.setIndex(index);
  154. if(index!==-1)
  155. scope.preSelect(angular.element(angular.element(this).find('li')[index]).text());
  156. break;
  157. case key.left:
  158. break;
  159. case key.right:
  160. case key.enter:
  161. index = scope.getIndex();
  162. // scope.preSelectOff();
  163. if(index !== -1)
  164. scope.select(angular.element(angular.element(this).find('li')[index]).text());
  165. scope.setIndex(-1);
  166. scope.$apply();
  167. break;
  168. case key.esc:
  169. // disable suggestions on escape
  170. scope.select();
  171. scope.setIndex(-1);
  172. scope.$apply();
  173. e.preventDefault();
  174. break;
  175. default:
  176. return;
  177. }
  178. if(scope.getIndex()!==-1 || keycode == key.enter)
  179. e.preventDefault();
  180. });
  181. },
  182. templateUrl: 'js/libs/angular-autocomplete/ac_template.html'
  183. };
  184. });
  185. app.filter('highlight', ['$sce', function ($sce) {
  186. return function (input, searchParam) {
  187. if (typeof input === 'function') return '';
  188. if (searchParam) {
  189. var words = '(' +
  190. searchParam.split(/\ /).join(' |') + '|' +
  191. searchParam.split(/\ /).join('|') +
  192. ')',
  193. exp = new RegExp(words, 'gi');
  194. if (words.length) {
  195. input = input.replace(exp, "<span class=\"highlight\">$1</span>");
  196. }
  197. }
  198. return $sce.trustAsHtml(input);
  199. };
  200. }]);
  201. app.directive('suggestion', function(){
  202. return {
  203. restrict: 'A',
  204. require: '^autocomplete', // ^look for controller on parents element
  205. link: function(scope, element, attrs, autoCtrl){
  206. element.bind('mouseenter', function() {
  207. autoCtrl.preSelect(attrs.val);
  208. autoCtrl.setIndex(attrs.index);
  209. });
  210. element.bind('mouseleave', function() {
  211. autoCtrl.preSelectOff();
  212. });
  213. }
  214. };
  215. });
  216. })