I. Logic
- For each
input
, wait 500ms to make API call, to load 40 items scroll
down close to bottom ( less than 20px left ), make API call to load another 40 items- could add local
cache
, to speed up response
II. code
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
137
138
139
140
141
142
143
144
<html>
<head>
<style>
#wrapper {
margin-top: 10px;
overflow: auto;
width: 250px;
display: inline-block;
border: 1px solid red;
overflow: hidden;
}
.listWrapper{
border: 1px solid blue;
height: 200px;
width: 140px;
overflow: auto;
scroll: auto;
}
</style>
</head>
<body>
<div id="wrapper">
<div>
<input id="inputText" />
<button>submit</button>
</div>
</div>
<script>
let body = document.getElementsByTagName("BODY")[0]
let data = Array.from({length: 40}, () => "recommdation"+Math.floor(Math.random() * 40));
const API = "https://www.demo.com/potentialList"
let isFetching = false // used for scroll
let isEnd = false // used for scroll
// create new element below <input> inside div wrapper. For both 'input' & 'scroll'
function appendList(elementCollection, wrapper, isScroll){
if(isScroll){
let listWrapper = document.getElementsByClassName("listWrapper")[0]
data.forEach( ele=>{
let itemNode = document.createElement("DIV")
let textNode = document.createTextNode(ele)
itemNode.appendChild(textNode)
listWrapper.appendChild(itemNode)
})
return
}
let oldlistWrapper = document.getElementsByClassName("listWrapper")
if(oldlistWrapper.length > 0){
wrapper.removeChild(oldlistWrapper[0])
}
let listWrapper = document.createElement("DIV")
listWrapper.setAttribute("class", "listWrapper")
let list = Array.prototype.slice.call(elementCollection)
data.forEach( ele=>{
let itemNode = document.createElement("DIV")
let textNode = document.createTextNode(ele)
itemNode.appendChild(textNode)
listWrapper.appendChild(itemNode)
})
listWrapper.addEventListener("click", putToInput)
listWrapper.addEventListener("scroll", scrollHandler)
wrapper.appendChild(listWrapper)
}
// onclick callback for items provided
function putToInput(e){
let input = document.getElementById("inputText")
let wrapper = document.getElementById("wrapper")
let listWrapper = document.getElementsByClassName("listWrapper")[0]
input.value = e.target.innerHTML
console.log(e.target)
wrapper.removeChild(listWrapper)
}
// make API call
function makeAPICall(API, val, isScroll){
console.log("val: ", val)
// 1. first check local cache
// 2. hit fail, call API
let ajax = new XMLHttpRequest()
ajax.open("GET", "https://www.w3schools.com/js/ajax_info.txt", true)
ajax.onreadystatechange = function(){
if(this.readyState === 4 && this.status === 200 ){
console.log(this.responseText)
let parser = new DOMParser()
let a = parser.parseFromString(this.responseText, "text/html")
console.log(a)
let body = a.getElementsByTagName("BODY")[0]
let wrapper = document.getElementById("wrapper")
if(val.localeCompare("scroll made request")===0){
isFetching = false
}
appendList(data, wrapper, isScroll)
}
}
ajax.send()
}
// scroll handler for listWrapper
function scrollHandler(e){
let listWrapper = e.target
let boxHeight = listWrapper.clientHeight
let scrollTop = listWrapper.scrollTop
let scrollHeight = listWrapper.scrollHeight
let remainder = scrollHeight - scrollTop
let diff = remainder - boxHeight
console.log("box height: ", boxHeight)
console.log("scrollTop: ", scrollTop)
console.log("scrollHeight: ", scrollHeight)
console.log("diff: ", diff)
if( diff < 20 && !isFetching && !isEnd ){
isFetching = true
makeAPICall(API, "scroll made request", true)
}
}
// debounce 500ms to make API call
let timeHandler = null
function inputHandler(e){
clearTimeout(timeHandler)
let val = e.target.value
timeHandler = setTimeout( function(){makeAPICall(API, "keypress made request", false)} ,500 )
}
let input = document.getElementById("inputText")
addEventListener("input", inputHandler)
</script>
</body>
</html>