| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- /* --- Made by justgoscha and licensed under MIT license --- */
- define(["libs/angular"], function(){
- var app = angular.module('autocomplete', []);
- app.directive('autocomplete', function() {
- var index = -1;
- return {
- restrict: 'E',
- scope: {
- searchParam: '=ngModel',
- suggestions: '=data',
- onType: '=onType',
- onSelect: '=onSelect'
- },
- controller: ['$scope', function($scope){
- // the index of the suggestions that's currently selected
- $scope.selectedIndex = -1;
- // set new index
- $scope.setIndex = function(i){
- $scope.selectedIndex = parseInt(i);
- };
- this.setIndex = function(i){
- $scope.setIndex(i);
- $scope.$apply();
- };
- $scope.getIndex = function(i){
- return $scope.selectedIndex;
- };
- // watches if the parameter filter should be changed
- var watching = true;
- // autocompleting drop down on/off
- $scope.completing = false;
- // starts autocompleting on typing in something
- $scope.$watch('searchParam', function(newValue, oldValue){
- if (oldValue === newValue) {
- return;
- }
- if(watching && $scope.searchParam) {
- $scope.completing = true;
- $scope.searchFilter = $scope.searchParam;
- $scope.selectedIndex = -1;
- }
- // function thats passed to on-type attribute gets executed
- if($scope.onType)
- $scope.onType($scope.searchParam);
- });
- // for hovering over suggestions
- this.preSelect = function(suggestion){
- watching = false;
- // this line determines if it is shown
- // in the input field before it's selected:
- //$scope.searchParam = suggestion;
- $scope.$apply();
- watching = true;
- };
- $scope.preSelect = this.preSelect;
- this.preSelectOff = function(){
- watching = true;
- };
- $scope.preSelectOff = this.preSelectOff;
- // selecting a suggestion with RIGHT ARROW or ENTER
- $scope.select = function(suggestion){
- if(suggestion){
- $scope.searchParam = suggestion;
- $scope.searchFilter = suggestion;
- if($scope.onSelect)
- $scope.onSelect(suggestion);
- }
- watching = false;
- $scope.completing = false;
- setTimeout(function(){watching = true;},1000);
- $scope.setIndex(-1);
- };
- }],
- link: function(scope, element, attrs){
- var attr = '';
- // Default atts
- scope.attrs = {
- "placeholder": "start typing...",
- "class": "",
- "id": "",
- "inputclass": "",
- "inputid": ""
- };
- for (var a in attrs) {
- attr = a.replace('attr', '').toLowerCase();
- // add attribute overriding defaults
- // and preventing duplication
- if (a.indexOf('attr') === 0) {
- scope.attrs[attr] = attrs[a];
- }
- }
- if (attrs.clickActivation) {
- element[0].onclick = function(e){
- if(!scope.searchParam){
- scope.completing = true;
- scope.$apply();
- }
- };
- }
- var key = {left: 37, up: 38, right: 39, down: 40 , enter: 13, esc: 27};
- document.addEventListener("keydown", function(e){
- var keycode = e.keyCode || e.which;
- switch (keycode){
- case key.esc:
- // disable suggestions on escape
- scope.select();
- scope.setIndex(-1);
- scope.$apply();
- e.preventDefault();
- }
- }, true);
- document.addEventListener("blur", function(e){
- // disable suggestions on blur
- // we do a timeout to prevent hiding it before a click event is registered
- setTimeout(function() {
- scope.select();
- scope.setIndex(-1);
- scope.$apply();
- }, 200);
- }, true);
- element[0].addEventListener("keydown",function (e){
- var keycode = e.keyCode || e.which;
- var l = angular.element(this).find('li').length;
- // implementation of the up and down movement in the list of suggestions
- switch (keycode){
- case key.up:
- index = scope.getIndex()-1;
- if(index<-1){
- index = l-1;
- } else if (index >= l ){
- index = -1;
- scope.setIndex(index);
- scope.preSelectOff();
- break;
- }
- scope.setIndex(index);
- if(index!==-1)
- scope.preSelect(angular.element(angular.element(this).find('li')[index]).text());
- scope.$apply();
- break;
- case key.down:
- index = scope.getIndex()+1;
- if(index<-1){
- index = l-1;
- } else if (index >= l ){
- index = -1;
- scope.setIndex(index);
- scope.preSelectOff();
- scope.$apply();
- break;
- }
- scope.setIndex(index);
- if(index!==-1)
- scope.preSelect(angular.element(angular.element(this).find('li')[index]).text());
- break;
- case key.left:
- break;
- case key.right:
- case key.enter:
- index = scope.getIndex();
- // scope.preSelectOff();
- if(index !== -1)
- scope.select(angular.element(angular.element(this).find('li')[index]).text());
- scope.setIndex(-1);
- scope.$apply();
- break;
- case key.esc:
- // disable suggestions on escape
- scope.select();
- scope.setIndex(-1);
- scope.$apply();
- e.preventDefault();
- break;
- default:
- return;
- }
- if(scope.getIndex()!==-1 || keycode == key.enter)
- e.preventDefault();
- });
- },
- templateUrl: 'js/libs/angular-autocomplete/ac_template.html'
- };
- });
- app.filter('highlight', ['$sce', function ($sce) {
- return function (input, searchParam) {
- if (typeof input === 'function') return '';
- if (searchParam) {
- var words = '(' +
- searchParam.split(/\ /).join(' |') + '|' +
- searchParam.split(/\ /).join('|') +
- ')',
- exp = new RegExp(words, 'gi');
- if (words.length) {
- input = input.replace(exp, "<span class=\"highlight\">$1</span>");
- }
- }
- return $sce.trustAsHtml(input);
- };
- }]);
- app.directive('suggestion', function(){
- return {
- restrict: 'A',
- require: '^autocomplete', // ^look for controller on parents element
- link: function(scope, element, attrs, autoCtrl){
- element.bind('mouseenter', function() {
- autoCtrl.preSelect(attrs.val);
- autoCtrl.setIndex(attrs.index);
- });
- element.bind('mouseleave', function() {
- autoCtrl.preSelectOff();
- });
- }
- };
- });
- })
|