1import mwCore from "/js/mw-core/mw-core.js" 2import "/js/mw-core/mw-core-button.js" 3 4class mwCorePagination extends mwCore { 5 6 // livecycle methods 7 8 updated() { 9 10 // cache DOM 11 12 this.cacheDOM() 13 14 // register eventListener 15 16 this.registerEventListener() 17 18 } 19 20 static get observedAttributes() { 21 return ["totalentries", "entriesperpage", "page"] 22 } 23 24 // css 25 26 styles() { 27 28 return [ 29 `<link href="/css/styleguide.css" rel="stylesheet">`, 30 ` 31 * { 32 user-select: none; 33 } 34 *:focus-visible { 35 outline: 2px solid black !important; 36 outline-offset: -2px !important; 37 transition: none !important; 38 } 39 :host([totalentries="0"]) { 40 opacity: 0; 41 visibility: hidden; 42 } 43 .container { 44 align-items: center; 45 display: flex; 46 justify-content: center; 47 } 48 .pages { 49 display: flex; 50 justify-content: center; 51 min-width: 224px; 52 } 53 .pages .entry { 54 align-items: center; 55 background: none; 56 border: none; 57 cursor: pointer; 58 display: flex; 59 height: 48px; 60 justify-content: center; 61 min-width: 34px; 62 padding: 0 5px; 63 } 64 .pages .entry:hover { 65 color: var(--mw-core-color-action-primary); 66 } 67 .pages .entry.selected { 68 background: var(--mw-core-color-action-primary); 69 color: #FFFFFF; 70 cursor: default; 71 width: 48px; 72 } 73 .pages .placeholder { 74 align-items: center; 75 display: flex; 76 height: 48px; 77 justify-content: center; 78 } 79 80 @media all and (min-width: 500px){ 81 82 .pages { 83 min-width: 250px; 84 } 85 .pages .entry { 86 min-width: 40px; 87 } 88 89 } 90 91 ` 92 ] 93 94 } 95 96 // render template 97 98 render() { 99 100 let lastPage = Math.ceil(this.totalentries / this.entriesperpage) 101 102 if (lastPage <= 1) { 103 lastPage = 1 104 } 105 106 return ` 107 <div class="container" role="navigation" aria-label="${document.documentElement.lang === 'de' ? 'Seitennavigation' : 'Pagination navigation'}"> 108 <mw-core-button class="prev"${this.page === 1 ? ` disabled` : ``} icon="2" nolabel tertiary aria-label="${document.documentElement.lang === 'de' ? 'Vorherige Seite' : 'Previous page'}"> 109 <template is="component-style"> 110 <style> 111 :host([nolabel]) button:hover { 112 border: var(--mw-core-color-action-primary-stroke); 113 } 114 :host([disabled]) button:hover { 115 border: 0; 116 } 117 </style> 118 </template> 119 </mw-core-button> 120 <div class="pages">${this.pages()}</div> 121 <mw-core-button class="next"${this.page === lastPage ? ` disabled` : ``} icon="3" nolabel tertiary aria-label="${document.documentElement.lang === 'de' ? 'Nächste Seite' : 'Next page'}"> 122 <template is="component-style"> 123 <style> 124 :host([nolabel]) button:hover { 125 border: var(--mw-core-color-action-primary-stroke); 126 } 127 :host([disabled]) button:hover { 128 border: 0; 129 } 130 </style> 131 </template> 132 </mw-core-button> 133 </div> 134 ` 135 136 } 137 138 // getter and setter 139 140 get totalentries() { 141 142 if (this._getAttribute("totalentries")) { 143 return parseInt(this._getAttribute("totalentries")) 144 } else { 145 return 0 146 } 147 148 } 149 150 set totalentries(val) { 151 this._setAttribute("totalentries", val) 152 } 153 154 get entriesperpage() { 155 156 if (this._getAttribute("entriesperpage")) { 157 return parseInt(this._getAttribute("entriesperpage")) 158 } else { 159 return 0 160 } 161 162 } 163 164 set entriesperpage(val) { 165 this._setAttribute("entriesperpage", val) 166 } 167 168 get page() { 169 170 if (this._getAttribute("page")) { 171 return parseInt(this._getAttribute("page")) 172 } else { 173 return 1 174 } 175 } 176 177 set page(val) { 178 this._setAttribute("page", val) 179 } 180 181 // custom methods 182 183 cacheDOM() { 184 185 // cache dom elements for faster access 186 187 this._dom = { 188 prev: this.shadowRoot.querySelector(".prev"), 189 next: this.shadowRoot.querySelector(".next"), 190 entries: this.shadowRoot.querySelectorAll(".entry") 191 } 192 193 } 194 195 registerEventListener() { 196 197 // click prev button 198 199 if (this._dom.prev) { 200 201 this._dom.prev.addEventListener("click", () => { 202 203 if (!this._dom.prev.hasAttribute("disabled")) { 204 205 if (this.page - 1 > 0) { 206 this.fireEvent(this.page - 1) 207 } 208 209 } 210 211 }) 212 213 } 214 215 // click next button 216 217 if (this._dom.next) { 218 219 this._dom.next.addEventListener("click", () => { 220 221 if (!this._dom.next.hasAttribute("disabled")) { 222 223 let sumPages = Math.ceil(this.totalentries / this.entriesperpage) 224 225 if (this.page + 1 <= sumPages) { 226 this.fireEvent(this.page + 1) 227 } 228 229 } 230 231 }) 232 233 } 234 235 // click entry 236 237 if (this._dom.entries) { 238 239 for (let entry of this._dom.entries) { 240 241 entry.addEventListener("click", () => { 242 243 if (parseInt(entry.innerHTML) > 0 && parseInt(entry.innerHTML) !== this.page) { 244 this.fireEvent(parseInt(entry.innerHTML)) 245 } 246 247 }) 248 249 } 250 251 } 252 253 } 254 255 pages() { 256 257 let sumPages = Math.ceil(this.totalentries / this.entriesperpage) 258 let html = `` 259 let pagesToShowInPagination = [] 260 261 if (this.page === 1) { 262 263 pagesToShowInPagination.push(1) 264 265 this.page + 1 <= sumPages ? pagesToShowInPagination.push(2) : null 266 this.page + 2 <= sumPages ? pagesToShowInPagination.push(3) : null 267 268 } else if (this.page === sumPages) { 269 270 let lastPage = this.page 271 272 lastPage - 2 > 0 ? pagesToShowInPagination.push(lastPage - 2) : null 273 lastPage - 1 > 0 ? pagesToShowInPagination.push(lastPage - 1) : null 274 pagesToShowInPagination.push(lastPage) 275 276 } else { 277 278 pagesToShowInPagination.push(this.page - 1) 279 pagesToShowInPagination.push(this.page) 280 281 this.page + 1 <= sumPages ? pagesToShowInPagination.push(this.page + 1) : null 282 283 } 284 285 // show first page? 286 287 if (pagesToShowInPagination[0] > 1) { 288 html += `<button class="entry first-page normal-text-bold" role="button" type="button" aria-label="${document.documentElement.lang === 'de' ? `erste Seite` : `first page`}" ${this.page === pagesToShowInPagination[0] > 1 ? `aria-current="page"` : ``}>1</button><div class="placeholder">...</div>` 289 } 290 291 for (let page of pagesToShowInPagination) { 292 html += `<button class="entry${this.page === page ? ` selected effect-border-radius` : ``} normal-text-bold" role="button" type="button" aria-label="${document.documentElement.lang === 'de' ? `Seite ${page}` : `Page ${page}`}" ${this.page === page ? `aria-current="page"` : ``}>${page}</button>` 293 } 294 295 // show last page? 296 297 if (pagesToShowInPagination[pagesToShowInPagination.length - 1] < sumPages) { 298 html += `<div class="placeholder">...</div><button class="entry last-page normal-text-bold" role="button" type="button" aria-label="${document.documentElement.lang === 'de' ? `letzte Seite` : `last page`}" ${this.page === pagesToShowInPagination[pagesToShowInPagination.length - 1] ? `aria-current="page"` : ``}>${sumPages}</button>` 299 } 300 301 return html 302 303 } 304 305 fireEvent(newPage) { 306 307 // fires custom event (change) 308 309 this.dispatchEvent(new CustomEvent("change", { 310 detail: { 311 newPage: newPage 312 } 313 })) 314 315 } 316 317} 318 319customElements.define("mw-core-pagination", mwCorePagination)
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.