Eliminate the margin on timeline elements so multiple timelines can touch.
[WebKit-https.git] / Websites / test-results / public / js / autocompleter.js
1 function Autocompleter(inputElement, list) {
2     this._inputElement = inputElement;
3     this._currentSelection = undefined;
4     this._list = list;
5     this._candidates = [];
6     this._currentFilter = null;
7     this._candidateWindow = null;
8
9     inputElement.addEventListener('focus', this.show.bind(this));
10     inputElement.addEventListener('blur', this.hide.bind(this));
11     inputElement.addEventListener('keyup', this.update.bind(this));
12     inputElement.addEventListener('keydown', this.navigate.bind(this));
13 }
14
15 Autocompleter.prototype.filterCandidates = function (filter) {
16     return this._list.filter(function (testName) { return testName.indexOf(filter) >= 0; });
17 }
18
19 Autocompleter.prototype._ensureCandidateWindow = function () {
20     if (this._candidateWindow)
21         return;
22
23     var container = element('ul');
24     container.className = 'candidateWindow';
25     container.style.position = 'absolute';
26     container.style.display = 'none';
27     this._inputElement.parentNode.appendChild(container);
28     this._candidateWindow = container;
29 }
30
31 Autocompleter.prototype._updateCandidates = function (filter) {
32     if (this._currentFilter == filter)
33         return false;
34
35     var candidates = this.filterCandidates(filter);
36     if (candidates.length > 50)
37         candidates = [];
38     this._candidates = candidates;
39     this._currentFilter = filter;
40     this._currentSelection = undefined;
41     return true;
42 }
43
44 Autocompleter.prototype._showCandidateWindow = function () {
45     if (!this._candidateWindow)
46         return;
47     var style = this._candidateWindow.style;
48     style.display = 'block';
49     style.top = this._inputElement.offsetTop + this._inputElement.offsetHeight + 'px';
50     style.left = this._inputElement.offsetLeft + 'px';
51 }
52
53 Autocompleter.prototype._createItem = function (candidate) {
54     var tokens = candidate.split(this._currentFilter);
55     var children = [];
56     for (var i = 0; i < tokens.length; i++) {
57         children.push(text(tokens[i]));
58         if (i + 1 < tokens.length)
59             children.push(element('em', [this._currentFilter]));
60     }
61     return element('li', children);
62 }
63
64 Autocompleter.prototype.show = function () {
65     this.hide();
66     this._ensureCandidateWindow();
67
68     for (var i = 0; i < this._candidates.length; i++)
69         this._candidateWindow.appendChild(this._createItem(this._candidates[i]));
70     this._selectItem(this._currentSelection);
71
72     if (this._candidates.length)
73         this._showCandidateWindow();
74 }
75
76 Autocompleter.prototype.update = function () {
77     if (this._updateCandidates(this._inputElement.value))
78         this.show();
79 }
80
81 Autocompleter.prototype.hide = function () {
82     if (!this._candidateWindow)
83         return;
84     this._candidateWindow.style.display = 'none';
85     this._candidateWindow.innerHTML = '';
86 }
87
88 Autocompleter.prototype._selectItem = function (index) {
89     if (!this._candidateWindow || this._currentSelection == index)
90         return;
91
92     var item = this._candidateWindow.childNodes[index];
93     if (!item)
94         return;
95     item.classList.add('selected');
96
97     var oldItem = this._candidateWindow.childNodes[this._currentSelection];
98     if (oldItem)
99         oldItem.classList.remove('selected');
100
101     this._currentSelection = index;
102 }
103
104 Autocompleter.prototype.navigate = function (event) {
105     if (event.keyCode == 0x28 /* DOM_VK_DOWN */) {
106         this._selectItem(this._currentSelection === undefined ? 0 : Math.min(this._currentSelection + 1, this._candidates.length - 1));
107         event.preventDefault();
108     } else if (event.keyCode == 0x26 /* DOM_VK_UP */) {
109         this._selectItem(this._currentSelection === undefined ? this._candidates.length - 1 : Math.max(this._currentSelection - 1, 0));
110         event.preventDefault();
111     } else if (event.keyCode == 0x0D /* VK_RETURN */) {
112         if (this._currentSelection === undefined)
113             return;
114         this._inputElement.value = this._candidates[this._currentSelection];
115     } else if (event.keyCode == 0x1B /* DOM_VK_ESCAPE */) {
116         this.hide();
117     }
118 }