Dynamic Web Development with Seaside

16.3Rendering the Sudoku Grid

What we need to do is to render a table that looks like a Sudoku grid. We start by defining a method that creates a table and uses style tags for formatting.

WebSudoku>>renderHeaderFor: aString on: html
html tableData
class: 'sudokuHeader';
class: 'sudokuHBorder';
class: 'sudokuVBorder';
with: aString
WebSudoku>>renderContentOn: html
self renderHeaderFor: 'This is a test' on: html

Make sure that you invoked the class side initialize method and then run the application by visiting http://localhost:8080/sudoku. Your browser should display the string This is a test.

We need two helper methods when creating the labels for the x and y axis of our Sudoku grid. You don’t need to actually add these helper methods yourself, they were already loaded when you loaded the Sudoku package:

Integer>>asSudokuCol
"Label for columns"

^ ($1 to: $9) at: self
Integer>>asSudokuRow
"Label for rows"

^ ($A to: $I) at: self

First we print a space to get our labels aligned and then draw the label for each column.

WebSudoku>>renderBoardOn: html
html table: [
html tableRow: [
self renderHeaderFor: '' on: html.
1 to: 9 do: [ :col |
self renderHeaderFor: col asSudokuCol on: html ] ] ]

We make sure that the method WebSudoku>>renderContentOn: invokes the board rendering method we just defined.

WebSudoku>>renderContentOn: html
self renderBoardOn: html

The column labels look like this

If you run the application again, you should see the column labels as shown in Figure 109.

We now draw each row with its label, identifying the cells with the product of its row and column number.

WebSudoku>>renderBoardOn: html
html table: [
html tableRow: [
self renderHeaderFor: '' on: html.
1 to: 9 do: [ :col | self renderHeaderFor: col asString on: html ] ].
1 to: 9 do: [ :row |
html tableRow: [
self renderHeaderFor: row asSudokuRow on: html.
1 to: 9 do: [ :col |
html tableData: col * row asString ] ] ] ]

If you have entered everything correctly, your page should now look like Figure 110.

Row labels are letters, column labels are numbers

Now we define the method renderCellAtRow:col:on: that sets the style tags and redefine the renderContentOn: as follows so that it uses our style sheet.

WebSudoku>>renderContentOn: html
html div
id: 'sudokuBoard';
with: [ self renderBoardOn: html ]
WebSudoku>>renderCellAtRow: rowInteger col: colInteger on: html
html tableData
class: 'sudokuHBorder' if: rowInteger \\ 3 == 0;
class: 'sudokuVBorder' if: colInteger \\ 3 == 0

You also need to change WebSudoku>>renderBoardOn: so that it uses our new method WebSudoku>>renderCellAtRow:col:on:.

WebSudoku>>renderBoardOn: html
html table: [
html tableRow: [
self renderHeaderFor: '' on: html.
1 to: 9 do: [ :col | self renderHeaderFor: col asString on: html ] ].
1 to: 9 do: [ :row |
html tableRow: [
self renderHeaderFor: row asSudokuRow on: html.
1 to: 9 do: [ :col | self renderCellAtRow: row col: col on: html ] ] ] ]

If you refresh your page again, you should finally see a styled Sudoku grid as show in Figure 111.

The Sudoku board with the style sheet applied

Next we will use a small helper method asCompactString that given a collection returns a string containing all the elements printed one after the other without spaces. Again, you do not need to type this method, it was loaded with the ML-Sudoku code.

Collection>>asCompactString
| stream |
stream := WriteStream on: String new.
self do: [ :each | ws nextPutAll: each printString ].
^ stream contents

We define a new method renderCellContentAtRow:col:on: that uses asCompactString to display the contents of a cell. Each cell displays its possibility set. These are the values that may legally appear in that cell.

WebSudoku>>renderCellContentAtRow: rowInteger col: colInteger on: html
| currentCell possibilites |
currentCell := MLCell row: rowInteger col: colInteger.
possibilites := sudoku possibilitiesAt: currentCell.
possibilites numberOfPossibilities = 1
ifTrue: [ html text: possibilites asCompactString ]
ifFalse: [
html span
class: 'sudokuPossibilities';
with: possibilites asCompactString ]

We make sure that the renderCellAtRow:col:on: invokes the method rendering cell contents.

WebSudoku>>renderCellAtRow: rowInteger col: colInteger on: html
html tableData
class: 'sudokuHBorder' if: rowInteger \\ 3 = 0;
class: 'sudokuVBorder' if: colInteger \\ 3 = 0;
with: [ self renderCellContentAtRow: rowInteger col: colInteger on: html ]

Refresh your application again, and your grid should appear as in Figure 112.

The Sudoku grid is showing the possible values for each cell

Copyright © 19 March 2024 Stéphane Ducasse, Lukas Renggli, C. David Shaffer, Rick Zaccone
This book is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 license.

This book is published using Seaside, Magritte and the Pier book publishing engine.