1 | | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
2 | | <html> |
3 | | <head> |
4 | | <title>Scroll Bar</title> |
5 | | <link rel="stylesheet" href="scrollbar.css" type="text/css" /> |
6 | | <script type="text/javascript" src="scrollbar.js"></script> |
7 | | |
8 | | <!-- Load the generated client side code... --> |
9 | | <script type=’text/javascript’ src=’server.php?client’></script> |
10 | | <script type=’text/javascript’ src=’objectPool.js’></script> |
11 | | <script type='text/javascript'> |
12 | | var remote = new nail_remote(); |
13 | | remote.Sync(); |
14 | | // our get data function to call in onScroll methods |
15 | | function getDataSync(start,rows) { |
16 | | ret = remote.data(start,rows); |
17 | | document.getElementById(‘trace').innerHTML += "<li>Sync Fetch Rows: " +start + " - "+rows+”</li>”; |
18 | | return ret; |
19 | | } |
20 | | |
21 | | function getNumRowsSync() { |
22 | | ret = remote.num_rows(); |
23 | | return ret; |
24 | | } |
25 | | |
26 | | // our get data function to call in onScroll Up methods |
27 | | function getData(start,rows) { |
28 | | var r = remotePool.getObject(); |
29 | | |
30 | | document.getElementById(‘trace').innerHTML += "<li>Async Call data("+start+”,”+rows+”)</li>”; |
31 | | r.data(start,rows); |
32 | | } |
33 | | |
34 | | // callback class |
35 | | function NailCallback() {} |
36 | | NailCallback.prototype.data = function(result) { |
37 | | var start = false; |
38 | | var rows = 0; |
39 | | for(var key in result) { |
40 | | if (!start) { |
41 | | start = key; |
42 | | } |
43 | | if (!tableData[key]) { |
44 | | tableData[key] = result[key]; |
45 | | rows++; |
46 | | } |
47 | | } |
48 | | document.getElementById(‘trace').innerHTML += "<li>ASync Fetch Rows: " +start + " - "+rows+”</li>”; |
49 | | remotePool.returnObject(this.parent.poolId); |
50 | | } |
51 | | |
52 | | // jpspan remote proxy class pool |
53 | | var remotePool = new objectPool(); |
54 | | remotePool.createObject = function() { |
55 | | var callback = new NailCallback(); |
56 | | var remote = new nail_remote(callback); |
57 | | callback.parent = remote; |
58 | | return remote; |
59 | | } |
60 | | |
61 | | var lastPrefetch = false; |
62 | | |
63 | | // decide if we should try to prefetch some data |
64 | | function prefetchDownAsNeeded(currentIndex) { |
65 | | var testUntil = currentIndex + 5; |
66 | | |
67 | | var startPrefetch = false; |
68 | | for(var i = currentIndex; i < testUntil; i++) { |
69 | | if (!tableData[i]) { |
70 | | startPrefetch = i; |
71 | | break; |
72 | | } |
73 | | } |
74 | | |
75 | | if (startPrefetch && startPrefetch != lastPrefetch) { |
76 | | lastPrefetch = startPrefetch; |
77 | | getData(startPrefetch,10); |
78 | | } |
79 | | } |
80 | | |
81 | | function prefetchUpAsNeeded(currentIndex) { |
82 | | var testUntil = currentIndex - 5; |
83 | | |
84 | | var startPrefetch = false; |
85 | | for(var i = currentIndex; i > testUntil; i--) { |
86 | | if (!tableData[i]) { |
87 | | startPrefetch = i-10; |
88 | | break; |
89 | | } |
90 | | } |
91 | | |
92 | | if (startPrefetch < 0) { |
93 | | startPrefetch = 0; |
94 | | } |
95 | | |
96 | | if (startPrefetch && startPrefetch != lastPrefetch) { |
97 | | lastPrefetch = startPrefetch; |
98 | | getData(startPrefetch,10); |
99 | | } |
100 | | } |
101 | | </script> |
102 | | </head> |
103 | | <body> |
104 | | </script> |
105 | | </head> |
106 | | <body> |
107 | | <table cellpadding=0 cellspacing=0 border=0> |
108 | | <tr> |
109 | | <td> |
110 | | |
111 | | <table border="1"> |
112 | | <tr> |
113 | | <th>Nail Id</th> |
114 | | <th>Length</th>
|
115 | | <th>Diameter</th> |
116 | | </tr> |
117 | | <tbody id="table"> |
118 | | </tbody> |
119 | | </table> |
120 | | </td> |
121 | | <td> |
122 | | <div class="scrollBar" id="bar"></div> |
123 | | </td> |
124 | | </tr> |
125 | | </table> |
126 | | <ol id="trace"> |
127 | | </ol> |
128 | | <script type="text/javascript"> |
129 | | <?php |
130 | | // allow the table to start at other places then the beginning |
131 | | if (isset($_GET['start'])) { |
132 | | $start = $_GET['start']; |
133 | | } |
134 | | else { |
135 | | $start = 0; |
136 | | } |
137 | | echo "var start = $start;”; |
138 | | ?> |
139 | | // load in some starting data |
140 | | var tableData = new Object(); |
141 | | var d = getDataSync(start,5); |
142 | | |
143 | | for(var i = start; i < (start+5); i++) { |
144 | | tableData[i] = d[i]; |
145 | | } |
146 | | |
147 | | // render 5 rows of data |
148 | | var table = document.getElementById('table'); |
149 | | for(var i = start; i < (start+5); i++) { |
150 | | var row = document.createElement('tr'); |
151 | | for(var key in tableData[i]) { |
152 | | var cell = document.createElement('td'); |
153 | | cell.appendChild(document.createTextNode(tableData[i][key])); |
154 | | row.appendChild(cell); |
155 | | } |
156 | | table.appendChild(row); |
157 | | } |
158 | | |
159 | | // add our scroll bar |
160 | | var bar = new ScrollBar('bar'); |
161 | | bar.currentRow = 0; |
162 | | bar.scrollSize = 5; |
163 | | bar.numRows = getNumRowsSync(); |
164 | | bar.currentRow = start; |
165 | | |
166 | | // override the scrollbars onScrollDown method |
167 | | // use currentRow and scrollSize to see if we have more data to scroll |
168 | | // Scrolling means remove a row from the top add one to the bottom |
169 | | bar.onScrollDown = function() { |
170 | | // check if we should scroll |
171 | | if ( (this.currentRow + 1 + this.scrollSize) > this.numRows) { |
172 | | return; // no data to scroll too bail |
173 | | } |
174 | | |
175 | | this.currentRow += 1; |
176 | | |
177 | | // add our new row |
178 | | var index = this.currentRow + this.scrollSize -1; |
179 | | |
180 | | if (!tableData[index]) { |
181 | | var d = getDataSync(index,5); |
182 | | |
183 | | for(var i in d) { |
184 | | tableData[i] = d[i]; |
185 | | } |
186 | | } |
187 | | else { |
188 | | prefetchDownAsNeeded(index); |
189 | | } |
190 | | var row = document.createElement('tr'); |
191 | | for(var key in tableData[index]) { |
192 | | var cell = document.createElement('td'); |
193 | | cell.appendChild(document.createTextNode(tableData[index][key])); |
194 | | row.appendChild(cell); |
195 | | } |
196 | | table.appendChild(row); |
197 | | |
198 | | // remove the first row |
199 | | table.removeChild(table.getElementsByTagName('tr').item(0)); |
200 | | } |
201 | | |
202 | | // override the scrollbars onScrollUp method |
203 | | // same as onScrollDown only in the other direction |
204 | | bar.onScrollUp = function() { |
205 | | // check if we should scroll |
206 | | if ( this.currentRow == 0) { |
207 | | return; // no data to scroll too bail |
208 | | } |
209 | | |
210 | | this.currentRow -= 1; |
211 | | |
212 | | // add our new row |
213 | | var index = this.currentRow; |
214 | | |
215 | | // to hit this get you need to pass in a start value ?start=100 and then scroll up |
216 | | if (!tableData[index]) { |
217 | | var start = index - 4; |
218 | | var d = getDataSync(start,5); |
219 | | |
220 | | for(var i in d) { |
221 | | tableData[i] = d[i]; |
222 | | } |
223 | | } |
224 | | else { |
225 | | prefetchUpAsNeeded(index); |
226 | | } |
227 | | |
228 | | var row = document.createElement('tr'); |
229 | | for(var key in tableData[index]) { |
230 | | var cell = document.createElement('td'); |
231 | | cell.appendChild(document.createTextNode(tableData[index][key])); |
232 | | row.appendChild(cell); |
233 | | } |
234 | | |
235 | | table.insertBefore(row,table.getElementsByTagName('tr').item(0)); |
236 | | |
237 | | // remove the last row |
238 | | table.removeChild(table.getElementsByTagName('tr').item(this.scrollSize)); |
239 | | } |
240 | | </script> |
241 | | |
242 | | </body> |
243 | | |
244 | | </head> |