23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ |
24 */ |
25 |
25 |
26 function debounce(func){ |
26 function debounce(func){ |
27 let timer; |
27 let timer; |
28 return () => { |
28 return (...args) => { |
29 clearTimeout(timer); |
29 clearTimeout(timer); |
30 timer = setTimeout(() => { func.apply(this); }, 300); |
30 timer = setTimeout(() => { func.apply(this, args); }, 300); |
31 }; |
31 }; |
32 } |
32 } |
33 |
33 |
34 const issueSearch = debounce(() => issueSearchImpl()) |
|
35 let searchBoxOldContent = ''; |
34 let searchBoxOldContent = ''; |
36 function issueSearchImpl() { |
35 function issueSearchImpl(elementId, project) { |
37 const searchBox = document.getElementById('search-box'); |
36 const searchBox = document.getElementById(elementId); |
38 if (searchBoxOldContent !== searchBox.value) { |
37 if (searchBoxOldContent !== searchBox.value) { |
39 searchBoxOldContent = searchBox.value; |
38 searchBoxOldContent = searchBox.value; |
40 const req = new XMLHttpRequest(); |
39 const req = new XMLHttpRequest(); |
41 req.addEventListener("load", (evt) => { |
40 req.addEventListener("load", (evt) => { |
42 const dataList = document.getElementById('search-box-list'); |
41 const dataList = document.getElementById(elementId+'-list'); |
43 dataList.innerHTML = ''; |
42 dataList.innerHTML = ''; |
44 JSON.parse(evt.target.responseText).forEach(function(item){ |
43 JSON.parse(evt.target.responseText).forEach(function(item){ |
45 const option = document.createElement('option'); |
44 const option = document.createElement('option'); |
46 option.value = item; |
45 option.value = item; |
47 dataList.appendChild(option); |
46 dataList.appendChild(option); |
48 }); |
47 }); |
49 }); |
48 }); |
50 req.open("GET", baseHref+'issues/search?q='+encodeURIComponent(searchBox.value)); |
49 let url = baseHref+'issues/search?q='+encodeURIComponent(searchBox.value); |
|
50 if (project > 0) url+='&p='+project; |
|
51 req.open("GET", url); |
51 req.send(); |
52 req.send(); |
52 } |
53 } |
53 } |
54 } |
|
55 const issueSearch = debounce((elementId, project = 0) => issueSearchImpl(elementId, project)) |
54 |
56 |
55 // configure the search box |
57 function configureSearchBox(elementId, project, navigateOnEnter = false) { |
56 window.addEventListener('load', () => { |
58 const searchBox = document.getElementById(elementId); |
57 const searchBox = document.getElementById('search-box'); |
59 searchBox.addEventListener('change', () => issueSearch(elementId, project)); |
58 searchBox.addEventListener('change', () => issueSearch()) |
60 if (navigateOnEnter) { |
59 searchBox.addEventListener('keyup', (evt) => { |
61 searchBox.addEventListener('keyup', (evt) => { |
60 if (evt.code === 'Enter' || evt.code === 'NumpadEnter') { |
62 if (evt.code === 'Enter' || evt.code === 'NumpadEnter') { |
61 let stext = searchBox.value.trim() |
63 let stext = searchBox.value.trim() |
62 if (stext.length === 0) return; |
64 if (stext.length === 0) return; |
63 if (stext[0] === '#') stext = stext.substring(1); |
65 if (stext[0] === '#') stext = stext.substring(1); |
64 const snum = Number.parseInt(stext.split(' ')[0], 10); |
66 const snum = Number.parseInt(stext.split(' ')[0], 10); |
65 if (snum !== Number.NaN) { |
67 if (snum !== Number.NaN) { |
66 location.assign(baseHref+'issues/'+snum+'?in_project=true'); |
68 location.assign(baseHref + 'issues/' + snum + '?in_project=true'); |
|
69 } |
|
70 } else { |
|
71 issueSearch(elementId, project); |
67 } |
72 } |
68 } else { |
73 }) |
69 issueSearch(); |
74 } else { |
70 } |
75 searchBox.addEventListener('keyup', () => issueSearch(elementId, project)); |
71 }) |
76 } |
72 }); |
77 } |
73 |
78 |
|
79 // configure the global search box |
|
80 window.addEventListener('load', () => configureSearchBox('search-box', 0, true)); |
|
81 |