|  | @@ -1,231 +1,53 @@
 | 
	
		
			
				|  |  |  Smalltalk current createPackage: 'Documentation' properties: #{}!
 | 
	
		
			
				|  |  | -Object subclass: #DocumentationBuilder
 | 
	
		
			
				|  |  | -	instanceVariableNames: 'chapters announcer widget'
 | 
	
		
			
				|  |  | -	category: 'Documentation'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!DocumentationBuilder methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -chapters
 | 
	
		
			
				|  |  | -	^chapters ifNil: [chapters := self buildChapters]
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -announcer
 | 
	
		
			
				|  |  | -	^announcer ifNil: [announcer := Announcer new]
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -widget
 | 
	
		
			
				|  |  | -	^widget ifNil: [widget := DocumentationWidget on: self]
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!DocumentationBuilder methodsFor: 'building'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -buildChapters
 | 
	
		
			
				|  |  | -	^((self class methodDictionary values sorted: [:a :b | a selector < b selector])
 | 
	
		
			
				|  |  | -		select: [:each | each category = 'chapters'])
 | 
	
		
			
				|  |  | -		collect: [:each | self perform: each selector]
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | +Object subclass: #ChapterSelectionAnnouncement
 | 
	
		
			
				|  |  | +	instanceVariableNames: 'id'
 | 
	
		
			
				|  |  | +	package: 'Documentation'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -buildOn: aCanvas
 | 
	
		
			
				|  |  | -	aCanvas with: self widget.
 | 
	
		
			
				|  |  | -	self 
 | 
	
		
			
				|  |  | -		checkHashChange;
 | 
	
		
			
				|  |  | -		checkHash
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | +!ChapterSelectionAnnouncement methodsFor: 'accessing'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -buildOnJQuery: aJQuery
 | 
	
		
			
				|  |  | -	self buildOn: (HTMLCanvas onJQuery: aJQuery)
 | 
	
		
			
				|  |  | +id
 | 
	
		
			
				|  |  | +	^id
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -build
 | 
	
		
			
				|  |  | -	self buildOnJQuery: ('body' asJQuery)
 | 
	
		
			
				|  |  | +id: aString
 | 
	
		
			
				|  |  | +	id := aString
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -!DocumentationBuilder methodsFor: 'chapters'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ch1introduction
 | 
	
		
			
				|  |  | -	^DocChapter new
 | 
	
		
			
				|  |  | -		title: 'Introduction';
 | 
	
		
			
				|  |  | -		contents: '
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -##Amber Smalltalk in a nutshell
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Amber is an implementation of the Smalltalk-80 language. It is designed to make client-side web development **faster, easier and more fun** as it allows developers to write HTML5 applications in a live Smalltalk environment!!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Amber is written in itself, including the IDE and the compiler and it runs **directly inside your browser**. The IDE is fairly complete with a class browser, workspace, transcript, unit test runner, object inspectors, cross reference tools and even a debugger.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Noteworthy features:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -- Amber is semantically and syntactically very close to [Pharo Smalltalk](http://www.pharo-project.org). Pharo is considered the reference implementation.
 | 
	
		
			
				|  |  | -- Amber **seamlessly interacts with JavaScript** and can use its full eco system of libraries without any glue code needed.
 | 
	
		
			
				|  |  | -- Amber **has no dependencies** and can be used in any JavaScript runtime, not only inside browsers. An important example is [Node.js](http://nodejs.org).
 | 
	
		
			
				|  |  | -- Amber is a live Smalltalk that **compiles incrementally into efficient JavaScript** often mapping one-to-one with JavaScript equivalents.
 | 
	
		
			
				|  |  | -- Amber has a **Seaside influenced canvas library** to dynamically generate HTML.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -## Arguments for using Amber
 | 
	
		
			
				|  |  | -In our humble opinion the main arguments for using Amber are:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -- JavaScript is quite a broken language with lots of traps and odd quirks. It is the assembler of the Internet which is cool, but we don''t want to write in it.
 | 
	
		
			
				|  |  | -- Smalltalk as a language is immensely cleaner and more mature, both syntactically and semantically.
 | 
	
		
			
				|  |  | -- Smalltalk has a simple class model with a lightweight syntax for closures, it is in many ways a perfect match for the Good Parts of JavaScript.
 | 
	
		
			
				|  |  | -- Having a true live interactive incremental development environment where you can build your application directly in the browser is unbeatable.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -## Disclaimer
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -This documentation doesn''t aim to teach Smalltalk. 
 | 
	
		
			
				|  |  | -Knowledge of Smalltalk is needed to understand the topics covered in this documentation. 
 | 
	
		
			
				|  |  | -If you want to learn the Smalltalk language, you can read the excellent [Pharo By Example](http://www.pharobyexample.org) book.
 | 
	
		
			
				|  |  | -'
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ch2differencesWithOtherSmalltalks
 | 
	
		
			
				|  |  | -	^DocChapter new
 | 
	
		
			
				|  |  | -		title: 'Differences with other Smalltalks';
 | 
	
		
			
				|  |  | -		contents: '
 | 
	
		
			
				|  |  | -Amber has some differences with other Smalltalk implementations. This makes porting code a non-trivial thing, but still quite manageable.
 | 
	
		
			
				|  |  | -Because it maps Smalltalk constructs one-to-one with the JavaScript equivalent, including Smalltalk classes to JavaScript constructors, the core class library is simplified compared to Pharo Smalltalk.
 | 
	
		
			
				|  |  | -And since we want Amber to be useful in building lean browser apps we can''t let it bloat too much.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -But apart from missing things other Smalltalks may have, there are also things that are plain different:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -- The collection class hierarchy is much simpler compared to most Smalltalk implementations. In part this is because we want to map reasonably well with JavaScript counter parts.
 | 
	
		
			
				|  |  | -- As of today, there is no SortedCollection. The size of arrays is dynamic, and they behave like an ordered collection. They can also be sorted with the `#sort*` methods.
 | 
	
		
			
				|  |  | -- The `Date` class behaves like the `Date` and `TimeStamp` classes in Pharo Smalltalk. Therefore both `Date today` and `Date now` are valid in Amber.
 | 
	
		
			
				|  |  | -- Amber does not have class Character, but `String` does implement some of Character behavior so a single character String can work as a Character.
 | 
	
		
			
				|  |  | -- Amber does support **class instance variables**, but not class variables.
 | 
	
		
			
				|  |  | -- Amber only has global classes and packages, but not arbitrary objects. Use classes instead like `Smalltalk current` instead of `Smalltalk` etc.
 | 
	
		
			
				|  |  | -- Amber does not support pool dictionaries.
 | 
	
		
			
				|  |  | -- Amber uses **< ...javascript code... >** to inline JavaScript code and does not have pragmas.
 | 
	
		
			
				|  |  | -- Amber does not have class categories. The left side in the browser lists real Packages, but they feel much the same.
 | 
	
		
			
				|  |  | -'
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ch3GettingStarted
 | 
	
		
			
				|  |  | -	^DocChapter new
 | 
	
		
			
				|  |  | -		title: 'Getting started';
 | 
	
		
			
				|  |  | -		contents: '
 | 
	
		
			
				|  |  | -To get started hacking in Amber you can basically take three routes, independent of your platform:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -1. Just **try it out directly** at [www.amber-lang.net](http://www.amber-lang.net) - click the **Class browser** button there. But you will **not be able to save any code you write**!! 
 | 
	
		
			
				|  |  | -    Still, it works fine for looking at the IDE and playing around. Just **don''t press F5/reload** - it will lose any code you have written.
 | 
	
		
			
				|  |  | -2. Download an Amber zip-ball, install [Nodejs](http://www.nodejs.org), fire up the Amber server and then open Amber from localhost - then you **can save code**. Detailed instructions are below!!
 | 
	
		
			
				|  |  | -3. Same as above but install git first and get a proper clone from [http://github.com/NicolasPetton/amber](http://github.com/NicolasPetton/amber) instead of a zip/tar-ball. 
 | 
	
		
			
				|  |  | -    If you want to **contribute to Amber itself** this is really what you want to do. In fact, in most cases this is what you want to do. It requires installing git first, but it is quite simple - although we leave this bit as an "exercise to the reader" :)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -**PLEASE NOTE:** Amber core developers use Linux. 
 | 
	
		
			
				|  |  | -We do not want to introduce dependencies that aren''t cross platform - but currently amberc (the command line compiler) is a bash script and we also use Makefiles 
 | 
	
		
			
				|  |  | -(for building Amber itself and server side examples) written on Linux/Unix. So using Windows is currently a bit limited - you can''t run "make" in the .st directory to rebuild whole of Amber for example.
 | 
	
		
			
				|  |  | - BUT... if you only want to use Amber to build web client apps and not really get involved in hacking Amber itself - then you should be fine!!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -## Downloading Amber
 | 
	
		
			
				|  |  | -Currently you can download in zip or tar-ball format, either cutting edge or a release. [Downloads are available here](https://github.com/NicolasPetton/amber/archives/amber). 
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Unpack wherever you like, but I would rename the directory that is unpacked to something slightly shorter - like say "amber". :)
 | 
	
		
			
				|  |  | -And yes, at this point you can double click the index.html file in the amber directory to get the IDE up, but again, **you will not be able to save code**. So please continue below :)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -## Installing Node.js
 | 
	
		
			
				|  |  | -[Node](http://www.nodejs.org) (for short) is simply the V8 Javascript VM from Google (used in Chrome) hooked together with some hard core C-libraries for doing "evented I/O".
 | 
	
		
			
				|  |  | -Basically it''s JavaScript for the server - on asynch steroids. Amber runs fine in Node and we use it for several Amber tools, like amberc (the command line Amber compiler) or the Amber server (see below). 
 | 
	
		
			
				|  |  | -There are also several Amber-Node examples to look at if you want to play with running Amber programs server side. **In short - you really want to install Nodejs. :)**
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -- Installing Node on Linux can be done using your package tool of choice (`apt-get install nodejs` for example) or any other way described at [the download page](http://nodejs.org/#download).
 | 
	
		
			
				|  |  | -- Installing Node on MacOS or Windows is probably done best by using the [installers available at Nodejs.org](http://nodejs.org/#download).
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -## Starting Amber server
 | 
	
		
			
				|  |  | -Nicolas has written a minimal webDAV server that is the easiest way to get up and running Amber with the ability to save code. This little server is written in... Amber!! 
 | 
	
		
			
				|  |  | -And it runs on top of Node. So to start it up serving your brand new directory tree of sweet Amber you do:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	cd amber	(or whatever you called the directory you unpackaged)
 | 
	
		
			
				|  |  | -	./bin/server	(in windows you type `node server\server.js` instead)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -It should say it is listening on port 4000. If it does, hooray!! That means both Node and Amber are good. In Windows you might get a question about opening that port in the local firewall - yep, do it!!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -## Firing up Amber
 | 
	
		
			
				|  |  | -The Amber IDE is written in... Amber. It uses [jQuery](http://jquery.com) and runs right in your browser as a ... well, a web page. 
 | 
	
		
			
				|  |  | -We could open it up just using a file url - but the reason we performed the previous steps is so that we can load the IDE web page from a server that can handle PUTs (webDAV) of source code. 
 | 
	
		
			
				|  |  | -According to web security Amber can only do PUT back to the same server it was loaded from. Thus we instead want to open it [through our little server now listening on port 4000](http://localhost:4000/index.html).
 | 
	
		
			
				|  |  | -Clicking that link and then pressing the **Class browser** should get your Amber IDE running with the ability to commit modified packages locally.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -To verify that you can indeed commit now - just select a Package in the browser, like say "Examples" and press the **Commit** button below. **If all goes well nothing happens :)**. 
 | 
	
		
			
				|  |  | -So in order to really know if it worked we can check the modified date on the files **amber/st/Examples.st**, **amber/js/Examples.js** and **amber/js/Examples.deploy.js** - they should be brand new.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -NOTE: We can use any webDAV server and Apache2 has been used earlier and works fine. But the Amber server is smaller and simpler to start.
 | 
	
		
			
				|  |  | -'
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ch5Index
 | 
	
		
			
				|  |  | -	^ClassesIndexChapter new
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ch6KernelObjects
 | 
	
		
			
				|  |  | -	^PackageDocChapter on: (Package named: 'Kernel-Objects')
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ch7KernelClasses
 | 
	
		
			
				|  |  | -	^PackageDocChapter on: (Package named: 'Kernel-Classes')
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ch4Tutorials
 | 
	
		
			
				|  |  | -	^TutorialsChapter new
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ch8KernelCollection
 | 
	
		
			
				|  |  | -	^PackageDocChapter on: (Package named: 'Kernel-Collections')
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ch9KernelMethods
 | 
	
		
			
				|  |  | -	^PackageDocChapter on: (Package named: 'Kernel-Methods')
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | +Object subclass: #ClassSelectionAnnouncement
 | 
	
		
			
				|  |  | +	instanceVariableNames: 'theClass'
 | 
	
		
			
				|  |  | +	package: 'Documentation'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -!DocumentationBuilder methodsFor: 'routing'!
 | 
	
		
			
				|  |  | +!ClassSelectionAnnouncement methodsFor: 'accessing'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -checkHashChange
 | 
	
		
			
				|  |  | -	(window jQuery: window) bind: 'hashchange' do: [self checkHash]
 | 
	
		
			
				|  |  | +theClass
 | 
	
		
			
				|  |  | +	^theClass
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -checkHash
 | 
	
		
			
				|  |  | -	| hash presentation |
 | 
	
		
			
				|  |  | -	hash := document location hash  replace: '^#' with: ''.
 | 
	
		
			
				|  |  | -	self announcer announce: (ChapterSelectionAnnouncement new 
 | 
	
		
			
				|  |  | -		id: hash; 
 | 
	
		
			
				|  |  | -		yourself)
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!DocumentationBuilder methodsFor: 'updating'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -update
 | 
	
		
			
				|  |  | -	chapters := nil.
 | 
	
		
			
				|  |  | -	announcer := nil.
 | 
	
		
			
				|  |  | -	widget := nil.
 | 
	
		
			
				|  |  | -	(window jQuery: '.documentation') remove.
 | 
	
		
			
				|  |  | -	self build
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -DocumentationBuilder class instanceVariableNames: 'current'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!DocumentationBuilder class methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -current
 | 
	
		
			
				|  |  | -	^current ifNil: [current := self new]
 | 
	
		
			
				|  |  | +theClass: aClass
 | 
	
		
			
				|  |  | +	theClass := aClass
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -!DocumentationBuilder class methodsFor: 'initialization'!
 | 
	
		
			
				|  |  | +!ClassSelectionAnnouncement class methodsFor: 'instance creation'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -initialize
 | 
	
		
			
				|  |  | -	self current build
 | 
	
		
			
				|  |  | +on: aClass
 | 
	
		
			
				|  |  | +	^self new
 | 
	
		
			
				|  |  | +		theClass: aClass;
 | 
	
		
			
				|  |  | +		yourself
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  Widget subclass: #DocChapter
 | 
	
		
			
				|  |  | -	instanceVariableNames: 'title contents parent'
 | 
	
		
			
				|  |  | -	category: 'Documentation'!
 | 
	
		
			
				|  |  | +	instanceVariableNames: 'title contents parent level'
 | 
	
		
			
				|  |  | +	package: 'Documentation'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  !DocChapter methodsFor: 'accessing'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -title
 | 
	
		
			
				|  |  | -	^title ifNil: ['']
 | 
	
		
			
				|  |  | +announcer
 | 
	
		
			
				|  |  | +	^DocumentationBuilder current announcer
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -title: aString
 | 
	
		
			
				|  |  | -	title := aString
 | 
	
		
			
				|  |  | +chapters
 | 
	
		
			
				|  |  | +	"A doc chapter can contain sub chapters"
 | 
	
		
			
				|  |  | +	^#()
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  contents
 | 
	
	
		
			
				|  | @@ -236,17 +58,18 @@ contents: aString
 | 
	
		
			
				|  |  |  	contents := aString
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -htmlContents
 | 
	
		
			
				|  |  | -	^(Showdown at: #converter) new makeHtml: self contents
 | 
	
		
			
				|  |  | +cssClass
 | 
	
		
			
				|  |  | +	^'doc_chapter'
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -chapters
 | 
	
		
			
				|  |  | -	"A doc chapter can contain sub chapters"
 | 
	
		
			
				|  |  | -	^#()
 | 
	
		
			
				|  |  | +htmlContents
 | 
	
		
			
				|  |  | +	^(Showdown at: #converter) new makeHtml: self contents
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -cssClass
 | 
	
		
			
				|  |  | -	^'doc_chapter'
 | 
	
		
			
				|  |  | +id
 | 
	
		
			
				|  |  | +	"The id is used in url fragments. 
 | 
	
		
			
				|  |  | +	It must be unique amoung all chapters"
 | 
	
		
			
				|  |  | +	^self title replace: ' ' with: '-'
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  level
 | 
	
	
		
			
				|  | @@ -265,28 +88,26 @@ parent: aChapter
 | 
	
		
			
				|  |  |  	parent := aChapter
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -id
 | 
	
		
			
				|  |  | -	"The id is used in url fragments. 
 | 
	
		
			
				|  |  | -	It must be unique amoung all chapters"
 | 
	
		
			
				|  |  | -	^self title replace: ' ' with: '-'
 | 
	
		
			
				|  |  | +title
 | 
	
		
			
				|  |  | +	^title ifNil: ['']
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -announcer
 | 
	
		
			
				|  |  | -	^DocumentationBuilder current announcer
 | 
	
		
			
				|  |  | +title: aString
 | 
	
		
			
				|  |  | +	title := aString
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  !DocChapter methodsFor: 'actions'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -selectClass: aClass
 | 
	
		
			
				|  |  | -	DocumentationBuilder current announcer announce: (ClassSelectionAnnouncement on: aClass)
 | 
	
		
			
				|  |  | +displayChapter: aChapter
 | 
	
		
			
				|  |  | +	DocumentationBuilder current widget displayChapter: aChapter
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  selectChapter: aChapter
 | 
	
		
			
				|  |  |  	document location hash: aChapter id
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -displayChapter: aChapter
 | 
	
		
			
				|  |  | -	DocumentationBuilder current widget displayChapter: aChapter
 | 
	
		
			
				|  |  | +selectClass: aClass
 | 
	
		
			
				|  |  | +	DocumentationBuilder current announcer announce: (ClassSelectionAnnouncement on: aClass)
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  !DocChapter methodsFor: 'initialization'!
 | 
	
	
		
			
				|  | @@ -298,14 +119,6 @@ initialize
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  !DocChapter methodsFor: 'rendering'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -renderOn: html
 | 
	
		
			
				|  |  | -	html div 
 | 
	
		
			
				|  |  | -		class: self cssClass;
 | 
	
		
			
				|  |  | -		with: [
 | 
	
		
			
				|  |  | -			self renderDocOn: html.
 | 
	
		
			
				|  |  | -			self renderLinksOn: html]
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  renderDocOn: html
 | 
	
		
			
				|  |  |  	| div |
 | 
	
		
			
				|  |  |  	html h1 with: self title.
 | 
	
	
		
			
				|  | @@ -314,6 +127,17 @@ renderDocOn: html
 | 
	
		
			
				|  |  |  	div asJQuery html: self htmlContents
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +renderLinksOn: html
 | 
	
		
			
				|  |  | +	html ul 
 | 
	
		
			
				|  |  | +		class: 'links';
 | 
	
		
			
				|  |  | +		with: [
 | 
	
		
			
				|  |  | +			self chapters do: [:each |
 | 
	
		
			
				|  |  | +				html li with: [
 | 
	
		
			
				|  |  | +					html a
 | 
	
		
			
				|  |  | +						with: each title;
 | 
	
		
			
				|  |  | +						onClick: [self selectChapter: each]]]]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  renderNavigationOn: html
 | 
	
		
			
				|  |  |  	self parent ifNotNil: [
 | 
	
		
			
				|  |  |  		html div 
 | 
	
	
		
			
				|  | @@ -323,15 +147,12 @@ renderNavigationOn: html
 | 
	
		
			
				|  |  |  					onClick: [self selectChapter: self parent]]]
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -renderLinksOn: html
 | 
	
		
			
				|  |  | -	html ul 
 | 
	
		
			
				|  |  | -		class: 'links';
 | 
	
		
			
				|  |  | +renderOn: html
 | 
	
		
			
				|  |  | +	html div 
 | 
	
		
			
				|  |  | +		class: self cssClass;
 | 
	
		
			
				|  |  |  		with: [
 | 
	
		
			
				|  |  | -			self chapters do: [:each |
 | 
	
		
			
				|  |  | -				html li with: [
 | 
	
		
			
				|  |  | -					html a
 | 
	
		
			
				|  |  | -						with: each title;
 | 
	
		
			
				|  |  | -						onClick: [self selectChapter: each]]]]
 | 
	
		
			
				|  |  | +			self renderDocOn: html.
 | 
	
		
			
				|  |  | +			self renderLinksOn: html]
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  !DocChapter methodsFor: 'subscriptions'!
 | 
	
	
		
			
				|  | @@ -341,57 +162,12 @@ subscribe
 | 
	
		
			
				|  |  |  		ann id = self id ifTrue: [self displayChapter: self]]
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -DocChapter subclass: #PackageDocChapter
 | 
	
		
			
				|  |  | -	instanceVariableNames: 'package chapters'
 | 
	
		
			
				|  |  | -	category: 'Documentation'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!PackageDocChapter methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -package
 | 
	
		
			
				|  |  | -	^package
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -title
 | 
	
		
			
				|  |  | -	^'Package ', self package name
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -chapters
 | 
	
		
			
				|  |  | -	^chapters
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -contents
 | 
	
		
			
				|  |  | -	^'Classes in package ', self package name, ':'
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!PackageDocChapter methodsFor: 'initialization'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -initializeWithPackage: aPackage
 | 
	
		
			
				|  |  | -	package := aPackage.
 | 
	
		
			
				|  |  | -	chapters := (aPackage classes sorted: [:a :b | a name < b name]) collect: [:each |
 | 
	
		
			
				|  |  | -		(ClassDocChapter on: each)
 | 
	
		
			
				|  |  | -			parent: self;
 | 
	
		
			
				|  |  | -			yourself]
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!PackageDocChapter class methodsFor: 'instance creation'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -on: aPackage
 | 
	
		
			
				|  |  | -	^self basicNew
 | 
	
		
			
				|  |  | -		initializeWithPackage: aPackage;
 | 
	
		
			
				|  |  | -		initialize;
 | 
	
		
			
				|  |  | -		yourself
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  DocChapter subclass: #ClassDocChapter
 | 
	
		
			
				|  |  |  	instanceVariableNames: 'theClass'
 | 
	
		
			
				|  |  | -	category: 'Documentation'!
 | 
	
		
			
				|  |  | +	package: 'Documentation'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  !ClassDocChapter methodsFor: 'accessing'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -theClass
 | 
	
		
			
				|  |  | -	^theClass
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  contents
 | 
	
		
			
				|  |  |  	^self theClass comment isEmpty
 | 
	
		
			
				|  |  |  		ifTrue: [self theClass name, ' is not documented yet.']
 | 
	
	
		
			
				|  | @@ -402,12 +178,16 @@ cssClass
 | 
	
		
			
				|  |  |  	^'doc_class ', super cssClass
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -title
 | 
	
		
			
				|  |  | -	^self theClass name
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  initializeWithClass: aClass
 | 
	
		
			
				|  |  |  	theClass := aClass
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +theClass
 | 
	
		
			
				|  |  | +	^theClass
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +title
 | 
	
		
			
				|  |  | +	^self theClass name
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  !ClassDocChapter methodsFor: 'rendering'!
 | 
	
	
		
			
				|  | @@ -440,106 +220,22 @@ on: aClass
 | 
	
		
			
				|  |  |  		yourself
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Widget subclass: #DocumentationWidget
 | 
	
		
			
				|  |  | -	instanceVariableNames: 'builder selectedChapter chapterDiv'
 | 
	
		
			
				|  |  | -	category: 'Documentation'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!DocumentationWidget methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -builder
 | 
	
		
			
				|  |  | -	^builder
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -builder: aDocumentationBuilder
 | 
	
		
			
				|  |  | -	builder := aDocumentationBuilder
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -chapters
 | 
	
		
			
				|  |  | -	^self builder chapters
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -selectedChapter
 | 
	
		
			
				|  |  | -	^selectedChapter ifNil: [selectedChapter := self chapters first]
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -selectedChapter: aChapter
 | 
	
		
			
				|  |  | -	^selectedChapter := aChapter
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!DocumentationWidget methodsFor: 'actions'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -displayChapter: aChapter
 | 
	
		
			
				|  |  | -	self selectedChapter: aChapter.
 | 
	
		
			
				|  |  | -	self updateChapterDiv
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -selectChapter: aChapter
 | 
	
		
			
				|  |  | -	document location hash: aChapter id
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!DocumentationWidget methodsFor: 'rendering'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -renderOn: html
 | 
	
		
			
				|  |  | -	html div 
 | 
	
		
			
				|  |  | -		class: 'documentation';
 | 
	
		
			
				|  |  | -		with: [
 | 
	
		
			
				|  |  | -			self renderMenuOn: html.
 | 
	
		
			
				|  |  | -			chapterDiv := html div.
 | 
	
		
			
				|  |  | -			self updateChapterDiv]
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -renderMenuOn: html
 | 
	
		
			
				|  |  | -	html div 
 | 
	
		
			
				|  |  | -		class: 'menu';
 | 
	
		
			
				|  |  | -		with: [
 | 
	
		
			
				|  |  | -			html ol with: [
 | 
	
		
			
				|  |  | -				self chapters do: [:each |
 | 
	
		
			
				|  |  | -					html li with: [
 | 
	
		
			
				|  |  | -						self renderChapterMenu: each on: html]]]]
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -renderChapterMenu: aChapter on: html
 | 
	
		
			
				|  |  | -	html a
 | 
	
		
			
				|  |  | -		with: aChapter title;
 | 
	
		
			
				|  |  | -		onClick: [
 | 
	
		
			
				|  |  | -			self selectChapter: aChapter].
 | 
	
		
			
				|  |  | -	html ol with: [
 | 
	
		
			
				|  |  | -			aChapter chapters do: [:each |
 | 
	
		
			
				|  |  | -				html li with: [
 | 
	
		
			
				|  |  | -					self renderChapterMenu: each on: html]]]
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!DocumentationWidget methodsFor: 'updating'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -updateChapterDiv
 | 
	
		
			
				|  |  | -	chapterDiv contents: [:html |
 | 
	
		
			
				|  |  | -		html with: self selectedChapter]
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -!DocumentationWidget class methodsFor: 'instance creation'!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -on: aBuilder
 | 
	
		
			
				|  |  | -	^self new
 | 
	
		
			
				|  |  | -		builder: aBuilder;
 | 
	
		
			
				|  |  | -		yourself
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  DocChapter subclass: #ClassesIndexChapter
 | 
	
		
			
				|  |  |  	instanceVariableNames: ''
 | 
	
		
			
				|  |  | -	category: 'Documentation'!
 | 
	
		
			
				|  |  | +	package: 'Documentation'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  !ClassesIndexChapter methodsFor: 'accessing'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +alphabet
 | 
	
		
			
				|  |  | +	^'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  cssClass
 | 
	
		
			
				|  |  |  	^'index_doc ', super cssClass
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  title
 | 
	
		
			
				|  |  |  	^'Smalltalk classes by index'
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -alphabet
 | 
	
		
			
				|  |  | -	^'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  !ClassesIndexChapter methodsFor: 'rendering'!
 | 
	
	
		
			
				|  | @@ -557,74 +253,132 @@ renderDocOn: html
 | 
	
		
			
				|  |  |  						onClick: [self selectClass: each]]]]]
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Object subclass: #ClassSelectionAnnouncement
 | 
	
		
			
				|  |  | -	instanceVariableNames: 'theClass'
 | 
	
		
			
				|  |  | -	category: 'Documentation'!
 | 
	
		
			
				|  |  | +DocChapter subclass: #PackageDocChapter
 | 
	
		
			
				|  |  | +	instanceVariableNames: 'package chapters'
 | 
	
		
			
				|  |  | +	package: 'Documentation'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -!ClassSelectionAnnouncement methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +!PackageDocChapter methodsFor: 'accessing'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -theClass
 | 
	
		
			
				|  |  | -	^theClass
 | 
	
		
			
				|  |  | +chapters
 | 
	
		
			
				|  |  | +	^chapters
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -theClass: aClass
 | 
	
		
			
				|  |  | -	theClass := aClass
 | 
	
		
			
				|  |  | -! !
 | 
	
		
			
				|  |  | +contents
 | 
	
		
			
				|  |  | +	^'Classes in package ', self package name, ':'
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -!ClassSelectionAnnouncement class methodsFor: 'instance creation'!
 | 
	
		
			
				|  |  | +package
 | 
	
		
			
				|  |  | +	^package
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -on: aClass
 | 
	
		
			
				|  |  | -	^self new
 | 
	
		
			
				|  |  | -		theClass: aClass;
 | 
	
		
			
				|  |  | -		yourself
 | 
	
		
			
				|  |  | +title
 | 
	
		
			
				|  |  | +	^'Package ', self package name
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Object subclass: #ChapterSelectionAnnouncement
 | 
	
		
			
				|  |  | -	instanceVariableNames: 'id'
 | 
	
		
			
				|  |  | -	category: 'Documentation'!
 | 
	
		
			
				|  |  | +!PackageDocChapter methodsFor: 'initialization'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -!ChapterSelectionAnnouncement methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +initializeWithPackage: aPackage
 | 
	
		
			
				|  |  | +	package := aPackage.
 | 
	
		
			
				|  |  | +	chapters := (aPackage classes sorted: [:a :b | a name < b name]) collect: [:each |
 | 
	
		
			
				|  |  | +		(ClassDocChapter on: each)
 | 
	
		
			
				|  |  | +			parent: self;
 | 
	
		
			
				|  |  | +			yourself]
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -id
 | 
	
		
			
				|  |  | -	^id
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | +!PackageDocChapter class methodsFor: 'instance creation'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -id: aString
 | 
	
		
			
				|  |  | -	id := aString
 | 
	
		
			
				|  |  | +on: aPackage
 | 
	
		
			
				|  |  | +	^self basicNew
 | 
	
		
			
				|  |  | +		initializeWithPackage: aPackage;
 | 
	
		
			
				|  |  | +		initialize;
 | 
	
		
			
				|  |  | +		yourself
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  DocChapter subclass: #TutorialsChapter
 | 
	
		
			
				|  |  |  	instanceVariableNames: ''
 | 
	
		
			
				|  |  | -	category: 'Documentation'!
 | 
	
		
			
				|  |  | +	package: 'Documentation'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  !TutorialsChapter methodsFor: 'accessing'!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -title
 | 
	
		
			
				|  |  | -	^'Tutorials'
 | 
	
		
			
				|  |  | +chapters
 | 
	
		
			
				|  |  | +	^{ self firstAppChapter. self counterChapter }
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  contents
 | 
	
		
			
				|  |  |  	^'Here''s a serie of tutorials. If you are new to Smalltalk, you can also learn Amber online with [ProfStef](http://www.amber-lang.net/learn.html)'
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -chapters
 | 
	
		
			
				|  |  | -	^{ self firstAppChapter. self counterChapter }
 | 
	
		
			
				|  |  | -!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -firstAppChapter
 | 
	
		
			
				|  |  | +counterChapter
 | 
	
		
			
				|  |  |  	^DocChapter new
 | 
	
		
			
				|  |  | -		title: 'A first application';
 | 
	
		
			
				|  |  | +		title: 'The counter application';
 | 
	
		
			
				|  |  |  		contents: '
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Let''s make Hello World in Amber.
 | 
	
		
			
				|  |  | +This tutorial will teach you how to build HTML with Amber using jQuery and the HTMLCanvas API. It is freely adapted from 
 | 
	
		
			
				|  |  | +the [Seaside counter example](http://www.seaside.st/about/examples/counter)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -First, you need a place for your new project. I made a new directory under amber:
 | 
	
		
			
				|  |  | +##The counter widget
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    amber/projects/hello
 | 
	
		
			
				|  |  | +The counter is the most basic example of a widget. It allows to increment and decrement a number by clicking a button.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -This will store your project files. To get started, add a new index.html file to this folder, as well as empty js and st folders.
 | 
	
		
			
				|  |  | +Amber already comes with a counter example in the `Examples` package. To avoid class name conflict, we''ll name our counter class `TCounter`.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Your index.html can be really basic. The most important thing it does is include amber.js and run loadAmber. Here is a basic index.html you can use:
 | 
	
		
			
				|  |  | +    Widget subclass: #TCounter
 | 
	
		
			
				|  |  | +        instanceVariableNames: ''count header''
 | 
	
		
			
				|  |  | +        package: ''Tutorials''
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +The first method is used to initialize the component with the default state, in this case we set the counter to 0:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    initialize
 | 
	
		
			
				|  |  | +        super initialize.
 | 
	
		
			
				|  |  | +        count := 0
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +The method used for rendering a widget is `#renderOn:`. It takes an instance of HTMLCanvas as parameter. 
 | 
	
		
			
				|  |  | +The `header` h1 kept as an instance variable, so when the count value change, we can update it''s contents accordingly.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    renderOn: html
 | 
	
		
			
				|  |  | +        header := html h1 
 | 
	
		
			
				|  |  | +            with: count asString;
 | 
	
		
			
				|  |  | +            yourself.
 | 
	
		
			
				|  |  | +        html button
 | 
	
		
			
				|  |  | +            with: ''++'';
 | 
	
		
			
				|  |  | +            onClick: [self increase].
 | 
	
		
			
				|  |  | +        html button
 | 
	
		
			
				|  |  | +            with: ''--'';
 | 
	
		
			
				|  |  | +            onClick: [self decrease]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +The counter is almost ready. All we need now is to implement the two action methods `#increase` and `#decrease` to change the state 
 | 
	
		
			
				|  |  | +of our counter and update its header.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    increase
 | 
	
		
			
				|  |  | +        count := count + 1.
 | 
	
		
			
				|  |  | +        header contents: [:html | html with: count asString]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    decrease
 | 
	
		
			
				|  |  | +        count := count - 1.
 | 
	
		
			
				|  |  | +        header contents: [:html | html with: count asString]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +That''s it!! We can now display an instance of TCounter by rendering it on the page using jQuery:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    TCounter new appendToJQuery: ''body'' asJQuery
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +'
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +firstAppChapter
 | 
	
		
			
				|  |  | +	^DocChapter new
 | 
	
		
			
				|  |  | +		title: 'A first application';
 | 
	
		
			
				|  |  | +		contents: '
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Let''s make Hello World in Amber.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +First, you need a place for your new project. I made a new directory under amber:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    amber/projects/hello
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +This will store your project files. To get started, add a new index.html file to this folder, as well as empty js and st folders.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Your index.html can be really basic. The most important thing it does is include amber.js and run loadAmber. Here is a basic index.html you can use:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      <!!DOCTYPE html>
 | 
	
	
		
			
				|  | @@ -699,60 +453,306 @@ From there, you can create new Smalltalk classes and messages to build up your a
 | 
	
		
			
				|  |  |  '
 | 
	
		
			
				|  |  |  !
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -counterChapter
 | 
	
		
			
				|  |  | +title
 | 
	
		
			
				|  |  | +	^'Tutorials'
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Object subclass: #DocumentationBuilder
 | 
	
		
			
				|  |  | +	instanceVariableNames: 'chapters announcer widget'
 | 
	
		
			
				|  |  | +	package: 'Documentation'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationBuilder methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +announcer
 | 
	
		
			
				|  |  | +	^announcer ifNil: [announcer := Announcer new]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +chapters
 | 
	
		
			
				|  |  | +	^chapters ifNil: [chapters := self buildChapters]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +widget
 | 
	
		
			
				|  |  | +	^widget ifNil: [widget := DocumentationWidget on: self]
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationBuilder methodsFor: 'building'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +build
 | 
	
		
			
				|  |  | +	self buildOnJQuery: ('body' asJQuery)
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +buildChapters
 | 
	
		
			
				|  |  | +	^((self class methodDictionary values sorted: [:a :b | a selector < b selector])
 | 
	
		
			
				|  |  | +		select: [:each | each category = 'chapters'])
 | 
	
		
			
				|  |  | +		collect: [:each | self perform: each selector]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +buildOn: aCanvas
 | 
	
		
			
				|  |  | +	aCanvas with: self widget.
 | 
	
		
			
				|  |  | +	self 
 | 
	
		
			
				|  |  | +		checkHashChange;
 | 
	
		
			
				|  |  | +		checkHash
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +buildOnJQuery: aJQuery
 | 
	
		
			
				|  |  | +	self buildOn: (HTMLCanvas onJQuery: aJQuery)
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationBuilder methodsFor: 'chapters'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +ch1introduction
 | 
	
		
			
				|  |  |  	^DocChapter new
 | 
	
		
			
				|  |  | -		title: 'The counter application';
 | 
	
		
			
				|  |  | +		title: 'Introduction';
 | 
	
		
			
				|  |  |  		contents: '
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -This tutorial will teach you how to build HTML with Amber using jQuery and the HTMLCanvas API. It is freely adapted from 
 | 
	
		
			
				|  |  | -the [Seaside counter example](http://www.seaside.st/about/examples/counter)
 | 
	
		
			
				|  |  | +##Amber Smalltalk in a nutshell
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -##The counter widget
 | 
	
		
			
				|  |  | +Amber is an implementation of the Smalltalk-80 language. It is designed to make client-side web development **faster, easier and more fun** as it allows developers to write HTML5 applications in a live Smalltalk environment!!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -The counter is the most basic example of a widget. It allows to increment and decrement a number by clicking a button.
 | 
	
		
			
				|  |  | +Amber is written in itself, including the IDE and the compiler and it runs **directly inside your browser**. The IDE is fairly complete with a class browser, workspace, transcript, unit test runner, object inspectors, cross reference tools and even a debugger.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Amber already comes with a counter example in the `Examples` package. To avoid class name conflict, we''ll name our counter class `TCounter`.
 | 
	
		
			
				|  |  | +Noteworthy features:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    Widget subclass: #TCounter
 | 
	
		
			
				|  |  | -        instanceVariableNames: ''count header''
 | 
	
		
			
				|  |  | -        package: ''Tutorials''
 | 
	
		
			
				|  |  | +- Amber is semantically and syntactically very close to [Pharo Smalltalk](http://www.pharo-project.org). Pharo is considered the reference implementation.
 | 
	
		
			
				|  |  | +- Amber **seamlessly interacts with JavaScript** and can use its full eco system of libraries without any glue code needed.
 | 
	
		
			
				|  |  | +- Amber **has no dependencies** and can be used in any JavaScript runtime, not only inside browsers. An important example is [Node.js](http://nodejs.org).
 | 
	
		
			
				|  |  | +- Amber is a live Smalltalk that **compiles incrementally into efficient JavaScript** often mapping one-to-one with JavaScript equivalents.
 | 
	
		
			
				|  |  | +- Amber has a **Seaside influenced canvas library** to dynamically generate HTML.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -The first method is used to initialize the component with the default state, in this case we set the counter to 0:
 | 
	
		
			
				|  |  | +## Arguments for using Amber
 | 
	
		
			
				|  |  | +In our humble opinion the main arguments for using Amber are:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    initialize
 | 
	
		
			
				|  |  | -        super initialize.
 | 
	
		
			
				|  |  | -        count := 0
 | 
	
		
			
				|  |  | +- JavaScript is quite a broken language with lots of traps and odd quirks. It is the assembler of the Internet which is cool, but we don''t want to write in it.
 | 
	
		
			
				|  |  | +- Smalltalk as a language is immensely cleaner and more mature, both syntactically and semantically.
 | 
	
		
			
				|  |  | +- Smalltalk has a simple class model with a lightweight syntax for closures, it is in many ways a perfect match for the Good Parts of JavaScript.
 | 
	
		
			
				|  |  | +- Having a true live interactive incremental development environment where you can build your application directly in the browser is unbeatable.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -The method used for rendering a widget is `#renderOn:`. It takes an instance of HTMLCanvas as parameter. 
 | 
	
		
			
				|  |  | -The `header` h1 kept as an instance variable, so when the count value change, we can update it''s contents accordingly.
 | 
	
		
			
				|  |  | +## Disclaimer
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    renderOn: html
 | 
	
		
			
				|  |  | -        header := html h1 
 | 
	
		
			
				|  |  | -            with: count asString;
 | 
	
		
			
				|  |  | -            yourself.
 | 
	
		
			
				|  |  | -        html button
 | 
	
		
			
				|  |  | -            with: ''++'';
 | 
	
		
			
				|  |  | -            onClick: [self increase].
 | 
	
		
			
				|  |  | -        html button
 | 
	
		
			
				|  |  | -            with: ''--'';
 | 
	
		
			
				|  |  | -            onClick: [self decrease]
 | 
	
		
			
				|  |  | +This documentation doesn''t aim to teach Smalltalk. 
 | 
	
		
			
				|  |  | +Knowledge of Smalltalk is needed to understand the topics covered in this documentation. 
 | 
	
		
			
				|  |  | +If you want to learn the Smalltalk language, you can read the excellent [Pharo By Example](http://www.pharobyexample.org) book.
 | 
	
		
			
				|  |  | +'
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -The counter is almost ready. All we need now is to implement the two action methods `#increase` and `#decrease` to change the state 
 | 
	
		
			
				|  |  | -of our counter and update its header.
 | 
	
		
			
				|  |  | +ch2differencesWithOtherSmalltalks
 | 
	
		
			
				|  |  | +	^DocChapter new
 | 
	
		
			
				|  |  | +		title: 'Differences with other Smalltalks';
 | 
	
		
			
				|  |  | +		contents: '
 | 
	
		
			
				|  |  | +Amber has some differences with other Smalltalk implementations. This makes porting code a non-trivial thing, but still quite manageable.
 | 
	
		
			
				|  |  | +Because it maps Smalltalk constructs one-to-one with the JavaScript equivalent, including Smalltalk classes to JavaScript constructors, the core class library is simplified compared to Pharo Smalltalk.
 | 
	
		
			
				|  |  | +And since we want Amber to be useful in building lean browser apps we can''t let it bloat too much.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    increase
 | 
	
		
			
				|  |  | -        count := count + 1.
 | 
	
		
			
				|  |  | -        header contents: [:html | html with: count asString]
 | 
	
		
			
				|  |  | +But apart from missing things other Smalltalks may have, there are also things that are plain different:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    decrease
 | 
	
		
			
				|  |  | -        count := count - 1.
 | 
	
		
			
				|  |  | -        header contents: [:html | html with: count asString]
 | 
	
		
			
				|  |  | +- The collection class hierarchy is much simpler compared to most Smalltalk implementations. In part this is because we want to map reasonably well with JavaScript counter parts.
 | 
	
		
			
				|  |  | +- As of today, there is no SortedCollection. The size of arrays is dynamic, and they behave like an ordered collection. They can also be sorted with the `#sort*` methods.
 | 
	
		
			
				|  |  | +- The `Date` class behaves like the `Date` and `TimeStamp` classes in Pharo Smalltalk. Therefore both `Date today` and `Date now` are valid in Amber.
 | 
	
		
			
				|  |  | +- Amber does not have class Character, but `String` does implement some of Character behavior so a single character String can work as a Character.
 | 
	
		
			
				|  |  | +- Amber does support **class instance variables**, but not class variables.
 | 
	
		
			
				|  |  | +- Amber only has global classes and packages, but not arbitrary objects. Use classes instead like `Smalltalk current` instead of `Smalltalk` etc.
 | 
	
		
			
				|  |  | +- Amber does not support pool dictionaries.
 | 
	
		
			
				|  |  | +- Amber uses **< ...javascript code... >** to inline JavaScript code and does not have pragmas.
 | 
	
		
			
				|  |  | +- Amber does not have class categories. The left side in the browser lists real Packages, but they feel much the same.
 | 
	
		
			
				|  |  | +'
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +ch3GettingStarted
 | 
	
		
			
				|  |  | +	^DocChapter new
 | 
	
		
			
				|  |  | +		title: 'Getting started';
 | 
	
		
			
				|  |  | +		contents: '
 | 
	
		
			
				|  |  | +To get started hacking in Amber you can basically take three routes, independent of your platform:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -That''s it!! We can now display an instance of TCounter by rendering it on the page using jQuery:
 | 
	
		
			
				|  |  | +1. Just **try it out directly** at [www.amber-lang.net](http://www.amber-lang.net) - click the **Class browser** button there. But you will **not be able to save any code you write**!! 
 | 
	
		
			
				|  |  | +    Still, it works fine for looking at the IDE and playing around. Just **don''t press F5/reload** - it will lose any code you have written.
 | 
	
		
			
				|  |  | +2. Download an Amber zip-ball, install [Nodejs](http://www.nodejs.org), fire up the Amber server and then open Amber from localhost - then you **can save code**. Detailed instructions are below!!
 | 
	
		
			
				|  |  | +3. Same as above but install git first and get a proper clone from [http://github.com/NicolasPetton/amber](http://github.com/NicolasPetton/amber) instead of a zip/tar-ball. 
 | 
	
		
			
				|  |  | +    If you want to **contribute to Amber itself** this is really what you want to do. In fact, in most cases this is what you want to do. It requires installing git first, but it is quite simple - although we leave this bit as an "exercise to the reader" :)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    TCounter new appendToJQuery: ''body'' asJQuery
 | 
	
		
			
				|  |  | +**PLEASE NOTE:** Amber core developers use Linux. 
 | 
	
		
			
				|  |  | +We do not want to introduce dependencies that aren''t cross platform - but currently amberc (the command line compiler) is a bash script and we also use Makefiles 
 | 
	
		
			
				|  |  | +(for building Amber itself and server side examples) written on Linux/Unix. So using Windows is currently a bit limited - you can''t run "make" in the .st directory to rebuild whole of Amber for example.
 | 
	
		
			
				|  |  | + BUT... if you only want to use Amber to build web client apps and not really get involved in hacking Amber itself - then you should be fine!!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +## Downloading Amber
 | 
	
		
			
				|  |  | +Currently you can download in zip or tar-ball format, either cutting edge or a release. [Downloads are available here](https://github.com/NicolasPetton/amber/archives/amber). 
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Unpack wherever you like, but I would rename the directory that is unpacked to something slightly shorter - like say "amber". :)
 | 
	
		
			
				|  |  | +And yes, at this point you can double click the index.html file in the amber directory to get the IDE up, but again, **you will not be able to save code**. So please continue below :)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +## Installing Node.js
 | 
	
		
			
				|  |  | +[Node](http://www.nodejs.org) (for short) is simply the V8 Javascript VM from Google (used in Chrome) hooked together with some hard core C-libraries for doing "evented I/O".
 | 
	
		
			
				|  |  | +Basically it''s JavaScript for the server - on asynch steroids. Amber runs fine in Node and we use it for several Amber tools, like amberc (the command line Amber compiler) or the Amber server (see below). 
 | 
	
		
			
				|  |  | +There are also several Amber-Node examples to look at if you want to play with running Amber programs server side. **In short - you really want to install Nodejs. :)**
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +- Installing Node on Linux can be done using your package tool of choice (`apt-get install nodejs` for example) or any other way described at [the download page](http://nodejs.org/#download).
 | 
	
		
			
				|  |  | +- Installing Node on MacOS or Windows is probably done best by using the [installers available at Nodejs.org](http://nodejs.org/#download).
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +## Starting Amber server
 | 
	
		
			
				|  |  | +Nicolas has written a minimal webDAV server that is the easiest way to get up and running Amber with the ability to save code. This little server is written in... Amber!! 
 | 
	
		
			
				|  |  | +And it runs on top of Node. So to start it up serving your brand new directory tree of sweet Amber you do:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	cd amber	(or whatever you called the directory you unpackaged)
 | 
	
		
			
				|  |  | +	./bin/server	(in windows you type `node server\server.js` instead)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +It should say it is listening on port 4000. If it does, hooray!! That means both Node and Amber are good. In Windows you might get a question about opening that port in the local firewall - yep, do it!!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +## Firing up Amber
 | 
	
		
			
				|  |  | +The Amber IDE is written in... Amber. It uses [jQuery](http://jquery.com) and runs right in your browser as a ... well, a web page. 
 | 
	
		
			
				|  |  | +We could open it up just using a file url - but the reason we performed the previous steps is so that we can load the IDE web page from a server that can handle PUTs (webDAV) of source code. 
 | 
	
		
			
				|  |  | +According to web security Amber can only do PUT back to the same server it was loaded from. Thus we instead want to open it [through our little server now listening on port 4000](http://localhost:4000/index.html).
 | 
	
		
			
				|  |  | +Clicking that link and then pressing the **Class browser** should get your Amber IDE running with the ability to commit modified packages locally.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +To verify that you can indeed commit now - just select a Package in the browser, like say "Examples" and press the **Commit** button below. **If all goes well nothing happens :)**. 
 | 
	
		
			
				|  |  | +So in order to really know if it worked we can check the modified date on the files **amber/st/Examples.st**, **amber/js/Examples.js** and **amber/js/Examples.deploy.js** - they should be brand new.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +NOTE: We can use any webDAV server and Apache2 has been used earlier and works fine. But the Amber server is smaller and simpler to start.
 | 
	
		
			
				|  |  |  '
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +ch4Tutorials
 | 
	
		
			
				|  |  | +	^TutorialsChapter new
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +ch5Index
 | 
	
		
			
				|  |  | +	^ClassesIndexChapter new
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +ch6KernelObjects
 | 
	
		
			
				|  |  | +	^PackageDocChapter on: (Package named: 'Kernel-Objects')
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +ch7KernelClasses
 | 
	
		
			
				|  |  | +	^PackageDocChapter on: (Package named: 'Kernel-Classes')
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +ch8KernelCollection
 | 
	
		
			
				|  |  | +	^PackageDocChapter on: (Package named: 'Kernel-Collections')
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +ch9KernelMethods
 | 
	
		
			
				|  |  | +	^PackageDocChapter on: (Package named: 'Kernel-Methods')
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationBuilder methodsFor: 'routing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +checkHash
 | 
	
		
			
				|  |  | +	| hash presentation |
 | 
	
		
			
				|  |  | +	hash := document location hash  replace: '^#' with: ''.
 | 
	
		
			
				|  |  | +	self announcer announce: (ChapterSelectionAnnouncement new 
 | 
	
		
			
				|  |  | +		id: hash; 
 | 
	
		
			
				|  |  | +		yourself)
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +checkHashChange
 | 
	
		
			
				|  |  | +	(window jQuery: window) bind: 'hashchange' do: [self checkHash]
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationBuilder methodsFor: 'updating'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +update
 | 
	
		
			
				|  |  | +	chapters := nil.
 | 
	
		
			
				|  |  | +	announcer := nil.
 | 
	
		
			
				|  |  | +	widget := nil.
 | 
	
		
			
				|  |  | +	(window jQuery: '.documentation') remove.
 | 
	
		
			
				|  |  | +	self build
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +DocumentationBuilder class instanceVariableNames: 'current'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationBuilder class methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +current
 | 
	
		
			
				|  |  | +	^current ifNil: [current := self new]
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationBuilder class methodsFor: 'initialization'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +initialize
 | 
	
		
			
				|  |  | +	self current build
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Widget subclass: #DocumentationWidget
 | 
	
		
			
				|  |  | +	instanceVariableNames: 'builder selectedChapter chapterDiv'
 | 
	
		
			
				|  |  | +	package: 'Documentation'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationWidget methodsFor: 'accessing'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +builder
 | 
	
		
			
				|  |  | +	^builder
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +builder: aDocumentationBuilder
 | 
	
		
			
				|  |  | +	builder := aDocumentationBuilder
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +chapters
 | 
	
		
			
				|  |  | +	^self builder chapters
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +selectedChapter
 | 
	
		
			
				|  |  | +	^selectedChapter ifNil: [selectedChapter := self chapters first]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +selectedChapter: aChapter
 | 
	
		
			
				|  |  | +	^selectedChapter := aChapter
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationWidget methodsFor: 'actions'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +displayChapter: aChapter
 | 
	
		
			
				|  |  | +	self selectedChapter: aChapter.
 | 
	
		
			
				|  |  | +	self updateChapterDiv
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +selectChapter: aChapter
 | 
	
		
			
				|  |  | +	document location hash: aChapter id
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationWidget methodsFor: 'rendering'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +renderChapterMenu: aChapter on: html
 | 
	
		
			
				|  |  | +	html a
 | 
	
		
			
				|  |  | +		with: aChapter title;
 | 
	
		
			
				|  |  | +		onClick: [
 | 
	
		
			
				|  |  | +			self selectChapter: aChapter].
 | 
	
		
			
				|  |  | +	html ol with: [
 | 
	
		
			
				|  |  | +			aChapter chapters do: [:each |
 | 
	
		
			
				|  |  | +				html li with: [
 | 
	
		
			
				|  |  | +					self renderChapterMenu: each on: html]]]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +renderMenuOn: html
 | 
	
		
			
				|  |  | +	html div 
 | 
	
		
			
				|  |  | +		class: 'menu';
 | 
	
		
			
				|  |  | +		with: [
 | 
	
		
			
				|  |  | +			html ol with: [
 | 
	
		
			
				|  |  | +				self chapters do: [:each |
 | 
	
		
			
				|  |  | +					html li with: [
 | 
	
		
			
				|  |  | +						self renderChapterMenu: each on: html]]]]
 | 
	
		
			
				|  |  | +!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +renderOn: html
 | 
	
		
			
				|  |  | +	html div 
 | 
	
		
			
				|  |  | +		class: 'documentation';
 | 
	
		
			
				|  |  | +		with: [
 | 
	
		
			
				|  |  | +			self renderMenuOn: html.
 | 
	
		
			
				|  |  | +			chapterDiv := html div.
 | 
	
		
			
				|  |  | +			self updateChapterDiv]
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationWidget methodsFor: 'updating'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +updateChapterDiv
 | 
	
		
			
				|  |  | +	chapterDiv contents: [:html |
 | 
	
		
			
				|  |  | +		html with: self selectedChapter]
 | 
	
		
			
				|  |  | +! !
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +!DocumentationWidget class methodsFor: 'instance creation'!
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +on: aBuilder
 | 
	
		
			
				|  |  | +	^self new
 | 
	
		
			
				|  |  | +		builder: aBuilder;
 | 
	
		
			
				|  |  | +		yourself
 | 
	
		
			
				|  |  |  ! !
 | 
	
		
			
				|  |  |  
 |