Seaside is web framework for Squeak and a program with tons of functionality. In this case we'll cover how to use it for web integration of Squeak applications. Before you get started you will need to have a few things:
To get everything rolling, evaluate the following code in a workspace.
WAKom startOn: 9090 "Start Seaside using Commanche on port 9090"Seaside should now be listening for requests on port 9090. Whenever you save and restart this image from now on, the Seaside service will come up automatically.
Open up a browser, find the class "WACounter" and take a look at some of the methods. count, decrease, and increase are all pretty standard and easy to follow.
In initialize, you'll notice the following:
self session registerObjectForBacktracking: self.This code is pretty self explanatory, and you shouldn't let it throw you off. It merely registers the instance of the component for tracking by seaside. Other than that, the initialize method is a no brainer.
The real heart of the component is in the renderContentsOn: method.
html heading: count. "Make a simple heading using the value of count."This method must be overridden in each new seaside component you create, as it determines how Seaside will generate html. As you can see, Seaside will handle page refreshing and will then generate the page again with the new value of count. This is good for two reasons: 1) it saves you from writing very long methods with huge string literals that detract from code readability. 2) It updates according to the state of the object. Seaside has all sorts of templates to generate various html widgets, all of which are referred to as components. You can look in the various Seaside-Component categories for a complete listing. They are all fairly simple, and how to use all of them is beyond the scope of this case. That said, here are a few examples of the items we used for M5.
html anchorWithAction: [self increase] text: '++'. "Hyperlink the text '++' to update the page after the block [self increase] has been executed" html space. "Insert a single space." html anchorWithAction: [self decrease] text: '--' "Hyperlink the text '--' to update the page after the block [self decrease] has been executed"
"Drop Down Menu" html selectFromList: (current slideTitles) selected: slideTitle callback: "Make a drop down menu from the slide titles, and have the default selected item be slideTitle" [:c | slideTitle _ c. current goToPage: (current slideTitles indexOf: c) ] "Whenever something is selected, execute this block" labels: [:slideName | slideName]. "have the labels for the menu items simply be the slide names" html space. "insert a single space" html submitButtonWithAction: [self jumpToSlide] text: 'Jump'. "insert a simple button, that has the text Jump and executes the block when you click it" "Hyperlink an Image" html anchorWithAction: [self showLargeImage] form: imageForm. "Hyperlink the image "imageForm" to execute the block" "Simple text input box" html form: [html text: 'Text Search: '. "Make a label that says 'Text Search:'" html textInputWithValue: 'text to search for' callback: [:val | self textSearch: val]. "execute the block sent to callback: with the text entered in the box once you click submit" html break. html submitButton] "make a simple submit button"One of the other nice features of Seaside is the call - return cycle. This cycle allows components to transfer control of the display back and forth. For information on call-answer and backtracking, see the following tutorial: Advanced Seaside
To start playing with your own creations, you'll need to look at the configuration app at http://localhost:9090/seaside/config. This is a link to the configuration utility, assuming you haven't changed any of the defaults. Here you will log in using the userid and the password you gave seaside when you installed it. You can then configure what paths will match up to what components and so forth. The best way to figure this out is to just play around with it. If you write a new component and want it to show up as an option in the config app, make sure you implement #canBeRoot on the class side to return true.
Some tutorials can be found at: