aboutsummaryrefslogtreecommitdiff
path: root/javascript/app/components/input-with-autocomplete.js
blob: 34abe7a3db429ceae475d088ae5871748382e481 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import Ember from 'ember';
export default Ember.Component.extend({
  store : Ember.inject.service('store'),  
  highlightedItemIndex: -1,
  items : [],
  query: null,
  didInsertElement() {
    const $input = Ember.$(this.element).find(".search-input");
    const $autocompleteContainer = Ember.$(this.element).find(".autocomplete-container");    
    this.$input = $input;        
    this.$autocompleteContainer = $autocompleteContainer;    
    const width = $input.width() + 300;
    $autocompleteContainer.css({
      "width" : width+"px",
      "top" : $input.outerHeight()
    });
    $input.keyup((e) => {
      if(e.which === 13) {
        this.onEnter();
      } else if(e.which === 27) {
        this.onEsc();
      } else if(e.which === 40) {
        this.onDown();
      } else if(e.which === 38) {
        this.onUp();
      } 
    });
    $input.focusin(() => {      
      this.showAutocompleteList();
    });
    $input.focusout(() => {
      //Timeout is needed to make sure that click event fires
      Ember.run.later((() => {
        this.hideAutocompleteList();
      }), 100);
    });
  },
  willDestroyElement() {
    this._super(...arguments);
    this.$input.off('keyup');
    this.$input.off('focusin');
    this.$input.off('focusout');
  },
  onEnter() {
    if(this.get('highlightedItemIndex') !== -1) {
      const item = this.get('items')[this.get('highlightedItemIndex')];
      if(item) {
        this.hideAutocompleteList();
        this.get('selectItem')(item);
      }
    } else {
      this.hideAutocompleteList();
      this.get('onSubmit')(this.get('query'));
    }
  },
  onEsc() {
    this.hideAutocompleteList();
  },
  onDown() {
    this.showAutocompleteList();
    const index = this.get('highlightedItemIndex');
    const items = this.get('items');
    const itemsCount = items.length;
    if(itemsCount > 0) {
      if(index !== -1) {
        if(index === itemsCount - 1) {
          this.set('highlightedItemIndex',0);
        } else {
          this.set('highlightedItemIndex',index+1);
        }
      } else {
        this.set('highlightedItemIndex',0);
      }
    }
  },
  onUp() {
    this.showAutocompleteList();
    const index = this.get('highlightedItemIndex');
    const items = this.get('items');
    const itemsCount = items.length;
    if(itemsCount > 0) {
      if(index !== -1) {
        if(index === 0) {
          this.set('highlightedItemIndex',itemsCount - 1);
        } else {
          this.set('highlightedItemIndex',index - 1);
        }
      } else {
        this.set('highlightedItemIndex',itemsCount - 1);
      }
    }
  },
  hideAutocompleteList() {
    this.set('highlightedItemIndex',-1);
    this.$autocompleteContainer.css({
      "display":"none",
    });
  },
  showAutocompleteList() {
    if(this.get('query') !== "") {
      this.$autocompleteContainer.css({
        "display":"block"
      });
    }
  },
  searchUrlObserver : Ember.observer('createSearchUrlFunction',function() {
    this.notifyPropertyChange('query');
  }),  
  queryObserver : Ember.observer("query",function() {
    if(this.get('query')) {
      const perPage = this.get('maxItems') ? this.get('maxItems') : 10;
      const url = this.get('createSearchUrlFunction')(this.get('query')) + "?per_page=" + perPage;
      Ember.run.debounce(this, () => {
        this.get('store').loadFromUrlPaginated(url).then((result) => {
          Ember.run.next(() => {
            this.set('items',result.items);
          });
        });
      }, 400);
      this.showAutocompleteList();
    } else {
      this.hideAutocompleteList();
      this.set('items',[]);
    }
  }),
  actions : {
    onSubmit() {
      this.hideAutocompleteList();
      this.get('onSubmit')(this.get('query'));
    },
    goToDefinition (item) {
      this.hideAutocompleteList();
      this.get('selectItem')(item);
    }
  }
});