@@ -22,6 +22,7 @@ const ModelProperty = {
2222} ;
2323
2424const Event = {
25+ CHANGE : "change" ,
2526 CHANGE_TABLE_HTML : `change:${ ModelProperty . TABLE_HTML } ` ,
2627 CLICK : "click" ,
2728} ;
@@ -34,29 +35,59 @@ const Event = {
3435 * }} options
3536 */
3637function render ( { model, el } ) {
38+ // Structure
3739 const container = document . createElement ( "div" ) ;
38- container . innerHTML = model . get ( ModelProperty . TABLE_HTML ) ;
39-
40- const buttonContainer = document . createElement ( "div" ) ;
40+ const tableContainer = document . createElement ( "div" ) ;
41+ const footer = document . createElement ( "div" ) ;
42+ // Total rows label
43+ const rowCountLabel = document . createElement ( "div" ) ;
44+ // Pagination controls
45+ const paginationContainer = document . createElement ( "div" ) ;
4146 const prevPage = document . createElement ( "button" ) ;
42- const label = document . createElement ( "span" ) ;
47+ const paginationLabel = document . createElement ( "span" ) ;
4348 const nextPage = document . createElement ( "button" ) ;
49+ // Page size controls
50+ const pageSizeContainer = document . createElement ( "div" ) ;
51+ const pageSizeLabel = document . createElement ( "label" ) ;
52+ const pageSizeSelect = document . createElement ( "select" ) ;
53+
54+ tableContainer . classList . add ( "table-container" ) ;
55+ footer . classList . add ( "footer" ) ;
56+ paginationContainer . classList . add ( "pagination" ) ;
57+ pageSizeContainer . classList . add ( "page-size" ) ;
4458
4559 prevPage . type = "button" ;
4660 nextPage . type = "button" ;
4761 prevPage . textContent = "Prev" ;
4862 nextPage . textContent = "Next" ;
4963
64+ pageSizeLabel . textContent = "Page Size" ;
65+ for ( const size of [ 10 , 25 , 50 , 100 ] ) {
66+ const option = document . createElement ( "option" ) ;
67+ option . value = size ;
68+ option . textContent = size ;
69+ if ( size === model . get ( ModelProperty . PAGE_SIZE ) ) {
70+ option . selected = true ;
71+ }
72+ pageSizeSelect . appendChild ( option ) ;
73+ }
74+
5075 /** Updates the button states and page label based on the model. */
5176 function updateButtonStates ( ) {
77+ const rowCount = model . get ( ModelProperty . ROW_COUNT ) ;
78+ rowCountLabel . textContent = `${ rowCount . toLocaleString ( ) } total rows` ;
79+
5280 const totalPages = Math . ceil (
5381 model . get ( ModelProperty . ROW_COUNT ) / model . get ( ModelProperty . PAGE_SIZE ) ,
5482 ) ;
5583 const currentPage = model . get ( ModelProperty . PAGE ) ;
5684
57- label . textContent = `Page ${ currentPage + 1 } of ${ totalPages } ` ;
85+ paginationLabel . textContent = `Page ${ currentPage + 1 } of ${ totalPages } ` ;
5886 prevPage . disabled = currentPage === 0 ;
5987 nextPage . disabled = currentPage >= totalPages - 1 ;
88+
89+ // Update page size selector
90+ pageSizeSelect . value = model . get ( ModelProperty . PAGE_SIZE ) ;
6091 }
6192
6293 /**
@@ -72,24 +103,48 @@ function render({ model, el }) {
72103 }
73104 }
74105
75- prevPage . addEventListener ( Event . CLICK , ( ) => handlePageChange ( - 1 ) ) ;
76- nextPage . addEventListener ( Event . CLICK , ( ) => handlePageChange ( 1 ) ) ;
106+ /** Handles the page_size in the model.
107+ * @param {number } size - new size to set
108+ */
109+ function handlePageSizeChange ( size ) {
110+ const currentSize = model . get ( ModelProperty . PAGE_SIZE ) ;
111+ if ( size !== currentSize ) {
112+ model . set ( ModelProperty . PAGE_SIZE , size ) ;
113+ model . save_changes ( ) ;
114+ }
115+ }
77116
78- model . on ( Event . CHANGE_TABLE_HTML , ( ) => {
117+ /** Updates the HTML in the table container **/
118+ function handleTableHTMLChange ( ) {
79119 // Note: Using innerHTML can be a security risk if the content is
80120 // user-generated. Ensure 'table_html' is properly sanitized.
81- container . innerHTML = model . get ( ModelProperty . TABLE_HTML ) ;
121+ tableContainer . innerHTML = model . get ( ModelProperty . TABLE_HTML ) ;
82122 updateButtonStates ( ) ;
123+ }
124+
125+ prevPage . addEventListener ( Event . CLICK , ( ) => handlePageChange ( - 1 ) ) ;
126+ nextPage . addEventListener ( Event . CLICK , ( ) => handlePageChange ( 1 ) ) ;
127+ pageSizeSelect . addEventListener ( Event . CHANGE , ( e ) => {
128+ const newSize = Number ( e . target . value ) ;
129+ if ( newSize ) {
130+ handlePageSizeChange ( newSize ) ;
131+ }
83132 } ) ;
133+ model . on ( Event . CHANGE_TABLE_HTML , handleTableHTMLChange ) ;
84134
85135 // Initial setup
86- updateButtonStates ( ) ;
87-
88- buttonContainer . appendChild ( prevPage ) ;
89- buttonContainer . appendChild ( label ) ;
90- buttonContainer . appendChild ( nextPage ) ;
136+ paginationContainer . appendChild ( prevPage ) ;
137+ paginationContainer . appendChild ( paginationLabel ) ;
138+ paginationContainer . appendChild ( nextPage ) ;
139+ pageSizeContainer . appendChild ( pageSizeLabel ) ;
140+ pageSizeContainer . appendChild ( pageSizeSelect ) ;
141+ footer . appendChild ( rowCountLabel ) ;
142+ footer . appendChild ( paginationContainer ) ;
143+ footer . appendChild ( pageSizeContainer ) ;
144+ container . appendChild ( tableContainer ) ;
145+ container . appendChild ( footer ) ;
91146 el . appendChild ( container ) ;
92- el . appendChild ( buttonContainer ) ;
147+ handleTableHTMLChange ( ) ;
93148}
94149
95150export default { render } ;
0 commit comments