1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16export class PageNation { 17 element: unknown; 18 pageInfo: unknown; 19 first: unknown; 20 prev: unknown; 21 next: unknown; 22 last: unknown; 23 inputBox: unknown; 24 btn: unknown; 25 list: unknown; 26 origin: HTMLElement | undefined; 27 static BtnBackColor = '#6C9BFA'; 28 static BtnColor = '#fff'; 29 constructor(selector: unknown, options = {}) { 30 // @ts-ignore 31 selector!.innerHTML = ''; 32 //最大容器 33 this.element = selector; 34 // 默认值 35 this.pageInfo = { 36 current: 1, 37 total: 100, 38 pageSize: 15, 39 }; 40 //等待创建的元素 41 this.first = null; 42 this.prev = null; 43 this.next = null; 44 this.last = null; 45 // 输入框 46 this.inputBox = null; 47 // 跳转按钮 48 this.btn = null; 49 // 中间的按钮组 50 this.list = null; 51 this.setPageOptions(options); 52 this.setItemStyles(); 53 this.createPageElement(); 54 this.bindPageHtml(); 55 this.bindPageEvent(); 56 } 57 58 setPageOptions(options: unknown): void { 59 // 当前页 60 // @ts-ignore 61 this.pageInfo.current = options.current || 1; 62 // 一页显示多少条 63 // @ts-ignore 64 this.pageInfo.pageSize = options.pageSize || 15; // @ts-ignore 65 if (options.totalpage) { 66 //用户传递了多少页 67 // @ts-ignore 68 this.pageInfo.totalpage = options.totalpage; 69 } else { 70 //没有传递多少页 71 // @ts-ignore 72 if (options.total) { 73 // 如果传递了总条数 74 // @ts-ignore 75 this.pageInfo.totalpage = Math.ceil(options.total / this.pageInfo.pageSize); 76 } else { 77 // 如果没有传递总条数 78 // @ts-ignore 79 this.pageInfo.totalpage = 9; 80 } 81 } // @ts-ignore 82 this.pageInfo.first = options.first || '<<'; 83 // @ts-ignore 84 this.pageInfo.change = options.change || function (): void {}; 85 } 86 87 setElementStyles(ele: unknown, styles: unknown): void { 88 // @ts-ignore 89 for (let key in styles) { 90 // @ts-ignore 91 ele.style[key] = styles[key]; 92 } 93 } 94 95 setItemStyles(): void { 96 this.setElementStyles(this.element, { 97 margin: '18px auto', 98 display: 'flex', 99 alignItems: 'center', 100 justifyContent: 'center', 101 }); 102 } 103 104 createElement(jumpDiv: HTMLElement): void { 105 // Create input field 106 this.inputBox = document.createElement('input'); // @ts-ignore 107 this.inputBox.value = this.pageInfo.current; 108 this.setElementStyles(this.inputBox, { 109 width: '35px', 110 height: '30px', 111 textAlign: 'center', 112 outline: 'none', 113 padding: '0', 114 border: '0', 115 'border-radius': '5px', 116 }); // @ts-ignore 117 jumpDiv.appendChild(this.inputBox); 118 let span = document.createElement('span'); 119 span.style.width = '1px'; 120 span.style.height = '24px'; 121 span.style.alignSelf = 'center'; 122 span.style.backgroundColor = '#999999'; 123 jumpDiv.appendChild(span); 124 // Create button 125 this.btn = document.createElement('button'); // @ts-ignore 126 this.btn.innerText = ''; // @ts-ignore 127 this.btn.name = 'goto'; 128 this.setElementStyles(this.btn, { 129 height: '32px', 130 width: '30px', 131 cursor: 'pointer', 132 backgroundColor: '#FFF', 133 border: '0', 134 'border-radius': '5px', 135 }); // @ts-ignore 136 this.btn.style.background = 'url("img/arrowright.png") no-repeat 98% center var(--dark-background3,#FFFFFF)'; // @ts-ignore 137 this.btn.style.backgroundPosition = 'center'; // @ts-ignore 138 jumpDiv.appendChild(this.btn); // @ts-ignore 139 this.element.appendChild(jumpDiv); 140 } 141 142 // 创建元素 首页 上一页 按钮组 下一页 尾页 输入框 按钮 143 createPageElement(): void { 144 //首页 145 this.origin = document.createElement('p'); 146 this.setElementStyles(this.origin, { 147 'border-radius': '4px', 148 padding: '5px', 149 border: '1px solid rgba(0,0,0,0.6)', 150 cursor: 'pointer', 151 margin: '0 5px', 152 }); 153 this.first = this.origin.cloneNode(true); // @ts-ignore 154 this.first.innerText = this.pageInfo.first; // @ts-ignore 155 this.first.name = 'first'; // @ts-ignore 156 this.element.appendChild(this.first); 157 this.prev = this.origin.cloneNode(true); // @ts-ignore 158 this.prev.innerText = '<'; // @ts-ignore 159 this.prev.name = 'prev'; // @ts-ignore 160 this.prev.style.padding = '5px 10px'; // @ts-ignore 161 this.element.appendChild(this.prev); 162 // 创建ul 163 this.list = document.createElement('ul'); 164 this.setElementStyles(this.list, { 165 display: 'flex', 166 padding: '0', 167 }); // @ts-ignore 168 this.element.appendChild(this.list); 169 this.next = this.origin.cloneNode(true); // @ts-ignore 170 this.next.innerText = '>'; // @ts-ignore 171 this.next.name = 'next'; // @ts-ignore 172 this.next.style.padding = '5px 10px'; // @ts-ignore 173 this.next.style.margin = '0px 5px'; // @ts-ignore 174 this.element.appendChild(this.next); 175 this.last = this.origin.cloneNode(true); // @ts-ignore 176 this.last.innerText = '>>'; // @ts-ignore 177 this.last.name = 'last'; // @ts-ignore 178 this.last.style.padding = '5px'; // @ts-ignore 179 this.last.style.margin = '0px 5px'; // @ts-ignore 180 this.element.appendChild(this.last); 181 let jumpDiv = document.createElement('div'); 182 jumpDiv.style.display = 'flex'; 183 jumpDiv.style.border = '1px solid rgba(0,0,0,0.6)'; 184 jumpDiv.style.borderRadius = '4px'; 185 jumpDiv.style.width = '70px'; 186 jumpDiv.style.height = '32px'; 187 jumpDiv.style.marginLeft = '10px'; 188 189 this.createElement(jumpDiv); 190 } 191 192 // 判断首页 上一页 下一页 尾页 是否可以点击 193 bindPageHtml(): void { 194 // @ts-ignore 195 const { current, totalpage } = this.pageInfo; 196 const disable = { color: '#999999', cursor: 'not-allowed' }; 197 const enable = { 198 color: '#000', 199 cursor: 'pointer', 200 }; 201 // 判断当前页是否是第一页 如果是第一页 那么首页和上一页就不能点击 202 if (current <= 1) { 203 this.setElementStyles(this.first, disable); 204 this.setElementStyles(this.prev, disable); 205 } else { 206 this.setElementStyles(this.first, enable); 207 this.setElementStyles(this.prev, enable); 208 } 209 // 判断当前页是否是最后一页 如果是最后一页 那么下一页和尾页就不能点击 210 if (current >= totalpage) { 211 this.setElementStyles(this.next, disable); 212 this.setElementStyles(this.last, disable); 213 } else { 214 this.setElementStyles(this.next, enable); 215 this.setElementStyles(this.last, enable); 216 } // @ts-ignore 217 this.inputBox.value = current; 218 //渲染的时候判断ul列表的显示情况 219 this.bindPageList(); // @ts-ignore 220 this.pageInfo.change(this.pageInfo.current); 221 } 222 223 bindPageList(): void { 224 // @ts-ignore 225 this.list.innerHTML = ''; // clear ul its contents 226 // @ts-ignore 227 const { pageSize, current, totalpage } = this.pageInfo; //Clean the ul before each load 228 const origin = document.createElement('li'); 229 origin.dataset.name = 'item'; 230 this.setElementStyles(origin, { 231 listStyle: 'none', 232 'border-radius': '4px', 233 border: '1px solid rgba(0,0,0,0.6)', 234 padding: '5px 10px', 235 margin: '0 5px', 236 cursor: 'pointer', 237 }); 238 if (totalpage <= 9) { 239 for (let i = 0; i < totalpage; i++) { 240 this.buildLi(origin, i, current); 241 } 242 return; 243 } 244 // Five on the left... Two on the right 245 if (this.bindLeftList(current, totalpage, origin)) { 246 return; 247 } 248 // The current page is larger than 5 pages and smaller than the last 5 pages 249 for (let index = 0; index < 2; index++) { 250 this.buildLi(origin, index, current); 251 } 252 let span = document.createElement('span'); 253 span.innerText = '...'; // @ts-ignore 254 this.list.appendChild(span); 255 for (let i = current - 3; i < current + 2; i++) { 256 this.buildLi(origin, i, current); 257 } 258 span = document.createElement('span'); 259 span.innerText = '...'; // @ts-ignore 260 this.list.appendChild(span); 261 for (let i = totalpage - 2; i < totalpage; i++) { 262 this.buildLi(origin, i, current); 263 } 264 } 265 266 private buildLi(origin: HTMLElement, i: number, current: number): void { 267 const li = origin.cloneNode(true); 268 // @ts-ignore 269 li.innerText = i + 1; 270 if (i + 1 === current) { 271 this.setElementStyles(li, { 272 backgroundColor: PageNation.BtnBackColor, 273 color: PageNation.BtnColor, 274 }); 275 } // @ts-ignore 276 this.list.appendChild(li); 277 } 278 279 bindLeftList(current: number, totalpage: number, origin: HTMLElement): boolean { 280 let span; 281 if (current < 5) { 282 // 左边5个 中间 ... 右边2个 283 for (let index = 0; index < 5; index++) { 284 this.buildLi(origin, index, current); 285 } 286 span = document.createElement('span'); 287 span.innerText = '...'; // @ts-ignore 288 this.list.appendChild(span); 289 for (let index = totalpage - 2; index < totalpage; index++) { 290 this.buildLi(origin, index, current); 291 } 292 return true; 293 } 294 if (current === 5) { 295 // 左边5个 中间 ... 右边2个 296 for (let i = 0; i < 7; i++) { 297 this.buildLi(origin, i, current); 298 } 299 span = document.createElement('span'); 300 span.innerText = '...'; // @ts-ignore 301 this.list.appendChild(span); 302 303 for (let index = totalpage - 2; index < totalpage; index++) { 304 this.buildLi(origin, index, current); 305 } 306 return true; 307 } 308 // 当前页面 大于倒数第5页 309 if (current > totalpage - 4) { 310 // 左边5个 中间 ... 右边2个 311 for (let index = 0; index < 2; index++) { 312 this.buildLi(origin, index, current); 313 } 314 span = document.createElement('span'); 315 span.innerText = '...'; // @ts-ignore 316 this.list.appendChild(span); 317 for (let i = totalpage - 5; i < totalpage; i++) { 318 this.buildLi(origin, i, current); 319 } 320 return true; 321 } 322 if (current === totalpage - 4) { 323 // 左边5个 中间 ... 右边2个 324 this.nodeAppendChild(origin, current, span, totalpage); 325 return true; 326 } 327 return false; 328 } 329 330 nodeAppendChild(origin: HTMLElement, current: number, span: unknown, totalpage: number): void { 331 for (let i = 0; i < 2; i++) { 332 this.buildLi(origin, i, current); 333 } 334 span = document.createElement('span'); // @ts-ignore 335 span.innerText = '...'; // @ts-ignore 336 this.list.appendChild(span); 337 for (let i = totalpage - 7; i < totalpage; i++) { 338 this.buildLi(origin, i, current); 339 } 340 } 341 342 bindPageEvent(): void { 343 // @ts-ignore 344 this.element.addEventListener( 345 'click', 346 (event: { 347 target: { 348 name: string; 349 dataset: { name: string }; 350 innerText: number; 351 }; 352 }) => { 353 this.targetName(event); 354 if (event.target.name === 'goto') { 355 // 拿到你文本的内容 356 // @ts-ignore 357 let page = this.inputBox.value - 0; 358 if (isNaN(page)) { 359 page = 1; 360 } 361 if (page <= 1) { 362 page = 1; 363 } // @ts-ignore 364 if (page >= this.pageInfo.totalpage) { 365 // @ts-ignore 366 page = this.pageInfo.totalpage; 367 } // @ts-ignore 368 this.pageInfo.current = page; 369 this.bindPageHtml(); 370 } 371 if (event.target.dataset.name === 'item') { 372 // @ts-ignore 373 this.pageInfo.current = event.target.innerText - 0; 374 this.bindPageHtml(); 375 } 376 } 377 ); 378 } 379 380 targetName(event: { 381 target: { 382 name: string; 383 dataset: { name: string }; 384 innerText: number; 385 }; 386 }): void { 387 if (event.target.name === 'first') { 388 // @ts-ignore 389 if (this.pageInfo.current === 1) { 390 return; 391 } // @ts-ignore 392 this.pageInfo.current = 1; 393 this.bindPageHtml(); 394 } 395 if (event.target.name === 'prev') { 396 // @ts-ignore 397 if (this.pageInfo.current === 1) { 398 return; 399 } // @ts-ignore 400 this.pageInfo.current--; 401 this.bindPageHtml(); 402 } 403 if (event.target.name === 'next') { 404 // @ts-ignore 405 if (this.pageInfo.current === this.pageInfo.totalpage) { 406 return; 407 } // @ts-ignore 408 this.pageInfo.current++; 409 this.bindPageHtml(); 410 } 411 if (event.target.name === 'last') { 412 // @ts-ignore 413 if (this.pageInfo.current === this.pageInfo.totalpage) { 414 return; 415 } // @ts-ignore 416 this.pageInfo.current = this.pageInfo.totalpage; 417 this.bindPageHtml(); 418 } 419 } 420} 421