12 |
13 |
14 |
--------------------------------------------------------------------------------
/_support/templates/latex/chapter.mustache:
--------------------------------------------------------------------------------
1 | % -*- mode: latex; -*- mustache tags: {{=« »=}} «! the '&' below prevents HTML escaping. »
2 | \ifx\wholebook\relax\else
3 |
4 | \documentclass[10pt,twoside,english]{_support/latex/sbabook/sbabook}
5 | \usepackage{import}
6 | \subimport{_support/latex/}{common.tex}
7 |
8 | \hypersetup{pdfinfo = {
9 | Title = {«& title»},
10 | Author = {«& attribution»},
11 | Keywords = {pharo, smalltalk}}}
12 | \begin{document}
13 | \fi
14 |
15 | \chapter{«& title»}
16 | \chapterprecis{«& attribution»}
17 |
18 | «& content»
19 |
20 | \ifx\wholebook\relax\else
21 | \end{document}
22 | \fi
--------------------------------------------------------------------------------
/_support/templates/latex/no-sectioning.mustache:
--------------------------------------------------------------------------------
1 | % -*- mode: latex; -*-
2 | \ifx\wholebook\relax\else
3 |
4 | \documentclass[10pt,twoside,ustradelulu]{_support/latex/sbabook/sbabook}
5 | \usepackage{import}
6 | \subimport{_support/latex/}{common.tex}
7 |
8 | \begin{document}
9 | \fi
10 |
11 | {{=« »=}}
12 |
13 | «! the '&' below prevents HTML escaping. »
14 | «& content»
15 |
16 | \ifx\wholebook\relax\else
17 | \end{document}
18 | \fi
--------------------------------------------------------------------------------
/export-old-wiki/advanced.txt:
--------------------------------------------------------------------------------
1 | This part presents some aspects that you face when you deploy Seaside applications for real. It presents how to configure and deploy an application.
While Seaside keeps as much state on the server side as possible, it supports the creation and integration of REST web services as well. This part covers how to write a REST API and integrate it with an existing application.
Although Seaside does not offer a built-in persistency framework, the issue of how to manage your data is a common concern when building web applications. This part also covers a selection of approaches to managing data persistency in Smalltalk, and how these work with Seaside.
Finally, we present Magritte, which is a metadata framework with Seaside integration: using Magritte allows you to generate forms on the fly without hard-coding HTML or generating XML files.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/deployment.txt:
--------------------------------------------------------------------------------
1 | At some point you certainly want to go public with your web application. This means you need to find a server that is publicly reachable and that can host your Seaside application. If your application is successful, you might need to scale it to handle thousands of concurrent users. All this requires some technical knowledge.
In *ref:deployment-preparing* we are going to have a look at some best practices before deploying an application. Then in *ref:deployment-seasidehosting* we introduce Seaside-Hosting, a simple and free hosting service for non-commercial Seaside applications. Next, in *ref:deployment-apache* we present how to setup your own server using Apache. Last but not least, in *ref:maintaining*, we demonstrate ways to maintain a deployed image.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/deployment/deployment-apache.txt:
--------------------------------------------------------------------------------
1 | In this section we discuss a typical server setup for Seaside using Debian Linux as operating system. Even if you are not on a Unix system, you might want to continue reading, as the basic principles are the same everywhere. Due to the deviation of different Linux and Apache distributions, the instructions given here cannot replace the documentation for your particular target system.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/deployment/deployment-apache/install-vm.txt:
--------------------------------------------------------------------------------
1 | Depending on the Smalltalk dialect you are using, the installation of
the VM is different. Installing Squeak on a Debian system is simple.
Install Squeak by entering the following command on the terminal:
=$ sudo apt-get install squeak-vm
Note that installing and running Squeak does not require you to have the ''X Window System'' installed. Just tell the installer not to pull these dependencies in, when you are asked for it. Squeak remains runnable headless without a user-interface, this is what you want to do on most servers anyway. Up-to-date information on the status of the Squeak VM you find at *http://www.squeakvm.org/unix/*.
Now you should be able to start the VM. Typing the ==squeak== command executes a helper script that allows one to install new images and sources in the current directory, and run the VM. The VM itself can be started using the ==squeakvm== command.
=$ squeakvm -help
=$ squeakvm -vm-display-null imagename.image
You can find additional help on starting the VM and the possible command line parameters in the man pages:
=$ man squeak
In the next section we are going to look at how we can run the VM as a daemon.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/deployment/deployment-apache/preparing-server.txt:
--------------------------------------------------------------------------------
1 | Before getting started you need a server machine. This is a computer with a static IP address that is always connected to the Internet. It is not required that you have physical access to your machine. You might well decide to host your application on a virtual private server (VPS). It is important to note that you require superuser-level access to be able to run Smalltalk images. The ability to execute PHP scripts is not enough.
We assume that your server already has a working Linux installation.
In the following sections we use Debian Linux 5.0 (Lenny), however with
minor adjustments you will also be able to deploy applications on other
distributions.
Before starting with the setup of your application, it is important to make sure that your server software is up-to-date. It is crucial that you always keep your server up to the latest version to prevent malicious attacks and well-known bugs in the software.
To update your server execute the following commands from a terminal. Most commands we use in this chapter require administrative privileges, therefore we prepend them with sudo (super user do):
=$ sudo apt-get update
=$ sudo apt-get upgrade
=Reading package lists... Done
=Building dependency tree... Done
=0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/deployment/maintaining.txt:
--------------------------------------------------------------------------------
1 | If you followed all the instructions up to now, you should have a working Seaside server based on Seaside, Apache and some other tools. Apache is handling the file requests and passing on other requests to your Seaside application server. This setup is straightforward and enough for smaller productive applications.
As your web application becomes widely used, you want to regularly provide fixes and new features to your users. Also you might want to investigate and debug the deployed server. To do that, you need a way to get our hands on the running Smalltalk VM. There are several possibilities to do that, we are going to look at those in this section.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/deployment/maintaining/vnc.txt:
--------------------------------------------------------------------------------
1 | A common technique is to run a VNC server within your deployed image. VNC (Virtual Network Computing) is a graphical desktop sharing system, which allows one to visually control another computer. The server constantly sends graphical screen updates through the network using a remote frame buffer (RFB) protocol, and the client sends back keyboard and mouse events. VNC is platform independent and there are several open-source server and client implementations available.
+rfb|width=100%+
Pharo comes with a VNC client and server implementation, which can optionally be loaded. It is called ''Remote Frame Buffer (RFB)''. Unfortunately the project is not officially maintained anymore and the latest code is broken in Pharo, however you can get a working version from *http://source.lukas-renggli.ch/unsorted/*.
Install the RFB package, define a password and start the server. Now you are able to connect to the Pharo screen using any VNC client. Either using the built-in client from a different Pharo image, or more likely using any other native client. Now you are able to connect to the server image from anywhere in the world, and this even works if the image is started headless. This is very useful to be able to directly interact with server images, for example to update code or investigate and fix a problem in the running image.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/deployment/maintaining/window.txt:
--------------------------------------------------------------------------------
1 | Instead of running the VM headless as we did in *ref:/book/advanced/deployment/deployment-apache/run-vm*, it is also possible to run it headful as you do during development. This is common practice on Windows servers, but it is rarely done on Unix. Normally servers doesn't come with a windowing system for performance and security reasons. Managing a headful image is straightforward, so we will not be discussing this case further.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/magritte.txt:
--------------------------------------------------------------------------------
1 | Many applications consist of a large number of input dialogs and reports that need to be built, displayed and validated manually. Often these dialogs remain static after the development phase and cannot be changed unless a new development effort occurs. For certain kinds of application domains such as small businesses, changing business plans, modifying workflows, etc., it usually boils down to minor modifications to domain objects and behavior, for example new fields have to be added, configured differently, rearranged or removed. Performing such tasks is tedious.
Magritte is a meta-data description framework. With Magritte you describe your domain objects and among other things you can get Seaside components and their associated validation for free. Moreover Magritte is self-described, enabling the automatic generation of meta-editors which can be adapted for building end-user customizations of application.
In this chapter we describe Magritte, its design and how to customize it. Now be warned, Magritte is a framework supporting meta-data description. As any framework, mastering it takes time. It is not a scaffolding engine, therefore Magritte may imply some extra complexity and you have to understand when you want to pay for such complexity.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/magritte/custom-descriptions.txt:
--------------------------------------------------------------------------------
1 | In some cases it might happen that there is no description provided to use with a class. If your domain manipulates money (amount and currency) or URLs (scheme, domain, port, path, parameters) you may want to define your own descriptions (or load an extension package that already provides these descriptions) to take advantage of Magritte.
Extending Magritte is simple, create your own description but remember that Magritte is described within itself so you have to provide certain information.
- Create a subclass of ==MAElementDescription==.
- On the class-side override: ==isAbstract== to return false, ==label== to return the name of the description. On the instance-side override: ==kind== to return the base-class, ==acceptMagritte:== to enable visiting and ==validateSpecific:== to validate.
- Create a view, if you want to use it for UI building.
We suggest you have a look at existing descriptions. In addition, carefully choosing the right superclass can already provide you part of what you are looking for. Parsing, printing and (de)serialization is implemented by the following visitors: ==MAStringReader==, ==MAStringWriter==, ==MABinaryReader== and ==MABinaryWriter==.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/magritte/custom-views.txt:
--------------------------------------------------------------------------------
1 | Components control how your objects display. Some descriptions have an obvious one to one relationship with a UI component while others could easily be shown by several different components. *ref:views* shows some components. For example, an ==MAMemoDescription== would be represented by a text area, but a ==MABooleanDescription== could be a checkbox, or a drop down with true and false, or a radio group with true and false.
Each description defaults to a component, but allows you to override and specify any component you choose, including any custom one you may write using the message +index:componentClass:!componentClass:+ ==Description>>componentClass:==.
==aDescription componentClass: aClass
+views|width=70%+
You can also define your own view by following the steps:
- Create a subclass of ==MADescriptionComponent==.
- Override ==renderEditorOn:== and/or ==renderViewerOn:== as necessary.
- Use your custom view together with your description by using the accessor ==componentClass:==.
- Possibly add your custom view to its description into ==defaultComponentClasses==.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/magritte/exceptions.txt:
--------------------------------------------------------------------------------
1 | Since actions on the meta-model can fail. In addition, objects might not match a given meta-model. Finally it is often important to present to the end users readable error messages. Magritte introduces an exception hierarchy which knows about the description, the failure and a human-readable error message as shown in *ref:exceptions*.
+exceptions|width=80%+
--------------------------------------------------------------------------------
/export-old-wiki/advanced/magritte/summary.txt:
--------------------------------------------------------------------------------
1 | While Magritte is really powerful, using a meta-data system will add another indirection layer to your application, so this is important to understand how to use such power and when to just use normal development techniques. A good and small example to learn from is the Conrad conference management system developed to manage the ESUG conference available at *http://www.squeaksource.com/Conrad.html*. Here Magritte is used to describe the different forms and all the data. The Pier content management system is a more complex example of using Magritte, it can be downloaded at *http://www.piercms.com*.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/persistency/magma.txt:
--------------------------------------------------------------------------------
1 | Magma is an open-source object-oriented database developed entirely in Smalltalk. Magma provides transparent access to a large-scale shared persistent object model. It supports multiple users concurrently via optimistic locking. It uses a simple transaction protocol, including nested transactions, supports collaborative program development via live class evolution, peer-to-peer model sharing and Monticello integration. Magma supports large, indexed collections with robust querying, runs with pretty good performance and provides performance tuning mechanisms. Magma is fault tolerant and includes a small suite of tools. Magma can either work locally or on a remote Magma server. This means, multiple images can access the same database concurrently.
Magma provides safe access and management to multiple, large, interconnected models over the network, by multiple users, simultaneously. In keeping with the simplicity of the other frameworks, it ``just works\'' out of the box with comparably little API and learning curve. Developers will appreciate there is no need to inherit from a special superclass and no need to signal changed-notifications anywhere. There are a lot of options but the defaults will work fine without any consideration. Servers running when the image is closed and reopened are automatically restarted, connected clients are automatically reconnected. Recovery from hardware failures also occurs automatically, guaranteeing integrity.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/persistency/magma/remotely.txt:
--------------------------------------------------------------------------------
1 | If you want to use Magma in remote server mode you have to execute the following piece of code in a second image. This code launches the server. You have to specify where the repository will be located and the port used for the connection.
==MagmaServerConsole new
== open: 'todo';
== processOn: 51001;
== inspect
Do not close the inspector since you will use it to send the message ==shutdown== to stop the server. If you accidently close the inspect window you can execute something like this:
==MagmaServerConsole allInstancesDo:
== [:aServerConsole| aServerConsole shutdown]
To connect to the server, we will have to specify the port and possibly the address. The following methods show how to define a connection to the port 51001 on localhost.
==ToDoDB>>connect
== session := MagmaSession
== hostAddress: self localhost
== port: self defaultPort.
== session connectAs: 'user'
==ToDoDB>>localhost
== ^ #(127 0 0 1) asByteArray
==ToDoDB>>defaultPort
== ^ 51001
We just showed superficially the functionality offered by Magma. Magma offers much more such as optimized and large collections. We suggest you read the documentation of Magma that you can find at: *http://wiki.squeak.org/squeak/2665*.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/restful.txt:
--------------------------------------------------------------------------------
1 | +index:REST+ Seaside is not built around REST services by default, to increase programmer productivity and make to development much more fun. In some cases, it might be necessary to provide a REST API to increase the usability and interoperability of a web application though. Luckily Seaside provides a ''Seaside REST'' package to fill the gap and to allow one to mix both approaches.
In this chapter, we show how to integrate web applications with Seaside REST services. We start with a short presentation of REST. Then we define a simple REST service for the todo application we implemented in *ref:../../in-action/todo*. We finish this chapter by inspecting how HTTP requests and responses work. We want to thank Olivier Auverlot for providing us with an initial draft of this chapter in French.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/restful/conclusion.txt:
--------------------------------------------------------------------------------
1 | This chapter shows that while Seaside provides a powerful way to build dynamic application using a stateful approach, it can also seamlessly integrate with existing stateless protocols. This chapter illustrated that an object-oriented model of an application in combination with Seaside can be very powerful: You can develop flexible web interfaces as composable Seaside components, and you can easily enrich them with an API for interoperability with REST clients. Seaside provides you with the best of all worlds: the power of object-design, the flexibility and elegance of Seaside components, and the integration of traditional HTTP architectures.
A piece of advice:
- Do not use cookies with a REST service. Such service should respect the stateless philosophie of HTTP. Each request should be independent of others.
- During the development, organize your tagged methods following the HTTP commands: (GET, POST, PUT, DELETE, HEAD). You can use protocols to access them faster.
- A good service web should be able to produce different types of contents depending on the capabilities of the clients. Been able to produce different formats such as plain text (text/plain), XML (text/xml), or JSON (text/json) increases the interoperability of your web services.
You should now have a better understanding of the possibilities offered by Seaside-REST and be ready to produce nice web services.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/restful/getting-started.txt:
--------------------------------------------------------------------------------
1 | To get started load the package ==Seaside-Rest-Core==, and if you are on Pharo ==Seaside-Pharo-Rest-Core==. All packages are available from the ==Seaside30Addons== repository and you can load then easily with the following Gofer script:
==Gofer new
== squeaksource: 'Seaside30Addons';
== package: 'Seaside-REST-Core';
== package: 'Seaside-Pharo-REST-Core';
== package: 'Seaside-Tests-REST-Core';
== load.
Recent Seaside images already contain the REST packages preloaded.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/restful/getting-started/define-handler.txt:
--------------------------------------------------------------------------------
1 | We are going to extend the todo application from *ref:../../../../in-action/todo* with a REST API. We will first build a service that returns a textual list of todo items.
+index:WARestfulHandler+ Our REST handler, named ==ToDoHandler==, should be declared by defining a Seaside class which inherits from ==WARestfulHandler==. This way we indicate to Seaside that ==ToDoHandler== is a REST handler. The todo items will be accessed through the same model as the existing todo application: ==ToDoList default==. This means we do not need to specify additional state in our handler class.
==WARestfulHandler subclass: #ToDoHandler
== instanceVariableNames: ''
== classVariableNames: ''
== poolDictionaries: ''
== category: 'ToDo-REST'
@@note With Seaside-REST, we do not subclass from ==WAComponent== that is reserved to the generation of stateful graphical components, but you should subclass from WARestfulHandler.
Last we need to initialize our hander by defining a class-side initialization method. We register the handler at the entry point ==todo-api== so that it is reachable at *http://localhost:8080/todo-api*. Don't forget to call the method to make sure the handler is properly registered.
==ToDoHandler class>>initialize
== WAAdmin register: self at: 'todo-api'
--------------------------------------------------------------------------------
/export-old-wiki/advanced/restful/matching.txt:
--------------------------------------------------------------------------------
1 | In the initial example we have seen how to define a service that catches all GET requests to the handler. In the following sections we will look at defining more complicated services using more elaborate patterns. In *ref:http-method* we are going to look at matching other request types, such as POST and PUT. In *ref:content-type* we are going to see how to serve different content types depending on the requested data. In *ref:request-path* we will see how to match path elements and in *ref:query-parameters* how to extract query parameters.
--------------------------------------------------------------------------------
/export-old-wiki/advanced/restful/matching/priorities.txt:
--------------------------------------------------------------------------------
1 | Sometimes there are several methods which Seaside-REST could choose for a request, here's how it finds the "best" one:
# Exact path matches like ==/index.html== take precedence over partial ==/index.{var}== or =={var}.html== or wildcard ones =={var}==.
# Partial path matches like ==/index.{var}== or =={var}.html== take precedence over wildcard ones =={var}==.
# Partial single element matches =={var}== take precedence over multi element matches ==\*var\*==.
# Exact mime type matches like ==text/xml== take precedence over partial ==\*/xml== or ==xml/\*==, wildcard ==\*/\*== and missing ones.
# Partial mime type matches like ==\*/xml== or ==xml/\*== take precedence over wildcard ones ==\*/\*== or missing ones.
# If the user agent supplies quality values for the Accept header, then that is taken into account as well.
--------------------------------------------------------------------------------
/export-old-wiki/components/calling.txt:
--------------------------------------------------------------------------------
1 | Seaside applications are based on the definition and composition of components. Each component is responsible for its rendering, its state and its own control flow. Seaside lets us freely compose and ''reuse'' such components to create advanced and dynamic applications. You have already built several components. In this chapter, we will show how to reuse these components by ``calling\'' them in a modal way. Embedding components in other components will be discussed in the following chapter.
--------------------------------------------------------------------------------
/export-old-wiki/components/calling/dont-call-while-rendering.txt:
--------------------------------------------------------------------------------
1 | One of the most common mistakes for first-time Seaside developers is to send the message ==call:== a component from another component's rendering method, ==renderContentOn:==. The rendering method's purpose is ''rendering''. Its only job is to display the current state of the component. Callbacks are responsible for changing state, calling other components, etc. If you want to render one component inside another one read *ref:/book/components/embedding*.
@@important Don't ==call:== a component from ==renderContentOn:==, only call components from callbacks or from ==WATask== subclasses.
--------------------------------------------------------------------------------
/export-old-wiki/components/calling/modal-display.txt:
--------------------------------------------------------------------------------
1 | Seaside components have the ability to specify that another component should be rendered (usually temporarily) in their place. This mechanism is triggered by the message ==call:==. During callback processing, a component may send the message ==call:== with another component as an argument. The component passed as an argument in this way can be referred to as the ''delegate''. The ==call:== method has two effects:
# In subsequent rendering cycles, the delegate will be displayed in place of the original component. This continues until the delegate sends the message +index:WAComponent!answer+ ==WAComponent>>answer== to itself.
# The current execution state of the calling method is suspended and does not return a value yet. Instead, Seaside renders the web page in the browser (showing the delegate in place of the original component).
The delegate may be a complex component with its own control flow and state. If the delegate component later sends the message ==answer==, then execution of the (currently suspended) calling method is resumed at the site of the ==call:==. We will explain this mechanism in detail after an example.
@@important From the point of view of a component, it calls another component and that component will (eventually) answer.
--------------------------------------------------------------------------------
/export-old-wiki/components/calling/sequencing.txt:
--------------------------------------------------------------------------------
1 | As we just showed, calling is a ''modal'' interaction, that is, the method ==call:== doesn't return until the component it called answers. That allows us to sequence component display.
==ContactListView>>editContact: aContact
== | view |
== view := ContactView new.
== view contact: aContact.
== self call: view.
== self inform: 'Thanks for editing ' , aContact name
Let's suppose that you have redefined the method ==editContact:== as shown above. The method calls the view component and then, after the view answers, it displays a message. Here's something to wrap your brain around. What if the user fills in the form, presses the ''Save'' button, then presses ''Back'' and changes the values in the form and saves again? After the first save, the above method calls +index:WAComponent!inform:+ ==WAComponent>>inform:== but when the user presses ''Back'' your method backs up into the ==call:== of ==ContactView==.
What Seaside does is the following: It snapshots the state of execution of your method so that it can jump back in response to the ''Back'' button. We'll go into much more detail about this later in *ref:/book/components/calling/back-button*, For now just try it and confirm that things work as you'd expect.
--------------------------------------------------------------------------------
/export-old-wiki/components/calling/summary.txt:
--------------------------------------------------------------------------------
1 | In this chapter we showed how to display component using the ==call:== method. In the next chapter we will demonstrate how to embed components within each other.
--------------------------------------------------------------------------------
/export-old-wiki/components/embedding.txt:
--------------------------------------------------------------------------------
1 | Building reusable components and frameworks is the goal of all developers in almost all parts of their applications. The dearth of truly reusable (canned) component libraries for most of the existing web development frameworks is a good indication that this is difficult to do.
Seaside is among the few frameworks poised to change this. It has a solid component model giving one all of the mechanisms necessary to develop well encapsulated components and application development frameworks. We have seen in *ref:../calling/modal-display* that components can be sequenced. In this chapter we show how to embed one component inside another component. In *ref:decorations*, we will see how to decorate a component to add functionality or change its appearance and as such reuse behavior. With a good component model, the possibility to display components and create new ones by reusing existing ones, writing Seaside applications is very similar to writing GUI applications.
We will start by writing an application which embeds one component, then refactor it into an application built out of two components. Finally we will discuss reuse and show how component decoration support this. We will show how components can be plugged together using events to maximize reuse.
--------------------------------------------------------------------------------
/export-old-wiki/components/embedding/decorations/behavioral-decorations.txt:
--------------------------------------------------------------------------------
1 | ""Validation."" A +index:WAValidationDecoration+ ==WAValidationDecoration== validates its component form data when the component returns using ==WAComponent>>answer== or ==WAComponent>>answer:==. This decoration can be added to a component via the method ==WAValidationDecoration>>validateWith:== as shown below.
==SampleLoginComponent>>initialize
== super initialize.
== form := WAFormDecoration new buttons: self buttons.
== self addDecoration: form.
== self validateWith: [ :answer | answer validate ].
== self addMessage: 'Please enter the following information'.
If the component returns via ==answer:==, the ==answer:== argument is passed to the validate block. If the component returns using ==answer== the sender of ==answer== is passed to the validate block.
@@todo Talk about ==WADelegation== and ==WAAnswerHandler==.
""Accessing the component."" To access the component when you have only a reference to its decoration you can use the message +index:WADecoration!decoratedComponent+ ==WADecoration>>decoratedComponent==.
--------------------------------------------------------------------------------
/export-old-wiki/components/embedding/intercepting-answer.txt:
--------------------------------------------------------------------------------
1 | Components may be designed to support both standalone and embedded use. Such components often produce answers (send ==self answer:==) in response to user actions. When the component is standalone the answer is returned to the caller, but if the component is embedded the answer is ignored unless the parent component arranges to intercept it. In our example application the editor provides an answer when the user presses the ``Save\'' button (i.e. in ==ContactView>>save==) but this answer is ignored. It is easy to change our application to make use of this information; let's say we want to give the user confirmation that their data was saved. To accomplish this, change ==IAddress>>initialize== and add the +index:WAComponent!onAnswer:+ ==WAComponent>>onAnswer:== behaviour:
==IAddress>>initialize
== super initialize.
== editor := ContactView new.
== editor contact: self contacts first.
== editor onAnswer: [ :answer | self inform: 'Saved' ] " <-- added "
Now restart your application (press ``New Session\'') and try it out. When you press the save button in the editor you should get a dialog tersely notifying you that your data is saved. Note that the component answer is passed into the block (although we didn't use it in this example).
The ==onAnswer:== method is an important protocol for handling components and their answer.
--------------------------------------------------------------------------------
/export-old-wiki/components/embedding/summary.txt:
--------------------------------------------------------------------------------
1 | In this chapter we have seen how to embed components to build up complex functionality. In particular, we have learned:
- To embed a component in another one, the parent component should just answer the component as one of its children. Its ==children== method should return the direct children components.
- Each component may render its immediate children in its own render method by calling various methods and possibly the ==render:== method.
- A component may be reused with decorations. Decorations are components which add visual aspects or change component behavior.
--------------------------------------------------------------------------------
/export-old-wiki/components/slime.txt:
--------------------------------------------------------------------------------
1 | This short chapter explains how you can improve the quality of your code and your programming skills in general by running ''Slime'', a Seaside-specific code critics tool. For example, Slime can detect if you do not follow the canonical forms for brush usage that we presented in *ref:/book/fundamentals/rendering-components*. It will also help you identify other potential bugs early on, and help you produce better code. Furthermore, if you work on a Seaside library, it is able to point out portability issues between the different Smalltalk dialects.
--------------------------------------------------------------------------------
/export-old-wiki/components/slime/summary.txt:
--------------------------------------------------------------------------------
1 | Slime offers the validation of your code and it will verify some coding practices. Once again, we suggest you run this tool often. This tools as well as your unit tests and the debugger are your best friends to produce good quality code.
--------------------------------------------------------------------------------
/export-old-wiki/components/tasks.txt:
--------------------------------------------------------------------------------
1 | In Seaside, it is possible to define components whose responsibility is to represent the flow of control between existing components. These components are called ''tasks''. In this chapter, we explain how you can define a task. We also show how Seaside supports application control flow by isolating certain paths from others. We will start by presenting a little game, the number guessing game. Then, we will implement two small hotel registration applications using the calendar component to illustrate tasks.
--------------------------------------------------------------------------------
/export-old-wiki/components/tasks/summary.txt:
--------------------------------------------------------------------------------
1 | In this chapter, we presented tasks, subclasses of ==Task==. Tasks are components that do not render themselves but are used to build application flow based on the composition of other components. We saw that the composition is expressed in plain Smalltalk.
--------------------------------------------------------------------------------
/export-old-wiki/cover/cover.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/cover/cover.ai
--------------------------------------------------------------------------------
/export-old-wiki/cover/figures/cincom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/cover/figures/cincom.jpg
--------------------------------------------------------------------------------
/export-old-wiki/cover/figures/esug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/cover/figures/esug.png
--------------------------------------------------------------------------------
/export-old-wiki/cover/figures/gemstone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/cover/figures/gemstone.png
--------------------------------------------------------------------------------
/export-old-wiki/cover/figures/inceptive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/cover/figures/inceptive.png
--------------------------------------------------------------------------------
/export-old-wiki/figures/AnnotatedSeasideApplicationDesk.graffle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/figures/AnnotatedSeasideApplicationDesk.graffle
--------------------------------------------------------------------------------
/export-old-wiki/figures/CSSStructure.graffle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/figures/CSSStructure.graffle
--------------------------------------------------------------------------------
/export-old-wiki/figures/StringHierarchy.graffle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/figures/StringHierarchy.graffle
--------------------------------------------------------------------------------
/export-old-wiki/figures/WAHeadingTag.graffle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/figures/WAHeadingTag.graffle
--------------------------------------------------------------------------------
/export-old-wiki/figures/deploy-url.graffle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/figures/deploy-url.graffle
--------------------------------------------------------------------------------
/export-old-wiki/figures/describingAddress.graffle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/figures/describingAddress.graffle
--------------------------------------------------------------------------------
/export-old-wiki/figures/inspector2.graffle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/figures/inspector2.graffle
--------------------------------------------------------------------------------
/export-old-wiki/figures/inspectorNavigation.graffle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/export-old-wiki/figures/inspectorNavigation.graffle
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals.txt:
--------------------------------------------------------------------------------
1 | In this part we will introduce you to the manipulation of basic elements such as texts, anchors and callbacks as well as forms. It presents the notion of ''brushes'' that is central to the Seaside API. Understanding these concepts will be fundamental to your use of Seaside.
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/anchors/adding-contact.txt:
--------------------------------------------------------------------------------
1 | We will modify the render method so that we can add a contact to our database, as follows. We add a callback associated with the text 'Add contact':
==ContactListView>>renderContentOn: html
== html anchor
== callback: [ self addContact ];
== with: 'Add contact'.
== html unorderedList: [
== Contact contacts do: [ :contact |
== html listItem: [ self renderContact: contact on: html ] ] ]
==ContactListView>>addContact
== | name emailAddress |
== name := self request: 'Name'.
== emailAddress := self request: 'Email address'.
== Contact addContact: (Contact name: name emailAddress: emailAddress)
You should now have the Add contact link as shown in *ref:contacts-listing-with-add*.
+contacts-listing-with-add|width=90%+
Here we've made use of the +index:WAComponent!request:+ ==WAComponent>>request:== method to display a message for the user to enter a name, then another message for them to enter an email address. We will discuss the ==request:== method in *ref:/book/components*. Note that a real application would present a form with several fields to be filled up by the user.
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/anchors/anchors-to-callbacks.txt:
--------------------------------------------------------------------------------
1 | You can generate run-of-the-mill HTML anchors by creating an anchor brush (send +index:WAHtmlCanvas!anchor+ ==WAHtmlCanvas>>anchor== to the canvas), then configuring the anchor to be associated with a URL using +index:WAAnchorTag!url:+ ==WAAnchorTag>>url:== and specifying the text for the anchor using ==WAAnchorTag>>with:==. Here is a simple component that displays an anchor that displays a link to the Seaside web site.
==WAComponent subclass: #SimpleAnchor
== instanceVariableNames: ''
== classVariableNames: ''
== poolDictionaries: ''
== category: 'SeasideBook-Anchors'
==SimpleAnchor>>renderContentOn: html
== html anchor
== url: 'http://www.seaside.st';
== with: 'Seaside Website'
Register this component as ``simple-anchor\'' then view the component through your browser and you should see a page similar to *ref:anchor-1*.
+A simple anchor>anchor-1|width=90%+
Clicking on the ''Seaside Website'' anchor will bring you to the website.
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/anchors/mailto-anchor.txt:
--------------------------------------------------------------------------------
1 | In this section, we add ``mailto:\'' links to our ==ContactListView==. Users of our application can then simply click on the e-mail address to send an e-mail, assuming that their web browser is properly configured to respond to ==mailto:== links. As discussed in *ref:/book/fundamentals/anchors/anchors-to-callbacks*, we can specify the URL for an anchor explicitly. Here is the modified version of our rendering method:
==ContactListView>>renderContact: aContact on: html
== html text: aContact name.
== html space.
== html anchor
== url: 'mailto:' , aContact emailAddress;
== with: aContact emailAddress.
== html text: ' ('.
== html anchor
== callback: [ self removeContact: aContact ];
== with: 'remove'.
== html text: ')'
Test this new component in your browser to see that your mailto: links are working correctly, see *ref:contacts-listing-with-removeandMail*.
+contacts-listing-with-removeandMail|width=90%+
Note that rather than manipulating strings in this way, experienced Smalltalkers might want to actually define an ``email address\'' class to handle the different representations of email addresses. In fact, Seaside 3.0 already defines a class WAEmailAddress which may be used for this very purpose.
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/anchors/summary.txt:
--------------------------------------------------------------------------------
1 | In this chapter you saw callbacks, a powerful feature of Seaside. Using a callback, we can attach an action or a small program to a link or button that will be executed only when the element is activated. What is really powerful is that you can write any Smalltalk code in a callback. In the next chapter, we will continue to enhance the iAddress application to show you how to handle forms.
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/css.txt:
--------------------------------------------------------------------------------
1 | In this chapter we present CSS in a nutshell and show how Seaside helps you to use CSS in your applications. The goal of the chapter is not to replace CSS tutorials, many of which can be found on the web. Rather, the goal is to establish some basic principles and show how Seaside facilitates the decoupling of information and its visual presentation in web browsers. A clear separation between the page components and their rendering is really central to Seaside. Sometimes this frustrates newcomers because Seaside does not use template mechanisms for rendering. However, the Seaside approach allows the clear separation between the responsibilities of the web designer and the web developer. The developer is not responsible for rendering and layout of the application, this is the job of the web designer.
The idea behind CSS is to decouple the presentation from the document itself. The tags in a document are interpreted using a CSS (Cascading Style Sheet) which defines the layout and style of the rendered document. In the context of Seaside, the component rendering methods generate XHTML and the CSS associated with the application specifies how such components should be displayed and placed on the page.
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/css/selectors.txt:
--------------------------------------------------------------------------------
1 | CSS allows you to select individual elements of an XHTML document, or groups of elements that share some property. Let's look at the different kind of selectors and how they can be used.
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/css/selectors/pseudo-class.txt:
--------------------------------------------------------------------------------
1 | Pseudo classes are similar to CSS classes, but they don't appear in the XHTML source code. They are automatically applied to elements by the web browser, if certain conditions apply. These conditions can be related to the content, or to the actions that the user is carrying out while viewing the page. To distinguish pseudo classes from normal CSS selectors they all start with a colon.
=:focus { background-color: yellow; }
=:hover { font-weight: bold; }
The first rule specifies that elements (typically input fields of a form) get a yellow background, if they have focus. The second rule specifies that all elements will appear in bold while the mouse cursor hovers over them.
The following table gives a brief overview of pseudo classes supported by most of today's browsers:
|{ ==:active== | Matches an activated element, e.g. a link that is clicked.
|{ ==:first-child== | Matches the first child of another element.
|{ ==:first-letter== | Matches the first character within an element.
|{ ==:first-line== | Matches the first line of text within an element.
|{ ==:focus== | Matches an element that has the focus.
|{ ==:hover== | Matches an element below the mouse pointer.
|{ ==:link== | Matches an unvisited link.
|{ ==:visited== | Matches a visited link.
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/css/selectors/reference.txt:
--------------------------------------------------------------------------------
1 | A reference or ID is the name of ''a particular'' XHTML element on the page. Thus, the given style will affect only the element with the unique ID ==error== (if defined). The ID selector is indicated by prefixing the ID with a ==#== character:
=#error { background-color: red; }
To create a tag with the given ID use the following Seaside code:
==html div
== id: 'error';
== with: 'Some error message'
The generated XHTML code looks like this:
=
Some error message
There are a couple of issues to be aware of when using IDs in your XHTML. IDs have to be unique on a XHTML page. If you use the same ID multiple times, some web browsers may not render your page as you expect, or may even refuse to render it at all. Furthermore some Javascript libraries dynamically apply their own IDs to identify page elements and these may override your carefully chosen IDs, causing your styling to fail in mysterious ways. See *ref:/book/web-20* on Javascript programming.
@@important So, to avoid invalid XHTML and conflicts with JavaScript code, do not use IDs for styling. Exclusively use CSS classes for styling, even if the particular style is used only once.
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/css/selectors/tag.txt:
--------------------------------------------------------------------------------
1 | The tag selector applies to specific XHTML tags, as we saw in the previous examples. The selector consists simply of the tag name as it appears in the XHTML source, but without the angle brackets. The following example removes the underlining from all anchor elements and changes the base font-size of the text within the page to 20 points. The ==body== tag is one of the top-level tags automatically created by Seaside enclosing the whole page.
=a { text-decoration: none; }
=body { font-size: 20pt; }
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/css/summary.txt:
--------------------------------------------------------------------------------
1 | Styling web applications is a broad topic. This chapter has shown you the most important things to get started. For most people this will be enough to get a decent looking prototype up and running. For commercial applications you will often hire a graphic designer with experience of designing web pages. Once such designers have worked with you on the desired look and feel of your pages, they can provide you with a purpose built style-sheet. Using the techniques described in this chapter you will be able to integrate such style-sheets with the content generated by your application to make it look beautiful.
We have found the following two documents to be helpful in learning more about XHTML and CSS:
|{ XHTML Specification | *http://www.w3.org/TR/xhtml1/*
|{ CSS Level 2 Specification | *http://www.w3.org/TR/REC-CSS2/*
There are many CSS resources on the web. We've accumulated a long list but here are a few that stand out as sites that we repeatedly visit.
|{ CSS Zen Garden | *http://www.csszengarden.com/*
|{ A List Apart | *http://www.alistapart.com/*
|{ Blueprint CSS | *http://www.blueprintcss.org/*
|{ The Layout Reservoir | *http://www.bluerobot.com/web/layouts/*
|{ Subtraction | *http://www.subtraction.com/*
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/forms.txt:
--------------------------------------------------------------------------------
1 | +index:forms+
In this chapter, we describe how to use XHTML forms and controls in Seaside. ''Controls'' such as text input fields, popup lists, radio buttons, check boxes, date inputs, and buttons are always created within an XHTML ==form== element. In this chapter we show how to create this ==form== element and how to use these common controls.
--------------------------------------------------------------------------------
/export-old-wiki/fundamentals/forms/formsummary.txt:
--------------------------------------------------------------------------------
1 | Seaside makes it easy to display forms with buttons, popup lists, checkboxes, etc. It is easy in part because of the callbacks that it uses to inform you of the value of these items. In *ref:/book/fundamentals/anchors*, we saw how callbacks are used with anchors. Seaside uses the power of callbacks to make your job much easier.
--------------------------------------------------------------------------------
/export-old-wiki/in-action.txt:
--------------------------------------------------------------------------------
1 | This part develops two little applications \-- a todo list manager and a sudoku player. Then it presents how to serve files in Seaside as well as character encodings and how to customize sessions to hold application centric information.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/serving-files.txt:
--------------------------------------------------------------------------------
1 | Most web-based applications make heavy use of static resources. By ``static\'' we mean resources whose contents are not sensitive to the context in which they are used. These resources are not dependent on the user or session state and while they may change from time to time they typically don't change during the time span of a single user's session. Static resources include for example images, style sheets and JavaScript files.
Using these resources in a Seaside application need be no different from using them in any other web application development framework: when deploying your application you can serve these resources using a web server and reference them in your Seaside application, as described in *ref:/book/advanced/deployment*.
In addition, Seaside supports a more tightly integrated file serving technique, called ''FileLibrary'', which has some advantages over using a separate web server. In this chapter we will cover how to reference external resources and how to use the integrated FileLibrary to serve them from your Smalltalk image. Note that using FileLibrary to serve static resources is often slower than using a dedicated web server. In *ref:/book/advanced/deployment* we explain how to serve static files in a more efficient way using Apache.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/serving-files/character-encodings.txt:
--------------------------------------------------------------------------------
1 | Character encoding is an area that we programmers tend to avoid as much as possible, often fixing problems by trial and errors. With web-development you will sooner or later be bitten by character encoding bugs, no matter how you try to escape them. As soon as you are getting inputs from the user and displaying information in your web-browser, you will be confronted with character encoding problems. However, the basic concepts are simple to understand and the difficulty often lies in the extra layers that typically a web developer does not have to worry about such as the web-rendering engine, the web server and the input keyboard.
Historically the difference between character sets and character encoding was minor, since a standard specified what characters were available as well as how they encoded. Unicode and ISO 10646 (Universal Character Set) changed this situation by clearly separating the two concepts. Such a separation is essential: on one hand you have the character sets you can manipulate and on the other hand you have how they are represented physically (encoded).
In this section we'll present the two basic concepts you have to understand -'' character sets'' and ''character encodings''. This should help you avoid most problems. Then we will tell you how these are supported in Seaside.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/serving-files/filelibraries.txt:
--------------------------------------------------------------------------------
1 | Since version 2.7, Seaside has included a library for serving files called ''FileLibrary''. This solution is handy for rapid application development and is suitable for deployed applications which only make use of a small number of small files. It has the advantage that all of the resources are contained in your Smalltalk image and can be versioned with your favorite Smalltalk version management tools. However this also means that these resources are ""not"" reachable where most of your operating system's tools are accustomed to find things.
FileLibrary has the primary advantage that it is a portable way to serve static contents directly from Seaside without the need to setup a standalone web server. See *ref:/book/advanced/deployment* to read about Apache configuration for static file serving.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/serving-files/filelibraries/including.txt:
--------------------------------------------------------------------------------
1 | How you use a file library depends on what you want to do with the files in it. As you've seen in the previous sections, using image, music, style sheets and JavaScript files requires knowing their URL. You can find the URL of any document in your file library by sending the class ==WAFileLibrary class>>urlOf:==. For example, if you had added the file ==picture.jpg== to your library and you want to display it in a component you would write something like:
==MyClass>>renderContentOn: html
== html image url: (MyFileLibrary urlOf: #pictureJpg)
The URL returned by +index:urlOf:!urlOf:+ ==urlOf:== is relative to the current server. It does not contain the *http://servername.com/* - the so-called ``method'' and ``host'' - portion of the URL. Note that WAFileLibrary implements a class method called ==/==, so the expression ==MyFileLibrary / #pictureJpeg== is equivalent to ==MyFileLibrary urlOf: #pictureJpeg==.
Once you know the URL of the FileLibrary resources you can use them to include style sheets and JavaScript in your components as we have already discussed.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/serving-files/what-method.txt:
--------------------------------------------------------------------------------
1 | You have the following choices for serving static files with your Seaside application:
- The default answer is pretty simple: if you don't know anything about web servers, use ==FileLibrary==.
- If you want to have your static resources versioned inside your Smalltalk image and don't have too many (or too large) resources, use ==FileLibrary==.
- If you prefer to keep your static resources on your file system where you can edit and version them with your favorite file-based tools but you don't want to run a separate web server, go read about how to serve static content from your image in *ref:/book/in-action/serving-files*.
- Otherwise read *ref:/book/advanced/deployment/deployment-apache* about Apache file serving and configuration.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/session.txt:
--------------------------------------------------------------------------------
1 | When a user interacts with a Seaside application for the first time, a new ''session'' object is automatically instantiated. This instance lasts as long as the user interacts with the application. Eventually, after the user has not interacted with the session for a while, it will time-out \-- we say that the session ''expires''. The session is internally used by Seaside to remember page-views and action callbacks. Most of the time developers don't need to worry about sessions.
In some cases the session can be a good place to keep information that should be available globally. The session is typically used to keep information about the current user or open database connections. For simple applications, you might consider keeping that information within your components. However, if big parts of your code need access to such objects it might be easier to use a custom session class instead.
Having your own session class can be also useful when you need to clean-up external resources upon session expiry, or when you need extra behavior that is performed for every request.
In this chapter you will learn how to access the current session, debug a session, define your own session to implement a simple login, recover from session expiration, and how to define bookmarkable urls.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/session/current-session.txt:
--------------------------------------------------------------------------------
1 | +index:WAComponent!session+
From within your components the current session is always available by sending ==self session==. This can happen during the rendering phase or while processing the callbacks: you get the same object in either case. To demonstrate a way to access the current session, quickly add the following code to a rendering method in your application:
==html anchor
== callback: [ self show: (WAInspector current on: self session) ];
== with: 'Inspect Session'
This displays a link that opens a Seaside inspector on the session. Click the link and explore the contents of the active session. To get an inspector within your image you can use the code ==self session inspect==. In both cases you should be able to navigate through the object.
In rare cases it might be necessary to access the current session from outside your component tree. Think twice before doing that though: it is considered to be extremely bad coding style to depend on the session from outside your component tree. Anyway, in some cases it might come in handy. In such a case, you can use the following expressions: +index:WACurrentSession+ +index:WARequestContext+
==WARequestContext value session.
But again you should avoid accessing the session from outside of the component tree.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/session/debugger.txt:
--------------------------------------------------------------------------------
1 | In older versions of Seaside, session objects could not be inspected from the debugger as normal objects. If you tried to evaluate ==self session== the debugger would answer ==nil== instead of the expected session object. This is because sessions are only accessible from within your web application process, and the Smalltalk debugger lives somewhere else. In Seaside 3.0 this problem is fixed on most platforms.
If this doesn't work for you, then you need to use a little workaround to access the session from within the debugger. Put the following expression into your code to open an inspector from within the web application and halt the application by opening a debugger:
==self session inspect; halt
--------------------------------------------------------------------------------
/export-old-wiki/in-action/session/manually-expire.txt:
--------------------------------------------------------------------------------
1 | In some cases developers might want to expire a session manually. This is useful for example after a user has logged out, as it frees all the memory that was allocated during the session. More important it makes
it impossible to use the ''Back'' button to get into the previously authenticated user-account and do something malicious.
A session can be marked for expiry by sending the message ==WASession>>expire== +index:WASession!expire+ to a ==WASession==. Note that calling ==expire== will not cause the session to disappear immediately, it is just marked as expired and not accessible from the web anymore. At a later point in time Seaside will call ==unregistered== and the garbage collector eventually frees the occupied memory.
Let us apply it to our hotel application: we change our MiniInn application to automatically expire the session when the user logs out.
==InnSession>>logout
== user := nil.
== self expire
Note that expiring a session without redirecting the user to a different location will automatically start a new session within the same application. Here we change that behavior to make it point to the Seaside web site as follows.
==InnSession>>logout
== user := nil.
== self expire.
== self redirectTo: 'http://www.seaside.st'
If the user tries to get back to the application, he is automatically redirected to a new session.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/session/summary.txt:
--------------------------------------------------------------------------------
1 | Sessions are Seaside's central mechanism for remembering user specific interaction state. Sessions are identified using the ==_s== parameter in the URL. As an application developer there is normally no need to access or change the session, because it is used internally by Seaside to manage the callbacks and to store the component tree. In certain cases it might be useful to change the behavior of the default implementation or to make information accessible from anywhere in the application.
Pay attention that if components depend on the presence of a specific session class, you introduce strong coupling between the component and the session. Such sessions act as global variables and should not be overused.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/sudoku.txt:
--------------------------------------------------------------------------------
1 | In this chapter we will build a Sudoku web application as shown in *ref:upto6*. This gives us another opportunity to revisit how we build a simple application in Seaside.
+upto6|width=60%+
--------------------------------------------------------------------------------
/export-old-wiki/in-action/sudoku/solver.txt:
--------------------------------------------------------------------------------
1 | For the Sudoku model we use the ML-Sudoku package developed by Martin Laubach which is available on SqueakSource. We thank him for allowing us to use this material. To load the package, open a Monticello browser and click on the ''\+Repository'' button. Select HTTP as the type of repository and specify it as follows:
==MCHttpRepository
== location: 'http://www.squeaksource.com/MLSudoku'
== user: ''
== password: ''
Click on the ''Open'' button, select the most recent version and click ''Load''.
ML-Sudoku is composed of 4 classes: ==MLSudoku==, ==MLBoard==, ==MLCell==, and ==MLPossibilitySet==. The class responsibilities are distributed as follows:
- ==MLSudoku== is the Sudoku solver. It knows how to solve a Sudoku.
- ==MLCell== knows its neighbors and their location on the game board. A cell does not know its possibility set, see ==MLPossibilitySet== below.
- ==MLBoard== contains the cells and their possibility sets.
- == MLPossibilitySet== is a list of possible numbers between 1 and 9 that can go into a cell. These are the values that are possible without violating the Sudoku rule that each row, column and 3-by-3 sub-grid contains each number once.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/sudoku/summary.txt:
--------------------------------------------------------------------------------
1 | While the Sudoku solver introduces some subtleties because of its backtracking behavior, this application shows the power of Seaside to manage state.
Now you have a solid basis for building a really powerful Sudoku online application. Have a look at the class ==MLSudoku==. Extend the application by loading challenging Sudoku grids that are defined by a string.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/todo.txt:
--------------------------------------------------------------------------------
1 | The objective of this chapter is to highlight the important issues when building a Seaside application: defining a model, defining a component, rendering the component, adding callbacks, and calling other components. This chapter will repeat some elements already presented before but within the context of a little application. It is a kind of summary of the previous points.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/todo/summary.txt:
--------------------------------------------------------------------------------
1 | You have briefly reviewed all the key mechanisms offered by Seaside to build a complex dynamic application out of reusable components. You can either invoke another component or compose a component out of existing ones. Each component has the responsibility to render itself and return its subcomponents.
--------------------------------------------------------------------------------
/export-old-wiki/in-action/todo/todoview.txt:
--------------------------------------------------------------------------------
1 | First, we define a component to see the item list. For that, we define a new component named ==ToDoListView==.
==WAComponent subclass: #ToDoListView
== instanceVariableNames: ''
== classVariableNames: ''
== poolDictionaries: ''
== category: 'ToDo-View'
We can register the application by defining the class method ==initialize== as shown and by executing ==ToDoListView>>initialize==.
==ToDoListView class>>initialize
== "self initialize"
== WAAdmin register: self asApplicationAt: 'todo'
You can see that the todo application is now registered by pointing your browser to *http://localhost:8080/config/* as shown in *ref:todoregistered*.
+todoregistered|width=40%+
If you click on the todo link in the config list you will get an empty browser window. This is to be expected since so far the application does not do any rendering. Now if you click on the halo you should see that your application is present on the page as shown in *ref:halosOnEmptyTodo*.
+halosonemptytodo|width=80%+
Now we are ready to work on the rendering of our component.
--------------------------------------------------------------------------------
/export-old-wiki/introduction.txt:
--------------------------------------------------------------------------------
1 | Seaside is an excellent framework for easily developing advanced and dynamic web applications. Seaside lets you create reusable components that you can freely compose using Smalltalk \-- a simple and pure object-oriented language.
Seaside offers a powerful callback mechanism that lets you trigger code snippets when the users clicks on a link. With Seaside, you can debug your web application with a powerful dynamic debugger and modify the code on the fly while your server is running. This makes the development of complex dynamic applications smooth and fast.
With Seaside, you have the time to focus on your design and solutions to your problems. In this chapter, we give an overview of Seaside and present some Smalltalk basics to help you to follow along with the book. In the *next chapter>../getting-started*, we will show you how ''you'' can program your first Seaside component in just 15 minutes.
--------------------------------------------------------------------------------
/export-old-wiki/introduction/online-book.txt:
--------------------------------------------------------------------------------
1 | A free online version of this book is available at *book.seaside.st>http://book.seaside.st*. The online version is always up-to-date and permits readers to add notes at the bottom of every page. This immediately notifies other readers of problems and helps us to quickly resolve remaining issues. We will regularly go through the notes and address the issues raised in the main text.
The complete book is written using the Pier content management system that itself is written using Seaside. The PDF version of the book is automatically rebuilt every night from the contents of the website.
The online version of the book can be navigated using the following keyboard shortcuts. This allows you to quickly navigate the contents of the book.
|{!Keys |{! |{!Action
| ==k== | ''left-arrow'' | Previous Page
| ==j== | ''right-arrow'' | Next Page
| ==p== | | Parent Page
| ==i== | | Table of Contents
--------------------------------------------------------------------------------
/export-old-wiki/introduction/pdf-book.txt:
--------------------------------------------------------------------------------
1 | You can buy a complete PDF version of this book for ''14 Euros'' (approximately 19 USD) using the PayPal link below. After the payment process click the link to be redirected back to the download area of this website. Don't forget to bookmark the download page, if you want to download the latest builds of the PDF book in the future. By buying the PDF version you support our hard work on the book.
--------------------------------------------------------------------------------
/export-old-wiki/introduction/print-book.txt:
--------------------------------------------------------------------------------
1 | You can buy a print-on-demand, softcover copy of this book for ''28 Euros'' (approximately 40 USD) through Lulu. The printed book is identical with the *online>../online-book* and the *PDF>../pdf-book* version of the book at ''Friday, April 23, 2010''. Due to technical reasons we are unable to update the printed versions as frequently as the online and PDF version. By buying the printed version you support our hard work on the book.
--------------------------------------------------------------------------------
/export-old-wiki/introduction/what-is-smalltalk/one-click-image.txt:
--------------------------------------------------------------------------------
1 | There are several implementations of Smalltalk. Some are commercial, such as Cincom Smalltalk, GemStone Smalltalk, VA Smalltalk, and Dolphin Smalltalk. Others are open source, such as Pharo, Squeak and GNU Smalltalk. Seaside is developed in Pharo, then ported to the other Smalltalks. The first chapter provides an equivalent of a ``Getting Started\'' chapter to all major Smalltalk implementations.
In this book, we use the Seaside 3.0 ``One Click Image\'' which you can find on the Seaside website at *www.seaside.st>http://www.seaside.st/*. The ``One Click Image\'' is a bundle of everything you need to run Seaside once you unzip it. This book is based on Pharo Smalltalk, a fork of Squeak that is used to build the One Click Image. We suggest you use this image to start. It makes things much simpler.
The Seaside mailing list is a good place to ask questions because the subscribers to the list answer questions quickly. Do not hesitate to join and participate in the community.
Okay then, you now have tools at your disposal to help you through any problems you might encounter.
--------------------------------------------------------------------------------
/export-old-wiki/keyword-index.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/export-old-wiki/web-20/comet.txt:
--------------------------------------------------------------------------------
1 | HTTP is unidirectional by design. It is always the client (web browser) that submits or requests information. The web server just waits at the other end and processes whatever requests it receives. For many applications it would be beneficial if the server could propagate events to the clients as they happen. For example a chat application would like to push new messages to all connected users, or our todo application would like to push updates of the model to other people working on the same list.
Even today, the most common solution to this problem is to use polling. That is, the client regularly queries the server for new information. The only way to decrease the latency is to increase the polling frequency, which causes a significant load on the server. In practice one would like to avoid both a high server load and high latency.
In March 2006 Alex Russell coined the term ''Comet'' in a *blog post>http://alex.dojotoolkit.org/2006/03/comet-low-latency-data-for-the-browser/* to describe an alternative approach: one where the server keeps its connection to the client open, and continues to send updates to the client through that connection. The idea that Alex describes in ''Comet'' was previously known by a variety of terms like `reverse AJAX', `HTTP push', `server streaming', etc, but Alex' post popularised the concept.
Comet was incorporated into Seaside only a few months after it was introduced.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/comet/inside.txt:
--------------------------------------------------------------------------------
1 | Before we dive into a comet application, let us have a look at precisely how Comet works. The figure depicts the basic interaction between the web browser and the Seaside server in a Comet setup. The first round-trip between the web browser and Seaside is a normal HTTP request that returns a full XHTML page. This first page includes a small JavaScript snippet, that is executed once the page has finished loading. This starts a new ''asynchronous connection'' to the server. This connection now persists for a much longer time, essentially as long as the web browser is listening. This connection can then be used by the server to send data to the web browser at any time.
+comet-serverpush|width=100%+
When using Comet, keep in mind that HTTP was not designed to push data from the server to the client. Comet is a hack, even if the details are hidden in Seaside. Luckily the implementation works on all modern web browsers, but there is no guarantee that these tricks will continue to work with the next generation of web browsers. It should be noted that upcoming generations of web browsers will very likely support this type of inverse communication, and there is work on an emerging Comet standard.
Enough ranting, let's give it a quick try.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/comet/summary.txt:
--------------------------------------------------------------------------------
1 | In this chapter we saw how we can use bleeding edge Web 2.0 technology in Seaside. The Comet technology circumvents the common restrictions of the asymmetric HTTP protocol, and allows one to change a website by initiating the update event from the server. Keep in mind that Comet is a browser hack and that you might run into scalability problems quickly. The ''Web Hypertext Application Technology Working Group'' proposes a standard as part of the HTML 5 draft recommendation. Rest assured that as soon as major web browsers implement an official standard for server push, Seaside will be among the first to support the new technology.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery.txt:
--------------------------------------------------------------------------------
1 | *jQuery>http://jquery.com* is one of the most popular open-source JavaScript frameworks today. jQuery was created by John Resig and focuses on simplifying HTML document traversing, event handling, animating, and AJAX interactions for rapid web development.
There is a huge collection of *plugins>http://plugins.jquery.com/* available that extend the base framework with new functionality. One of the most popular of these plugins is *jQuery UI>http://jqueryui.com/*. It provides additional abstractions over low-level interaction and animation, advanced effects and high-level themeable widgets for building highly interactive web applications.
jQuery and jQuery UI are both well integrated into Seaside 3.0. This allows you to access all aspects of the library from Smalltalk by writing Smalltalk code only. The Smalltalk side of the integration is automatically built from the excellent *jQuery documentation>http://docs.jquery.com*, so you can be sure that the integration is up-to-date and feature-complete.
+functional-tests|width=90%+
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/adding-jquery.txt:
--------------------------------------------------------------------------------
1 | After creating a jQuery object on the Smalltalk side it is time to investigate on how to add them to the Seaside application.
The standard way of doing so in jQuery is to keep all the Javascript functionality ''unobtrusive'' in a separate Javascript file. This is possible with Seaside, but not the suggested way. In Seaside we try to encapsulate views and view-related functionality in components. Furthermore we keep components independent of each other and reusable in different contexts, what does not work well with sharing unobtrusive Javascript code. Additionally, the unobtrusiveness comes into the way when we want to define AJAX interactions.
!! Attaching to Element
==html anchor
== onClick: (html jQuery: 'div')
== remove;
== with: 'Remove DIVs'
==html anchor
== onClick: (html jQuery this)
== remove;
== with: 'Remove Myself'
!! Execute at Load-Time
- Forget about $(document).ready(...)
- Seaside has its own mechanism there
==html document addLoadScript: (html jQuery: 'div') remove
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/ajax.txt:
--------------------------------------------------------------------------------
1 | !!Loading
==aQuery load html: [ :r | r div: Time now ].
!!No Query
==html jQuery ajax.
!!Generators
==anAjax html: [ :r | r div ].
==anAjax script: [ :s | s alert: 'Hello' ].
!!Triggering Callbacks
==anAjax serialize: aQuery.
==anAjax trigger: [ :p | ... ] passengers: aQuery.
==anAjax callback: [ :v | ... ] value: anObject.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/enhanced-todo-application.txt:
--------------------------------------------------------------------------------
1 | jQuery is an increasingly popular Javascript library. Let's port the the ToDo application to use jQuery for the Javascript functionality, instead of Scriptaculous.
First, we'll implement the heading highlight effect with jQuery UI. Then we'll move on to implementing a couple of interesting effects and eye-candy possible with jQuery. Drag and drop is easy to implement, but we'll need to do something special to get the "in place" editing to work in jQuery.
If you have already worked through enhancing the ToDo application with Prototype and Scriptaculous, then the jQuery version will seem very familiar - we are still working with JavaScript underneath the covers after all.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/enhanced-todo-application/drag-and-drop.txt:
--------------------------------------------------------------------------------
1 | @@todo Drag and Drop list items with jQuery
==ToDoListView>>renderContentOn: html
==
== self renderHeadingOn: html.
== html form:
== [(html unorderedList)
== id: (listId := html nextId);
== script: ((html jQuery new sortable)
== onStop: (html jQuery ajax
== callback: [:items | self model items: items]
== passengers: (html jQuery this find: 'li'));
== axis: 'y');
== with: [self renderItemsOn: html].
== "html submitButton text: 'Save'."
== (html submitButton)
== callback: [self add];
== text: 'Add'].
== html render: editor
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/enhanced-todo-application/summary.txt:
--------------------------------------------------------------------------------
1 | @@todo Summarize this section.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/getting-ready.txt:
--------------------------------------------------------------------------------
1 | Make sure to have the packages Javascript-Core, JQuery-Core and JQuery-UI-Core loaded. For examples and functional tests also load the test packages Javascript-Tests-Core, JQuery-Tests-Core and JQuery-Tests-UI.
In order to use the libraries in your applications, you will need to load them in the Seaside web configuration application. You will notice that the core JQuery and JQueryUI libraries come in three forms which may be installed interchangeably. The ==Development== versions have the full human-readable Javascript, and so are ideal for inspection and debugging during development; the ==Deployment== versions are minified and gzipped to about 1/10th of the size of the development libraries, and so are much faster-loading for end users; and the ==Google== versions link to copies of the libraries hosted by Google \-- as many sites reference these versions, your users may already have them cached, and so these can be the fastest loading versions.
|{ ==JQDevelopmentLibrary== |{ JQuery | Full
| ==JQDeploymentLibrary== | JQuery | Compressed
| ==JQGoogleLibrary== | JQuery | Google
| ==JQUiDevelopmentLibrary== | JQuery UI | Full
| ==JQUiDeploymentLibrary== | JQuery UI | Compressed
| ==JQUiGoogleLibrary== | JQuery UI | Google
@@advanced For many of the most popular jQuery plugins there are ready-made Smalltalk wrappers in the Project *JQueryWidgetBox>http://www.squeaksource.com/JQueryWidgetBox* on SqueakSource available.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/how-to.txt:
--------------------------------------------------------------------------------
1 | @@todo Better use the ToDo example.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/how-to/click-and-show.txt:
--------------------------------------------------------------------------------
1 | == html anchor
== onClick: (html jQuery: 'div.help') toggle;
== with: 'About jQuery'.
==
== html div
== class: 'help';
== style: 'display: none';
== with: 'jQuery is a fast and ...'
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/how-to/open-lightbox.txt:
--------------------------------------------------------------------------------
1 | == | id |
== html div
== id: (id := html nextId);
== script: (html jQuery new dialog
== title: 'Lightbox Dialog';
== modal: true);
== with: [ self renderDialogOn: html ]
== html anchor
== onClick: (html jQuery id: id) dialog open;
== with: 'Open Lightbox'
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/how-to/replace-component.txt:
--------------------------------------------------------------------------------
1 | == html div
== id: (id := html nextId);
== with: child.
==
== html anchor
== onClick: ((html jQuery id: id) load
== html: [ :r |
== child := OtherComponent new;
== r render: child ]);
== with: 'Change Component'
--------------------------------------------------------------------------------
/export-old-wiki/web-20/jquery/how-to/update-multiple-elements.txt:
--------------------------------------------------------------------------------
1 | == html div id: #date.
== html div id: #time.
==
== html anchor
== onClick: (html jQuery ajax script: [ :s |
== s << (s jQuery: #date)
== html: [ :r | r render: Date today ].
== s << (s jQuery: #time)
== html: [ :r | r render: Time now ] ]);
== with: 'Update'
--------------------------------------------------------------------------------
/export-old-wiki/web-20/rss/subscribe-feed.txt:
--------------------------------------------------------------------------------
1 | Now we have done all that is required to let users subscribe. Below you can see how the feed is presented to the user in the feed reader when the URL was added manually.
+feed-vienna|width=90%+
One remaining thing to do is to tell the users of our todo application where they can subscribe to the RSS feed. Of course we could simply put an anchor at the bottom our web application, however there is a more elegant solution. We override the method +index:WAComponent!updateRoot:+ ==WAComponent>>updateRoot:== in our Seaside component to add a link to our feed into the XHTML head. Most modern web browser will pick up this tag and show the RSS logo in the toolbar to allow people to register for the feed with one click.
==ToDoListView>>updateRoot: aHtmlRoot
== super updateRoot: aHtmlRoot.
== aHtmlRoot link
== beRss;
== title: self model title;
== url: 'http://localhost:8080/todo.rss'
Note the use of the message ==beRss== tells the web browser that the given link points to an RSS feed.
In Firefox you may have to add the relationship property to make the rss logo visible.
==updateRoot: aHtmlRoot
== super updateRoot: aHtmlRoot.
== aHtmlRoot link
== beRss;
== relationship: 'alternate';
== title: self model title;
== url: 'http://localhost:8080/todo.rss'
--------------------------------------------------------------------------------
/export-old-wiki/web-20/rss/summary.txt:
--------------------------------------------------------------------------------
1 | In Seaside you don't manipulate tags directly. The elegant generation of RSS feeds nicely shows how the canvas can be extended to produce something other than XHTML. In particular, it is important to see that Seaside is not limited to serve XHTML but can be extended to serve SVG, WAP and RSS.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/scriptaculous.txt:
--------------------------------------------------------------------------------
1 | While a simple web application requires communication with the server for each update of the display, refresh or any action, JavaScript-enabled applications can allow some part of the computation to be done in the client without requiring the server to recreate and resend the complete XHTML defining the page. This allows you, for example, to have UI updates without forcing the user to explicitly click on a link or press a button.
JavaScript running in the web browser can also communicate with the web server without the need to reload the whole page. This provides you with a lightweight way to provide updates to the contents of your application's pages, such as stock tickers.
The use of these techniques allows you to build highly dynamic and interactive web applications that behave like desktop applications rather than traditional web pages. Google's web mail client is a great example of how well this approach can work.
In this chapter, we give a brief description of the JavaScript frameworks Seaside supports. Then we explain how you can add JavaScript effects to your applications and show how you can take advantage of AJAX to support the communication between the client side and the server.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/scriptaculous/ajax.txt:
--------------------------------------------------------------------------------
1 | AJAX is an acronym for ''Asynchronous JavaScript and XML''. The fact that it is asynchronous means that additional data is passed to, or requested from the web server in the background, without the user waiting for it to arrive. JavaScript obviously names the programming language that is used to trigger the request. Fortunately the data being transmitted by an AJAX request doesn't have to be in XML. It can be anything that can be sent through the HTTP protocol. The reason for the ``XML\'' in the name is that in most web browsers the internal implementation of this functionality can be found in an object called ==XMLHttpRequest==. Thankfully the Prototype framework and its integration into Seaside makes it a cakewalk to use in your applications.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/scriptaculous/frameworks/installation.txt:
--------------------------------------------------------------------------------
1 | As a first step we need to make sure that the Smalltalk Scriptaculous package is loaded. Most prebuilt images such as the one-click image already come with this package included. Note that despite the Scriptaculous name, the package includes the JavaScript source and integration code for both the Prototype and the script.aculo.us frameworks.
Make sure to have the packages ==Javascript-Core==, ==Prototype-Core==, ==Scriptaculous-Core== and ==Scriptaculous-Components== loaded. For examples and functional tests also load the test packages ==Javascript-Tests-Core==, ==Scriptaculous-Tests-Core== and ==Scriptaculous-Tests-Components==.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/scriptaculous/snippets-and-brushes.txt:
--------------------------------------------------------------------------------
1 | Adding JavaScript code to your Seaside application is not much different from rendering plain XHTML. You need to
# ask the rendering canvas ==html prototype== to instantiate a Prototype or script.aculo.us brush,
# configure the newly created brush with a cascade of configuration messages, and
# add the brush to the XHTML output. This will embed the JavaScript snippet at the desired place into the XHTML output stream.
In the following paragraphs we are going to have a in-depth look at these 3 steps and all the possibilities that Scriptaculous is providing. To directly dive into a running example, skip this section and continue with *ref:../add-effect*. To learn about the details you can always come back later.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/scriptaculous/snippets-and-brushes/configure-brush.txt:
--------------------------------------------------------------------------------
1 | There is no point in listing all possible configuration messages that can be sent to brushes. However, both underlying JavaScript frameworks have excellent documentation that can be directly mapped to the Smalltalk world. Use the table above to find out the JavaScript class name of the item in question and look it up on either *http://www.prototypejs.org/api* or *http://wiki.github.com/madrobby/scriptaculous/*. Some of the documentation available on these sites is also part of the class and method comments in your Smalltalk image.
--------------------------------------------------------------------------------
/export-old-wiki/web-20/scriptaculous/summary.txt:
--------------------------------------------------------------------------------
1 | As you have seen, introducing JavaScript functionality can allow you to greatly improve the user experience of your applications. Seaside offers a tight integration of JavaScript and AJAX functionality into the core of the framework. It allows you to define JavaScript behaviour using standard Smalltalk, and hides the necessary details from you.
--------------------------------------------------------------------------------
/originalPDF/2014-07-16-seaside.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SquareBracketAssociates/DynamicWebDevelopmentWithSeaside/cb23e6fbbdaf872c1dd6ae368eaba7d4996e9bf1/originalPDF/2014-07-16-seaside.pdf
--------------------------------------------------------------------------------
/pillar.conf:
--------------------------------------------------------------------------------
1 | {
2 | "latexWriter" : "miclatex:sbabook",
3 | "series" : "The Pharo Technology Collection",
4 | "attribution" : "Stéphane Ducasse \\ (based on S. Ducasse, D.C. Shaffer, L. Renggli, and R. Zaccone)",
5 | "htmlWriter" : "html",
6 | "newLine" : "unix",
7 | "title" : "Dynamic Web Development with Seaside"
8 | }
--------------------------------------------------------------------------------