Göran Krampe 13 years ago
parent
commit
3eeca292b8

+ 1 - 15
css/amber.css

@@ -257,27 +257,13 @@ body.jtalkBody {
     height: 100%;
 }
 
-.jtalkTool .jt_commit {
+.jtalkTool .jt_packagesButtons {
     position: absolute;
     top: 129px;
     left: 0;
     z-index: 1;
 }
 
-.jtalkTool .jt_rename {
-    position: absolute;
-    top: 129px;
-    left: 90px;
-    z-index: 1;
-}
-
-.jtalkTool .jt_delete {
-    position: absolute;
-    top: 129px;
-    left: 185px;
-    z-index: 1;
-}
-
 .jtalkTool .jt_column {
     width: 25%;
     padding: 0;

+ 18 - 0
css/style.css

@@ -267,6 +267,24 @@ h1 {
 	border: 1px solid #919293; 
 }
 
+
+.examples li {
+	list-style: none;
+	float: left;
+}
+
+.examples li img {
+		border-radius: 5px;
+		border: 5px solid rgba(0,0,0,0.4);
+		margin: 5px;
+}
+
+.examples a:hover img {
+		border-color: rgba(0,0,0,0.8);
+}
+
+
+
 #footer {
 	height: 200px;
 	border: 1px solid #ccc;

File diff suppressed because it is too large
+ 210 - 258
examples/presentation/js/Presentation.deploy.js


File diff suppressed because it is too large
+ 226 - 309
examples/presentation/js/Presentation.js


+ 180 - 93
examples/presentation/st/Presentation.st

@@ -70,7 +70,7 @@ Widget subclass: #Presentation
 !Presentation methodsFor: 'accessing'!
 
 title
-	^'Slides'
+	^ self class title.
 !
 
 author
@@ -117,24 +117,6 @@ style
 
 !Presentation methodsFor: 'actions'!
 
-reload
-	'#slides' asJQuery remove.
-	'#tools' asJQuery remove.
-	self initSlides.
-	self appendToJQuery: 'body' asJQuery.
-	self checkHash
-!
-
-setup
-	Presentation setCurrent: self.
-	(window jQuery: document) ready: [
-		self appendToJQuery: 'body' asJQuery.
-		self 
-			setKeybindings;
-			checkHashChange;
-			checkHash].
-!
-
 nextSlide
 	| next |
 	self currentSlide ifNotNil: [
@@ -161,18 +143,6 @@ previousSlide
 		next ifNotNil: [currentSlide := next. next show]]
 !
 
-setKeybindings
-	(window jQuery: document) keyup: [:e || node |
-		node := e target nodeName asLowercase.
-		(node = 'textarea' or: [node = 'input']) ifFalse: [
-			e keyCode = 39 ifTrue: [self nextSlide].
-			e keyCode = 37 ifTrue: [self previousSlide]]]
-!
-
-checkHashChange
-	(window jQuery: window) bind: 'hashchange' do: [self checkHash]
-!
-
 checkHash
 	| hash slide |
 	hash := document location hash  replace: '^#' with: ''.
@@ -195,9 +165,6 @@ renderOn: html
 	html style
 		type: 'text/css';
 		with: self style.
-	html div 
-		id: 'tools';
-		with: [self renderToolsOn: html].
 	html div 
 		id: 'slides';
 		with: [self renderSlidesOn: html]
@@ -208,41 +175,24 @@ renderSlidesOn: html
 		each renderOn: html].
 	currentSlide ifNil: [currentSlide := self slides first].
 	self showCurrentSlide
-!
-
-renderToolsOn: html
-	html a 
-		with: 'IDE';
-		onClick: [TabManager current open].
-	html a
-		with: 'Reload';
-		onClick: [self reload].
-	html a
-		with: '←';
-		onClick: [self previousSlide].
-	html a
-		with: '→';
-		onClick: [self nextSlide]
 ! !
 
 Presentation class instanceVariableNames: 'current'!
 
-!Presentation class methodsFor: 'initialization'!
+!Presentation class methodsFor: 'accessing'!
 
-initialize
-	self isConcrete ifTrue: [self setup]
+concretePresentations
+	^ self allSubclasses select: [:aPresentationClass| aPresentationClass isConcrete]
 !
 
-setup
-	self new setup
-!
+title
+	^ 'Slides'
+! !
 
-setCurrent: aSlides
-	current := aSlides
-!
+!Presentation class methodsFor: 'enumerating'!
 
-current
-	^current
+concretePresentationsDo: aBlockWithArg
+	self concretePresentations do: aBlockWithArg.
 ! !
 
 !Presentation class methodsFor: 'testing'!
@@ -257,10 +207,6 @@ Presentation subclass: #ESUG2011Presentation
 
 !ESUG2011Presentation methodsFor: 'accessing'!
 
-title
-	^'Jtalk'
-!
-
 description
 	^'ESUG 2011, Edinburgh'
 !
@@ -557,35 +503,6 @@ body {
     padding: 0 5px;
 }
 
-#tools {
-    z-index: 1;
-    position: fixed;
-    top: 0;
-    left: 50%;
-    margin-left: -150px;
-    width: 300px;
-    padding: 5px;
-    border-radius: 5px;
-    -moz-border-radius: 5px;
-    -webkit-border-radius: 5px;
-    background: #333;
-    opacity: 0.3;
-    color: #eee;
-}
-
-#tools a {
-    font-weight: bold;
-    color: #eee;
-    text-decoration: none;
-    cursor: pointer;
-    padding: 0 2px;
-    font-size: 14px;
-}
-
-#tools:hover {
-    opacity: 0.8;
-}
-
 .slide {
     
 }
@@ -594,6 +511,12 @@ body {
 
 ESUG2011Presentation class instanceVariableNames: 'current'!
 
+!ESUG2011Presentation class methodsFor: 'accessing'!
+
+title
+	^'Jtalk'
+! !
+
 !ESUG2011Presentation class methodsFor: 'testing'!
 
 isConcrete
@@ -1156,3 +1079,167 @@ renderSlideOn: html
 		html span class: 'blue'; with: 'Enyo'].
 ! !
 
+Widget subclass: #PresentationNavigator
+	instanceVariableNames: 'presentationBrush currentPresentation'
+	category: 'Presentation'!
+
+!PresentationNavigator methodsFor: 'accessing'!
+
+currentPresentation: aPresentation
+	currentPresentation := aPresentation.
+!
+
+currentPresentation
+	^  currentPresentation ifNil: [currentPresentation := Presentation concretePresentations first new].
+!
+
+style
+	^ '
+#navigator {
+    z-index: 1;
+    position: fixed;
+    top: 0;
+    left: 50%;
+    margin-left: -150px;
+    padding: 5px;
+    border-radius: 5px;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    background: #333;
+    opacity: 0.3;
+    color: #eee;
+}
+
+#navigator a {
+    font-weight: bold;
+    color: #eee;
+    text-decoration: none;
+    cursor: pointer;
+    padding: 0 2px;
+    font-size: 14px;
+}
+
+#navigator:hover {
+    opacity: 0.8;
+}
+'
+! !
+
+!PresentationNavigator methodsFor: 'callbacks'!
+
+selectPresentation: aPresentationClass
+	self currentPresentation: aPresentationClass new.
+	self renderCurrentPresentation.
+!
+
+selectPresentationNamed: aString
+	|presentationClass|
+	presentationClass :=  (Smalltalk current at: aString).
+	presentationClass ifNotNil: [ self selectPresentation: presentationClass ].
+!
+
+previousSlide
+	self currentPresentation previousSlide
+!
+
+nextSlide
+	self currentPresentation nextSlide
+!
+
+reload
+	self currentPresentation: self currentPresentation class new.
+	self renderCurrentPresentation.
+! !
+
+!PresentationNavigator methodsFor: 'hash'!
+
+checkHash
+	self currentPresentation checkHash
+!
+
+checkHashChange
+	(window jQuery: window) bind: 'hashchange' do: [self checkHash]
+! !
+
+!PresentationNavigator methodsFor: 'keybindings'!
+
+setKeybindings
+	(window jQuery: document) keyup: [:e || node |
+		node := e target nodeName asLowercase.
+		(node = 'textarea' or: [node = 'input']) ifFalse: [
+			e keyCode = 39 ifTrue: [self nextSlide].
+			e keyCode = 37 ifTrue: [self previousSlide]]]
+! !
+
+!PresentationNavigator methodsFor: 'rendering'!
+
+renderToolsOn: html
+	html a 
+		with: 'IDE';
+		onClick: [TabManager current open].
+	html a
+		with: 'Reload';
+		onClick: [self reload].
+	html a
+		with: '←';
+		onClick: [self previousSlide].
+	html a
+		with: '→';
+		onClick: [self nextSlide].
+!
+
+renderPresentationSelectOn: html
+	|presentationSelect|
+	presentationSelect := html select.
+	presentationSelect
+		onChange: [self  selectPresentationNamed:  presentationSelect asJQuery val];
+		with: [	Presentation concretePresentationsDo: [:aPresentationClass |   
+                                                              							html option
+                                                              								value: aPresentationClass name;
+                                                              								with: aPresentationClass title ] ].
+!
+
+open
+	(window jQuery: document)  ready: [
+          	self 
+          		appendToJQuery: 'body' asJQuery;
+          		setKeybindings;
+          		checkHashChange.
+        ].
+!
+
+renderOn: html
+	html style
+		type: 'text/css';
+		with: self style.
+	html div
+		id: 'navigator';
+		with: [	self
+					renderToolsOn: html;
+					renderPresentationSelectOn: html	].
+
+	presentationBrush := html div 
+							id: 'presentation';
+							yourself.
+
+	self renderCurrentPresentation.
+!
+
+renderCurrentPresentation
+	presentationBrush contents: [:html |
+        	self currentPresentation
+                                     	renderOn: html;
+                                     	checkHash.
+        ].
+! !
+
+!PresentationNavigator class methodsFor: 'initialize'!
+
+initialize
+	^ self open
+!
+
+open
+	^ self new open
+! !
+

+ 1 - 1
examples/trysmalltalk/st/TrySmalltalk.st

@@ -941,7 +941,7 @@ theEnd
 	^ Lesson
 title: 'Tutorial done !!' 
 contents: 
-'"This tutorial is done. Enjoy programming Smalltalk with JTalk. 
+'"This tutorial is done. Enjoy programming Smalltalk with Amber. 
 
 You can run this tutorial again by evaluating: ProfStef go.
 

BIN
favicon.ico


BIN
images/presentation.png


BIN
images/profstef.png


BIN
images/twitterwall.png


+ 104 - 91
index.html

@@ -1,4 +1,3 @@
-
 <!DOCTYPE html> 
 <html> 
   <head> 
@@ -8,95 +7,109 @@
     <link rel="stylesheet" type="text/css" href='css/style.css' /> 
     <link type="image/x-icon" rel="shortcut icon" href="/favicon.ico"/> 
     <link href='http://fonts.googleapis.com/css?family=Istok+Web' rel='stylesheet' type='text/css'> 
-    <script type='text/javascript' src='js/amber.js'></script> 
-  </head> 
-  <body> 
-    
-    <a href="http://github.com/NicolasPetton/amber"><img style="position: absolute; top: 0; lef
-								t: 0; border: 0;" src="https://assets.github.com/img/bec6c51521dcc8148146135149fe06a9cc737577?repo=&url=http%3A%2F%2Fs3.amazonaws.com%2Fgithub%2Fribbons%2Fforkme_left_darkblue_121621.png&path=" alt="Fork me on GitHub"></a> 
-    
-    <div id="wrapper"> 
-      
-      <div id="header"> 
-	<div class="main"> 
-	  <div class="logo"> 
-	    <img src="images/amber.png"/> 
-	  </div> 
-	  
-	  <ul id="tabs"> 
-	    <li><a target="_blank" href="http://amber-lang.net/index.html">Overview</a></li> · 
-	    <li><a target="_blank" href="http://amber-lang.net/index.html#download">Download</a></li> · 
-	    <li><a target="_blank" href="http://amber-lang.net/learn.html">Learn</a></li> ·
-	    <li><a target="_blank" href="http://amber-lang.net/documentation.html">Documentation</a></li> ·
-	    <li><a target="_blank" target="_blank" href="https://github.com/NicolasPetton/amber">Source</a></li> 
-	  </ul> 
-	  
-	  <div class="clear"></div> 
-	  
-	</div> 
-      </div> 
-      
-      <div class="teaser"> 
-	<div class="main"> 
-	  <h1>Welcome aboard!</h1> 
-	  <div class="column">
-	    <h2>What is Amber?</h2>
-	    <p>Amber, formerly known as Jtalk, is an implementation of the Smalltalk-80 language. It is designed to make client-side development faster and easier. It allows developers to write client-side heavy web applications in Smalltalk. </p> 
-	    <p>Amber includes an integrated development environment with a class browser, workspace, transcript, object inspector and debugger.</p> 
-	    <p>Amber is written in itself, including the compiler, and compiles into efficient JavaScript, mapping one-to-one with the JS equivalent.</p> 
-	    <h2>Give it a try!</h2>
-	    <p><b>Try a <button onClick="smalltalk.Browser._open()"> Class browser</button> right now!</b></p> 
-	  </div> 
-	  <div class="column">
-	    <h2>Getting started</h2>
-	    <p>The <a href="https://github.com/NicolasPetton/amber/wiki">Wiki on GitHub</a> includes a <a href="https://github.com/NicolasPetton/amber/wiki/Getting-started">Getting started</a> tutorial for OSX, Linux and Windows.</p>
-	    <p>If you're new to Smalltalk, You can learn it online with <a href="http://amber-lang.net/learn.html">ProfStef</a>.</p>
-	    <h2>Join the community</h2>
-	    <ul>
-	      <li><a href="http://amber-lang.net">Amber's website</a></li>
-	      <li><a href="https://github.com/NicolasPetton/amber/wiki">Wiki on GitHub</a></li>
-	      <li><a href="http://groups.google.com/group/amber-lang">Mailing list</a></li>
-	      <li>Join us on IRC at #amber-lang on Freenode</li>
-	    </ul>
-	  </div>
-	  <div class="clear"></div> 
-	</div> 
-	
-	
-      </div> 
-      
-      <div id="content"> 
-	<div class="main"> 
-	  <div class="box"> 
-	    <h2>Client-side usage</h2> 
-	    <div class="content"> 
-	      <p>Load the full Amber Smalltalk environment with the IDE in your page:</p> 
-	      
-	      <code><pre>&lt;script src="js/amber.js" type="text/javascript"&gt;&lt;/script&gt;
+			<script type='text/javascript' src='js/amber.js'></script> 
+		</head> 
+		<body> 
+			
+			<a href="http://github.com/NicolasPetton/amber"><img style="position: absolute; top: 0; lef
+			t: 0; border: 0;" src="https://assets.github.com/img/bec6c51521dcc8148146135149fe06a9cc737577?repo=&url=http%3A%2F%2Fs3.amazonaws.com%2Fgithub%2Fribbons%2Fforkme_left_darkblue_121621.png&path=" alt="Fork me on GitHub"></a> 
+			
+			<div id="wrapper"> 
+				
+				<div id="header"> 
+					<div class="main"> 
+						<div class="logo"> 
+							<img src="images/amber.png"/> 
+						</div> 
+						
+						<ul id="tabs"> 
+							<li><a target="_blank" href="http://amber-lang.net/index.html">Overview</a></li> · 
+							<li><a target="_blank" href="http://amber-lang.net/index.html#download">Download</a></li> · 
+							<li><a target="_blank" href="http://amber-lang.net/learn.html">Learn</a></li> ·
+							<li><a target="_blank" href="http://amber-lang.net/documentation.html">Documentation</a></li> ·
+							<li><a target="_blank" target="_blank" href="https://github.com/NicolasPetton/amber">Source</a></li> 
+						</ul> 
+						
+						<div class="clear"></div> 
+						
+					</div> 
+				</div> 
+				
+				<div class="teaser"> 
+					<div class="main"> 
+						<h1>Welcome aboard!</h1> 
+						<div class="column">
+							<h2>What is Amber?</h2>
+							<p>Amber, formerly known as Jtalk, is an implementation of the Smalltalk-80 language. It is designed to make client-side development faster and easier. It allows developers to write client-side heavy web applications in Smalltalk. </p> 
+							<p>Amber includes an integrated development environment with a class browser, workspace, transcript, object inspector and debugger.</p> 
+							<p>Amber is written in itself, including the compiler, and compiles into efficient JavaScript, mapping one-to-one with the JS equivalent.</p> 
+							<h2>Give it a try!</h2>
+							<p><b>Try a <button onClick="smalltalk.Browser._open()"> Class browser</button> right now!</b></p> 
+						</div> 
+						<div class="column">
+							<h2>Getting started</h2>
+							<p>The <a href="https://github.com/NicolasPetton/amber/wiki">Wiki on GitHub</a> includes a <a href="https://github.com/NicolasPetton/amber/wiki/Getting-started">Getting started</a> tutorial for OSX, Linux and Windows.</p>
+							<p>If you're new to Smalltalk, You can learn it online with <a href="http://amber-lang.net/learn.html">ProfStef</a>.</p>
+							<h2>Join the community</h2>
+							<ul>
+								<li><a href="http://amber-lang.net">Amber's website</a></li>
+								<li><a href="https://github.com/NicolasPetton/amber/wiki">Wiki on GitHub</a></li>
+								<li><a href="http://groups.google.com/group/amber-lang">Mailing list</a></li>
+								<li>Join us on IRC at #amber-lang on Freenode</li>
+							</ul>
+						</div>
+						<div class="clear"></div> 
+					</div> 
+					
+					
+				</div> 
+				
+				<div id="content"> 
+					<div class="main"> 
+						<div class="box"> 
+							<h2>Client-side usage</h2> 
+							<div class="content"> 
+								<p>Load the full Amber Smalltalk environment with the IDE in your page:</p> 
+								
+								<code><pre>&lt;script src="js/amber.js" type="text/javascript"&gt;&lt;/script&gt;
 &lt;script type="text/javascript"&gt; loadAmber()&lt;/script&gt;</pre></code>
-	    </div> 
-	    
-	    
-	    <p>Or the deployment JavaScript file only (without the Smalltalk sources, parser, compiler and IDE):</p>
-	    <code><pre>&lt;script src="js/amber.js" type="text/javascript"&gt;&lt;/script&gt;
+							</div> 
+							
+							
+							<p>Or the deployment JavaScript file only (without the Smalltalk sources, parser, compiler and IDE):</p>
+							<code><pre>&lt;script src="js/amber.js" type="text/javascript"&gt;&lt;/script&gt;
 &lt;script type="text/javascript"&gt; loadAmber({deploy: true})&lt;/script&gt;</pre></code>
-	  </div> 
-	  
-	  <div class="box last"> 
-	    <h2 id="download">Examples</h2> 
-	    <div class="content"> 
-	      <ul>
-		<li><a href="examples/trysmalltalk/index.html">ProfStef tutorial</a></li>
-		<li><a href="examples/presentation/index.html">Presentation at ESUG 2011</a></li>
-	      </ul>
-	    </div> 
-	  </div> 
-	  
-	</div> 
-      </div> 
-    </div> 
-    
-    <script type='text/javascript'> loadAmber() </script> 
-    
-  </body> 
-</html> 
+						</div> 
+						
+						<div class="box last examples"> 
+							<h2>Examples</h2> 
+							<div class="content"> 
+								<ul>
+									<li>
+										<a href="examples/trysmalltalk/index.html">
+											<img src="images/profstef.png" alt="Learn Smalltalk with ProfStef"/>
+										</a>
+									</li>
+									<li>
+										<a href="examples/presentation/index.html">
+											<img src="images/presentation.png" alt="ESUG 2011 presentation"/>
+										</a>
+									</li>
+									<li>
+										<a href="examples/twitterwall/index.html">
+											<img src="images/twitterwall.png" alt="Twitter Wall"/>
+										</a>
+									</li>
+									<div class="clear"></div>
+								</ul>
+							</div> 
+						</div> 
+						
+					</div> 
+				</div> 
+			</div> 
+			
+			<script type='text/javascript'> loadAmber() </script> 
+			
+		</body> 
+	</html> 

+ 33 - 44
js/Canvas.deploy.js

@@ -562,6 +562,28 @@ return self;}
 }),
 smalltalk.HTMLCanvas);
 
+smalltalk.addMethod(
+'_span_',
+smalltalk.method({
+selector: 'span:',
+fn: function (anObject){
+var self=this;
+return smalltalk.send(smalltalk.send(self, "_span", []), "_with_", [anObject]);
+return self;}
+}),
+smalltalk.HTMLCanvas);
+
+smalltalk.addMethod(
+'_style_',
+smalltalk.method({
+selector: 'style:',
+fn: function (aString){
+var self=this;
+return (function($rec){smalltalk.send($rec, "_with_", [aString]);return smalltalk.send($rec, "_yourself", []);})(smalltalk.send(self, "_style", []));
+return self;}
+}),
+smalltalk.HTMLCanvas);
+
 
 smalltalk.addMethod(
 '_onJQuery_',
@@ -839,6 +861,17 @@ return self;}
 }),
 smalltalk.TagBrush);
 
+smalltalk.addMethod(
+'_value_',
+smalltalk.method({
+selector: 'value:',
+fn: function (aString){
+var self=this;
+smalltalk.send(self, "_at_put_", ["value", aString]);
+return self;}
+}),
+smalltalk.TagBrush);
+
 smalltalk.addMethod(
 '_asJQuery',
 smalltalk.method({
@@ -998,50 +1031,6 @@ smalltalk.TagBrush.klass);
 
 
 smalltalk.addClass('Widget', smalltalk.Object, [], 'Canvas');
-smalltalk.addMethod(
-'_alert_',
-smalltalk.method({
-selector: 'alert:',
-fn: function (aString){
-var self=this;
-alert(aString);
-return self;}
-}),
-smalltalk.Widget);
-
-smalltalk.addMethod(
-'_confirm_',
-smalltalk.method({
-selector: 'confirm:',
-fn: function (aString){
-var self=this;
-return window.confirm(aString);
-return self;}
-}),
-smalltalk.Widget);
-
-smalltalk.addMethod(
-'_prompt_',
-smalltalk.method({
-selector: 'prompt:',
-fn: function (aString){
-var self=this;
-return smalltalk.send(self, "_prompt_default_", [aString, ""]);
-return self;}
-}),
-smalltalk.Widget);
-
-smalltalk.addMethod(
-'_prompt_default_',
-smalltalk.method({
-selector: 'prompt:default:',
-fn: function (aString, anotherString){
-var self=this;
-return window.prompt(aString, anotherString);
-return self;}
-}),
-smalltalk.Widget);
-
 smalltalk.addMethod(
 '_appendToBrush_',
 smalltalk.method({

+ 48 - 64
js/Canvas.js

@@ -817,6 +817,38 @@ referencedClasses: []
 }),
 smalltalk.HTMLCanvas);
 
+smalltalk.addMethod(
+unescape('_span_'),
+smalltalk.method({
+selector: unescape('span%3A'),
+category: 'tags',
+fn: function (anObject){
+var self=this;
+return smalltalk.send(smalltalk.send(self, "_span", []), "_with_", [anObject]);
+return self;},
+args: ["anObject"],
+source: unescape('span%3A%20anObject%0A%20%20%20%20%5Eself%20span%20with%3A%20anObject'),
+messageSends: ["with:", "span"],
+referencedClasses: []
+}),
+smalltalk.HTMLCanvas);
+
+smalltalk.addMethod(
+unescape('_style_'),
+smalltalk.method({
+selector: unescape('style%3A'),
+category: 'tags',
+fn: function (aString){
+var self=this;
+return (function($rec){smalltalk.send($rec, "_with_", [aString]);return smalltalk.send($rec, "_yourself", []);})(smalltalk.send(self, "_style", []));
+return self;},
+args: ["aString"],
+source: unescape('style%3A%20aString%0A%09%5E%20self%20style%20with%3A%20aString%3B%20yourself'),
+messageSends: ["with:", "yourself", "style"],
+referencedClasses: []
+}),
+smalltalk.HTMLCanvas);
+
 
 smalltalk.addMethod(
 unescape('_onJQuery_'),
@@ -1214,6 +1246,22 @@ referencedClasses: []
 }),
 smalltalk.TagBrush);
 
+smalltalk.addMethod(
+unescape('_value_'),
+smalltalk.method({
+selector: unescape('value%3A'),
+category: 'attributes',
+fn: function (aString){
+var self=this;
+smalltalk.send(self, "_at_put_", ["value", aString]);
+return self;},
+args: ["aString"],
+source: unescape('value%3A%20aString%0A%20%20%20%20self%20%20at%3A%20%27value%27%20put%3A%20aString'),
+messageSends: ["at:put:"],
+referencedClasses: []
+}),
+smalltalk.TagBrush);
+
 smalltalk.addMethod(
 unescape('_asJQuery'),
 smalltalk.method({
@@ -1443,70 +1491,6 @@ smalltalk.TagBrush.klass);
 
 
 smalltalk.addClass('Widget', smalltalk.Object, [], 'Canvas');
-smalltalk.addMethod(
-unescape('_alert_'),
-smalltalk.method({
-selector: unescape('alert%3A'),
-category: 'actions',
-fn: function (aString){
-var self=this;
-alert(aString);
-return self;},
-args: ["aString"],
-source: unescape('alert%3A%20aString%0A%20%20%20%20%3Calert%28aString%29%3E'),
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.Widget);
-
-smalltalk.addMethod(
-unescape('_confirm_'),
-smalltalk.method({
-selector: unescape('confirm%3A'),
-category: 'actions',
-fn: function (aString){
-var self=this;
-return window.confirm(aString);
-return self;},
-args: ["aString"],
-source: unescape('confirm%3A%20aString%0A%20%20%20%20%3Creturn%20window.confirm%28aString%29%3E'),
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.Widget);
-
-smalltalk.addMethod(
-unescape('_prompt_'),
-smalltalk.method({
-selector: unescape('prompt%3A'),
-category: 'actions',
-fn: function (aString){
-var self=this;
-return smalltalk.send(self, "_prompt_default_", [aString, ""]);
-return self;},
-args: ["aString"],
-source: unescape('prompt%3A%20aString%0A%20%20%20%20%5Eself%20prompt%3A%20aString%20default%3A%20%27%27'),
-messageSends: ["prompt:default:"],
-referencedClasses: []
-}),
-smalltalk.Widget);
-
-smalltalk.addMethod(
-unescape('_prompt_default_'),
-smalltalk.method({
-selector: unescape('prompt%3Adefault%3A'),
-category: 'actions',
-fn: function (aString, anotherString){
-var self=this;
-return window.prompt(aString, anotherString);
-return self;},
-args: ["aString", "anotherString"],
-source: unescape('prompt%3A%20aString%20default%3A%20anotherString%0A%20%20%20%20%3Creturn%20window.prompt%28aString%2C%20anotherString%29%3E'),
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.Widget);
-
 smalltalk.addMethod(
 unescape('_appendToBrush_'),
 smalltalk.method({

+ 1 - 1
js/Compiler.js

@@ -2224,7 +2224,7 @@ return self;},
 args: [],
 source: unescape('recompileAll%0A%09Smalltalk%20current%20classes%20do%3A%20%5B%3Aeach%20%7C%0A%09%09Transcript%20show%3A%20each%3B%20cr.%0A%09%09%5Bself%20recompile%3A%20each%5D%20valueWithTimeout%3A%20100%5D'),
 messageSends: ["do:", "classes", "current", "show:", "cr", "valueWithTimeout:", "recompile:"],
-referencedClasses: [smalltalk.Smalltalk]
+referencedClasses: [smalltalk.Smalltalk,smalltalk.Transcript]
 }),
 smalltalk.Compiler);
 

File diff suppressed because it is too large
+ 37 - 147
js/IDE.deploy.js


File diff suppressed because it is too large
+ 56 - 216
js/IDE.js


+ 12 - 0
js/Kernel-Tests.deploy.js

@@ -295,6 +295,18 @@ return self;}
 }),
 smalltalk.NumberTest);
 
+smalltalk.addMethod(
+'_testCopying',
+smalltalk.method({
+selector: 'testCopying',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send((1), "_copy", []), "__eq", [(1)])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send((1), "_deepCopy", []), "__eq", [(1)])]);
+return self;}
+}),
+smalltalk.NumberTest);
+
 
 
 smalltalk.addClass('JSObjectProxyTest', smalltalk.TestCase, [], 'Kernel-Tests');

+ 18 - 1
js/Kernel-Tests.js

@@ -243,7 +243,7 @@ smalltalk.addMethod(
 unescape('_testPrintShowingDecimalPlaces'),
 smalltalk.method({
 selector: unescape('testPrintShowingDecimalPlaces'),
-category: 'not yet classified',
+category: 'tests',
 fn: function (){
 var self=this;
 smalltalk.send(self, "_assert_equals_", ["23.00", smalltalk.send((23), "_printShowingDecimalPlaces_", [(2)])]);
@@ -390,6 +390,23 @@ referencedClasses: []
 }),
 smalltalk.NumberTest);
 
+smalltalk.addMethod(
+unescape('_testCopying'),
+smalltalk.method({
+selector: unescape('testCopying'),
+category: 'tests',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send((1), "_copy", []), "__eq", [(1)])]);
+smalltalk.send(self, "_assert_", [smalltalk.send(smalltalk.send((1), "_deepCopy", []), "__eq", [(1)])]);
+return self;},
+args: [],
+source: unescape('testCopying%0A%09self%20assert%3A%201%20copy%20%3D%201.%0A%09self%20assert%3A%201%20deepCopy%20%3D%201'),
+messageSends: ["assert:", unescape("%3D"), "copy", "deepCopy"],
+referencedClasses: []
+}),
+smalltalk.NumberTest);
+
 
 
 smalltalk.addClass('JSObjectProxyTest', smalltalk.TestCase, [], 'Kernel-Tests');

+ 173 - 25
js/Kernel.deploy.js

@@ -2011,6 +2011,28 @@ return self;}
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+'_deepCopy',
+smalltalk.method({
+selector: 'deepCopy',
+fn: function (){
+var self=this;
+return smalltalk.send(self, "_copy", []);
+return self;}
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+'_copy',
+smalltalk.method({
+selector: 'copy',
+fn: function (){
+var self=this;
+return self;
+return self;}
+}),
+smalltalk.Number);
+
 
 smalltalk.addMethod(
 '_pi',
@@ -3610,6 +3632,17 @@ return self;}
 }),
 smalltalk.SequenceableCollection);
 
+smalltalk.addMethod(
+'_atRandom',
+smalltalk.method({
+selector: 'atRandom',
+fn: function (){
+var self=this;
+return smalltalk.send(self, "_at_", [smalltalk.send(smalltalk.send(self, "_size", []), "_atRandom", [])]);
+return self;}
+}),
+smalltalk.SequenceableCollection);
+
 
 
 smalltalk.addClass('String', smalltalk.SequenceableCollection, [], 'Kernel');
@@ -5218,31 +5251,6 @@ return self;}
 }),
 smalltalk.ClassBuilder);
 
-smalltalk.addMethod(
-'_superclass_subclass_instanceVariableNames_module_',
-smalltalk.method({
-selector: 'superclass:subclass:instanceVariableNames:module:',
-fn: function (aClass, aString, aString2, aString3){
-var self=this;
-var newClass=nil;
-newClass=smalltalk.send(self, "_addSubclassOf_named_instanceVariableNames_module_", [aClass, aString, smalltalk.send(self, "_instanceVariableNamesFor_", [aString2]), (($receiver = aString3) == nil || $receiver == undefined) ? (function(){return "unclassified";})() : $receiver]);
-smalltalk.send(self, "_setupClass_", [newClass]);
-return self;}
-}),
-smalltalk.ClassBuilder);
-
-smalltalk.addMethod(
-'_addSubclassOf_named_instanceVariableNames_module_',
-smalltalk.method({
-selector: 'addSubclassOf:named:instanceVariableNames:module:',
-fn: function (aClass, aString, aCollection, moduleName){
-var self=this;
-smalltalk.addClass(aString, aClass, aCollection, moduleName);
-	    return smalltalk[aString];
-return self;}
-}),
-smalltalk.ClassBuilder);
-
 smalltalk.addMethod(
 '_superclass_subclass_instanceVariableNames_package_',
 smalltalk.method({
@@ -5252,6 +5260,7 @@ var self=this;
 var newClass=nil;
 newClass=smalltalk.send(self, "_addSubclassOf_named_instanceVariableNames_package_", [aClass, aString, smalltalk.send(self, "_instanceVariableNamesFor_", [aString2]), (($receiver = aString3) == nil || $receiver == undefined) ? (function(){return "unclassified";})() : $receiver]);
 smalltalk.send(self, "_setupClass_", [newClass]);
+return newClass;
 return self;}
 }),
 smalltalk.ClassBuilder);
@@ -6332,3 +6341,142 @@ smalltalk.Set);
 
 
 
+smalltalk.addClass('Transcript', smalltalk.Object, ['textarea'], 'Kernel');
+
+smalltalk.Transcript.klass.iVarNames = ['current'];
+smalltalk.addMethod(
+'_open',
+smalltalk.method({
+selector: 'open',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_open", []);
+return self;}
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+'_new',
+smalltalk.method({
+selector: 'new',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_shouldNotImplement", []);
+return self;}
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+'_current',
+smalltalk.method({
+selector: 'current',
+fn: function (){
+var self=this;
+return self['@current'];
+return self;}
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+'_show_',
+smalltalk.method({
+selector: 'show:',
+fn: function (anObject){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_show_", [anObject]);
+return self;}
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+'_cr',
+smalltalk.method({
+selector: 'cr',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_show_", [smalltalk.send((smalltalk.String || String), "_cr", [])]);
+return self;}
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+'_clear',
+smalltalk.method({
+selector: 'clear',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_clear", []);
+return self;}
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+'_register_',
+smalltalk.method({
+selector: 'register:',
+fn: function (aTranscript){
+var self=this;
+self['@current']=aTranscript;
+return self;}
+}),
+smalltalk.Transcript.klass);
+
+
+smalltalk.addClass('ConsoleTranscript', smalltalk.Object, ['textarea'], 'Kernel');
+smalltalk.addMethod(
+'_clear',
+smalltalk.method({
+selector: 'clear',
+fn: function (){
+var self=this;
+
+return self;}
+}),
+smalltalk.ConsoleTranscript);
+
+smalltalk.addMethod(
+'_cr',
+smalltalk.method({
+selector: 'cr',
+fn: function (){
+var self=this;
+
+return self;}
+}),
+smalltalk.ConsoleTranscript);
+
+smalltalk.addMethod(
+'_show_',
+smalltalk.method({
+selector: 'show:',
+fn: function (anObject){
+var self=this;
+console.log(String(anObject._asString()));
+return self;}
+}),
+smalltalk.ConsoleTranscript);
+
+smalltalk.addMethod(
+'_open',
+smalltalk.method({
+selector: 'open',
+fn: function (){
+var self=this;
+
+return self;}
+}),
+smalltalk.ConsoleTranscript);
+
+
+smalltalk.addMethod(
+'_initialize',
+smalltalk.method({
+selector: 'initialize',
+fn: function (){
+var self=this;
+smalltalk.send((smalltalk.Transcript || Transcript), "_register_", [smalltalk.send(self, "_new", [])]);
+return self;}
+}),
+smalltalk.ConsoleTranscript.klass);
+
+

+ 249 - 36
js/Kernel.js

@@ -2862,6 +2862,38 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+unescape('_deepCopy'),
+smalltalk.method({
+selector: unescape('deepCopy'),
+category: 'copying',
+fn: function (){
+var self=this;
+return smalltalk.send(self, "_copy", []);
+return self;},
+args: [],
+source: unescape('deepCopy%0A%09%5Eself%20copy'),
+messageSends: ["copy"],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+unescape('_copy'),
+smalltalk.method({
+selector: unescape('copy'),
+category: 'copying',
+fn: function (){
+var self=this;
+return self;
+return self;},
+args: [],
+source: unescape('copy%0A%09%5Eself'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 
 smalltalk.addMethod(
 unescape('_pi'),
@@ -5152,6 +5184,22 @@ referencedClasses: []
 }),
 smalltalk.SequenceableCollection);
 
+smalltalk.addMethod(
+unescape('_atRandom'),
+smalltalk.method({
+selector: unescape('atRandom'),
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.send(self, "_at_", [smalltalk.send(smalltalk.send(self, "_size", []), "_atRandom", [])]);
+return self;},
+args: [],
+source: unescape('atRandom%0A%09%5E%20self%20at%3A%20self%20size%20atRandom'),
+messageSends: ["at:", "atRandom", "size"],
+referencedClasses: []
+}),
+smalltalk.SequenceableCollection);
+
 
 
 smalltalk.addClass('String', smalltalk.SequenceableCollection, [], 'Kernel');
@@ -7430,41 +7478,6 @@ referencedClasses: []
 }),
 smalltalk.ClassBuilder);
 
-smalltalk.addMethod(
-unescape('_superclass_subclass_instanceVariableNames_module_'),
-smalltalk.method({
-selector: unescape('superclass%3Asubclass%3AinstanceVariableNames%3Amodule%3A'),
-category: 'class creation',
-fn: function (aClass, aString, aString2, aString3){
-var self=this;
-var newClass=nil;
-newClass=smalltalk.send(self, "_addSubclassOf_named_instanceVariableNames_module_", [aClass, aString, smalltalk.send(self, "_instanceVariableNamesFor_", [aString2]), (($receiver = aString3) == nil || $receiver == undefined) ? (function(){return "unclassified";})() : $receiver]);
-smalltalk.send(self, "_setupClass_", [newClass]);
-return self;},
-args: ["aClass", "aString", "aString2", "aString3"],
-source: unescape('superclass%3A%20aClass%20subclass%3A%20aString%20instanceVariableNames%3A%20aString2%20module%3A%20aString3%0A%09%7C%20newClass%20%7C%0A%09newClass%20%3A%3D%20self%20addSubclassOf%3A%20aClass%0A%09%09%09%09named%3A%20aString%20instanceVariableNames%3A%20%28self%20instanceVariableNamesFor%3A%20aString2%29%0A%09%09%09%09module%3A%20%28aString3%20ifNil%3A%20%5B%27unclassified%27%5D%29.%0A%09self%20setupClass%3A%20newClass'),
-messageSends: ["addSubclassOf:named:instanceVariableNames:module:", "instanceVariableNamesFor:", "ifNil:", "setupClass:"],
-referencedClasses: []
-}),
-smalltalk.ClassBuilder);
-
-smalltalk.addMethod(
-unescape('_addSubclassOf_named_instanceVariableNames_module_'),
-smalltalk.method({
-selector: unescape('addSubclassOf%3Anamed%3AinstanceVariableNames%3Amodule%3A'),
-category: 'private',
-fn: function (aClass, aString, aCollection, moduleName){
-var self=this;
-smalltalk.addClass(aString, aClass, aCollection, moduleName);
-	    return smalltalk[aString];
-return self;},
-args: ["aClass", "aString", "aCollection", "moduleName"],
-source: unescape('addSubclassOf%3A%20aClass%20named%3A%20aString%20instanceVariableNames%3A%20aCollection%20module%3A%20moduleName%0A%09%3Csmalltalk.addClass%28aString%2C%20aClass%2C%20aCollection%2C%20moduleName%29%3B%0A%09%20%20%20%20return%20smalltalk%5BaString%5D%3E'),
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.ClassBuilder);
-
 smalltalk.addMethod(
 unescape('_superclass_subclass_instanceVariableNames_package_'),
 smalltalk.method({
@@ -7475,9 +7488,10 @@ var self=this;
 var newClass=nil;
 newClass=smalltalk.send(self, "_addSubclassOf_named_instanceVariableNames_package_", [aClass, aString, smalltalk.send(self, "_instanceVariableNamesFor_", [aString2]), (($receiver = aString3) == nil || $receiver == undefined) ? (function(){return "unclassified";})() : $receiver]);
 smalltalk.send(self, "_setupClass_", [newClass]);
+return newClass;
 return self;},
 args: ["aClass", "aString", "aString2", "aString3"],
-source: unescape('superclass%3A%20aClass%20subclass%3A%20aString%20instanceVariableNames%3A%20aString2%20package%3A%20aString3%0A%09%7C%20newClass%20%7C%0A%09newClass%20%3A%3D%20self%20addSubclassOf%3A%20aClass%0A%09%09%09%09named%3A%20aString%20instanceVariableNames%3A%20%28self%20instanceVariableNamesFor%3A%20aString2%29%0A%09%09%09%09package%3A%20%28aString3%20ifNil%3A%20%5B%27unclassified%27%5D%29.%0A%09self%20setupClass%3A%20newClass'),
+source: unescape('superclass%3A%20aClass%20subclass%3A%20aString%20instanceVariableNames%3A%20aString2%20package%3A%20aString3%0A%09%7C%20newClass%20%7C%0A%09newClass%20%3A%3D%20self%20addSubclassOf%3A%20aClass%0A%09%09%09%09named%3A%20aString%20instanceVariableNames%3A%20%28self%20instanceVariableNamesFor%3A%20aString2%29%0A%09%09%09%09package%3A%20%28aString3%20ifNil%3A%20%5B%27unclassified%27%5D%29.%0A%09self%20setupClass%3A%20newClass.%0A%09%5EnewClass'),
 messageSends: ["addSubclassOf:named:instanceVariableNames:package:", "instanceVariableNamesFor:", "ifNil:", "setupClass:"],
 referencedClasses: []
 }),
@@ -9009,3 +9023,202 @@ smalltalk.Set);
 
 
 
+smalltalk.addClass('Transcript', smalltalk.Object, ['textarea'], 'Kernel');
+
+smalltalk.Transcript.klass.iVarNames = ['current'];
+smalltalk.addMethod(
+unescape('_open'),
+smalltalk.method({
+selector: unescape('open'),
+category: 'instance creation',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_open", []);
+return self;},
+args: [],
+source: unescape('open%0A%20%20%20%20self%20current%20open'),
+messageSends: ["open", "current"],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_new'),
+smalltalk.method({
+selector: unescape('new'),
+category: 'instance creation',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_shouldNotImplement", []);
+return self;},
+args: [],
+source: unescape('new%0A%20%20%20%20self%20shouldNotImplement'),
+messageSends: ["shouldNotImplement"],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_current'),
+smalltalk.method({
+selector: unescape('current'),
+category: 'instance creation',
+fn: function (){
+var self=this;
+return self['@current'];
+return self;},
+args: [],
+source: unescape('current%0A%20%20%20%20%5Ecurrent'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_show_'),
+smalltalk.method({
+selector: unescape('show%3A'),
+category: 'printing',
+fn: function (anObject){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_show_", [anObject]);
+return self;},
+args: ["anObject"],
+source: unescape('show%3A%20anObject%0A%20%20%20%20self%20current%20show%3A%20anObject'),
+messageSends: ["show:", "current"],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_cr'),
+smalltalk.method({
+selector: unescape('cr'),
+category: 'printing',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_show_", [smalltalk.send((smalltalk.String || String), "_cr", [])]);
+return self;},
+args: [],
+source: unescape('cr%0A%20%20%20%20self%20current%20show%3A%20String%20cr'),
+messageSends: ["show:", "current", "cr"],
+referencedClasses: [smalltalk.String]
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_clear'),
+smalltalk.method({
+selector: unescape('clear'),
+category: 'printing',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_clear", []);
+return self;},
+args: [],
+source: unescape('clear%0A%20%20%20%20self%20current%20clear'),
+messageSends: ["clear", "current"],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_register_'),
+smalltalk.method({
+selector: unescape('register%3A'),
+category: 'instance creation',
+fn: function (aTranscript){
+var self=this;
+self['@current']=aTranscript;
+return self;},
+args: ["aTranscript"],
+source: unescape('register%3A%20aTranscript%0A%09current%20%3A%3D%20aTranscript'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+
+smalltalk.addClass('ConsoleTranscript', smalltalk.Object, ['textarea'], 'Kernel');
+smalltalk.addMethod(
+unescape('_clear'),
+smalltalk.method({
+selector: unescape('clear'),
+category: 'printing',
+fn: function (){
+var self=this;
+
+return self;},
+args: [],
+source: unescape('clear%0A%09%22no%20op%22'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ConsoleTranscript);
+
+smalltalk.addMethod(
+unescape('_cr'),
+smalltalk.method({
+selector: unescape('cr'),
+category: 'printing',
+fn: function (){
+var self=this;
+
+return self;},
+args: [],
+source: unescape('cr%0A%09%22no%20op%22'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ConsoleTranscript);
+
+smalltalk.addMethod(
+unescape('_show_'),
+smalltalk.method({
+selector: unescape('show%3A'),
+category: 'printing',
+fn: function (anObject){
+var self=this;
+console.log(String(anObject._asString()));
+return self;},
+args: ["anObject"],
+source: unescape('show%3A%20anObject%0A%09%3Cconsole.log%28String%28anObject._asString%28%29%29%29%3E'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ConsoleTranscript);
+
+smalltalk.addMethod(
+unescape('_open'),
+smalltalk.method({
+selector: unescape('open'),
+category: 'actions',
+fn: function (){
+var self=this;
+
+return self;},
+args: [],
+source: unescape('open'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ConsoleTranscript);
+
+
+smalltalk.addMethod(
+unescape('_initialize'),
+smalltalk.method({
+selector: unescape('initialize'),
+category: 'initialization',
+fn: function (){
+var self=this;
+smalltalk.send((smalltalk.Transcript || Transcript), "_register_", [smalltalk.send(self, "_new", [])]);
+return self;},
+args: [],
+source: unescape('initialize%0A%09Transcript%20register%3A%20self%20new'),
+messageSends: ["register:", "new"],
+referencedClasses: [smalltalk.Transcript]
+}),
+smalltalk.ConsoleTranscript.klass);
+
+

+ 157 - 67
js/amber.js

@@ -1,103 +1,193 @@
-/* Adapted from Clamato by Avi Bryant. http://www.clamato.net */
+/* Amber package loading
+   usage example:
+   amber.load({
+     files: ['MyCategory1.js', 'MyCategory2.js'],
+     ready: function() {smalltalk.Browser._open()}
+   })
+*/
+
+
+amber = (function() {
+    var that = {};
 
-(function() {
     var scripts = document.getElementsByTagName("script");
-    var src = scripts[ scripts.length - 1 ].src;
-    var home = src.split("/").slice(0, -2).join("/") + "/";
+    var src     = scripts[ scripts.length - 1 ].src;
+    var home    = src.split("/").slice(0, -2).join("/") + "/";
     var nocache = '?' + (new Date()).getTime();
-    var deploy = false;
+
+    var debug;
+    var deploy;
+
+    var localStorageSource = [];
+    var localPackages;
+    var spec;
+
+    that.load = function(obj) {
+	spec = obj || {};
+
+	// In deployment mode, only the compressed version of Kernel
+	// and Canvas are loaded
+	deploy = spec.deploy || false;
+	debug = spec.debug || false;
+
+	// Specify a version string to avoid wrong browser caching
+	if (spec.version) {
+	    nocache = '?' + spec.version;
+	}
+	
+	loadDependencies();
+	loadJS('boot.js');
+	
+	populateLocalPackages();
+
+	if (deploy) {
+	    loadPackages([
+		'Kernel.deploy',
+		'Canvas.deploy'
+	    ]);
+	} else {
+	    loadIDEDependencies();
+	    loadCSS('amber.css');
+	    
+	    loadPackages([
+		'Kernel',
+		'Canvas',
+		'Compiler',
+		'parser',
+		'IDE',
+		'SUnit',
+		'Examples',
+		'Benchfib',
+		'Kernel-Tests'
+	    ]);
+	}
+
+	var additionalFiles = spec.packages || spec.files;
+	    if (additionalFiles) {
+		loadPackages(additionalFiles, spec.prefix);
+	    }
+
+	    // Always load all local packages
+	    for (name in localPackages) {
+		log('Local package:  ' + name);
+		localStorageSource.push(localPackages[name]);
+	    }
+
+	    // Be sure to setup & initialize smalltalk classes
+	    loadJS('init.js');
+	    initializeSmalltalk();
+    };
+
+    function loadPackages(names, prefix){
+	var name, url;
+	var prefix = prefix || 'js';
+	
+	for (var i=0; i < names.length; i++) {
+	    name = names[i].split(/\.js$/)[0];
+	    
+	    // Only load package from the server if it isn't stored in
+	    // localStorage
+	    if (!(name in localPackages)) {
+		log('Server package: ' + name);
+		loadJS(name + '.js', prefix);
+	    }
+	}
+    };
 
     function loadJS(name, prefix) {
 	var prefix = prefix || 'js';
 	var name = name;
-	if(!deploy) {
+	
+	if (!deploy) {
 	    name = name + nocache;
 	}
-	document.write('<script src="' + home + prefix + '/' + name + '" type="text/javascript"></script>');
-    }
-    
+
+	var url = home + prefix + '/' + name;
+	var scriptString = '<script src="' + url + '" type="text/javascript"></script>';
+	document.write(scriptString);
+    };
+
     function loadCSS(name, prefix) {
 	var prefix = prefix || 'css';
 	var name = name;
-	if(!deploy) {
+	if (!deploy) {
 	    name = name + nocache;
 	}
-	var link = document.createElement("link")
-  	link.setAttribute("rel", "stylesheet")
-  	link.setAttribute("type", "text/css")
-  	link.setAttribute("href", home + prefix + '/' + name)
+
+	var url = home + prefix + '/' + name;
+
+	var link = document.createElement("link");
+	link.setAttribute("rel", "stylesheet");
+	link.setAttribute("type", "text/css");
+	link.setAttribute("href", url);
 	document.getElementsByTagName("head")[0].appendChild(link);
-    }
+    };
 
     function loadDependencies() {
 	loadJS('lib/jQuery/jquery-1.6.4.min.js');
 	loadJS('lib/jQuery/jquery-ui-1.8.9.custom.min.js');
-    }
-
+    };
+    
     function loadIDEDependencies() {
 	loadJS('lib/jQuery/jquery.textarea.js');
 	loadJS('lib/CodeMirror/lib/codemirror.js');
 	loadCSS('lib/CodeMirror/lib/codemirror.css', 'js');
 	loadJS('lib/CodeMirror/mode/smalltalk/smalltalk.js');
 	loadCSS('lib/CodeMirror/theme/amber.css', 'js');
-    }
+    };
 
-    window.loadAmber = function(spec) {
-	/* 
-	 example: 
-	 loadAmber({
-	   files: ['MyCategory1.js', 'MyCategory2.js'], 
-	   ready: function() {smalltalk.Browser._open()}
-	 })
-	*/
-
-	var spec = spec || {};
-
-	// In deployment mode, only the compressed version of Kernel 
-	// and Canvas are loaded
-	deploy = spec.deploy || false;
-
-	// Specify a version string to avoid wrong browser caching
-	if(spec.version) {
-	    nocache = '?' + spec.version;
+    // This will be called after JS files have been loaded
+    function initializeSmalltalk() {
+	
+	window.smalltalkReady = function() {
+	    
+	    for (var i=0; i < localStorageSource.length; i++) {
+		eval(localStorageSource[i]);
+	    }
+	    
+	    if (deploy) {
+		smalltalk.setDeploymentMode();
+	    }
+	    
+	    if (spec.ready) {
+		spec.ready();
+	    }
 	}
+    };
 
-	loadDependencies();
-	if(deploy) {
-	    loadJS("boot.js");
-	    loadJS("Kernel.deploy.js");
-	    loadJS("Canvas.deploy.js");
-	} else {
-	    loadIDEDependencies();
-	    loadCSS('amber.css');
-	    loadJS("boot.js");
-	    loadJS("Kernel.js");
-	    loadJS("Canvas.js");
-	    loadJS("Compiler.js");
-	    loadJS("parser.js");
-	    loadJS("IDE.js");
-	    loadJS("SUnit.js");
-	    loadJS("Examples.js");
-	    loadJS("Benchfib.js");
-	    loadJS("Kernel-Tests.js");
-	}
+    function populateLocalPackages(){
+	var localStorageRE = /^smalltalk\.packages\.(.*)$/;
+	localPackages = {};
 
-	// Load other files, possibly with another directory prefix than 'js'
-	if(spec.files) {
-	    for(var i=0; i < spec.files.length; i++) {
-		loadJS(spec.files[i], spec.prefix);
+	var match, key;
+	
+	for(var i=0; i < localStorage.length; i++) {
+	    key = localStorage.key(i);
+	    
+	    if (match = key.match(localStorageRE)) {
+		localPackages[match[1]] = localStorage[key];
 	    }
 	}
 
-	smalltalkReady = function() {
-	    if(spec.ready) {
-		spec.ready();
-	    }
-	    if(deploy) {smalltalk.setDeploymentMode()}
+	return localPackages;
+    };
+
+    function clearLocalPackages() {
+	for (var name in localPackages) {
+	    log('Removing ' + name + ' from local storage');
+	    localStorage.removeItem('smalltalk.packages.' + name);
 	}
+    };
 
-	// Be sure to setup & initialize smalltalk classes
-	loadJS("init.js");
+    function log(string) {
+	if (debug) {
+	    console.log(string);
+	}
     }
 
-})();
+    return that;
+})();
+
+window.loadAmber = function(spec) {
+    amber.load(spec);
+}

+ 1 - 1
js/boot.js

@@ -41,7 +41,7 @@ if (typeof console === "undefined") {
 	warn: function() {},
 	info: function() {},
 	debug: function() {},
-	error: function() {},
+	error: function() {}
     };
 }
 

+ 1 - 1
js/init.js

@@ -5,4 +5,4 @@ smalltalk.classes()._do_(function(each) {each._initialize()});
 
 if(this.smalltalkReady) {
     this.smalltalkReady();
-}
+}

File diff suppressed because it is too large
+ 0 - 302
server/FileServer.js


+ 270 - 58
server/server.js

@@ -41,7 +41,7 @@ if (typeof console === "undefined") {
 	warn: function() {},
 	info: function() {},
 	debug: function() {},
-	error: function() {},
+	error: function() {}
     };
 }
 
@@ -750,7 +750,7 @@ return self;},
 args: ["anObject"],
 source: unescape('-%3E%20anObject%0A%09%5EAssociation%20key%3A%20self%20value%3A%20anObject'),
 messageSends: ["key:value:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.Association]
 }),
 smalltalk.Object);
 
@@ -1246,7 +1246,7 @@ return self;},
 args: ["aMessage"],
 source: unescape('doesNotUnderstand%3A%20aMessage%0A%09MessageNotUnderstood%20new%0A%09%09receiver%3A%20self%3B%0A%09%09message%3A%20aMessage%3B%0A%09%09signal'),
 messageSends: ["receiver:", "message:", "signal", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.MessageNotUnderstood]
 }),
 smalltalk.Object);
 
@@ -1838,7 +1838,7 @@ return self;},
 args: [],
 source: unescape('properties%0A%09%22It%20is%20stored%20as%20a%20javascript%20object.%22%0A%0A%09%7C%20result%20%7C%0A%09result%20%3A%3D%20Dictionary%20new.%0A%09%3Cfor%20%28var%20i%20in%20self.properties%29%20%7B%0A%09%09result._at_put_%28i%2C%20self.properties%5Bi%5D%29%3B%0A%09%7D%0A%09return%20result%3B%3E'),
 messageSends: ["new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.Dictionary]
 }),
 smalltalk.Package);
 
@@ -2158,7 +2158,7 @@ return self;},
 args: ["aString"],
 source: unescape('methodsFor%3A%20aString%0A%09%5EClassCategoryReader%20new%0A%09%20%20%20%20class%3A%20self%20category%3A%20aString%3B%0A%09%20%20%20%20yourself'),
 messageSends: ["class:category:", "yourself", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.ClassCategoryReader]
 }),
 smalltalk.Behavior);
 
@@ -2238,7 +2238,7 @@ return self;},
 args: [],
 source: unescape('commentStamp%0A%20%20%20%20%5EClassCommentReader%20new%0A%09class%3A%20self%3B%0A%09yourself'),
 messageSends: ["class:", "yourself", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.ClassCommentReader]
 }),
 smalltalk.Behavior);
 
@@ -2310,7 +2310,7 @@ return self;},
 args: ["aBlock"],
 source: unescape('protocolsDo%3A%20aBlock%0A%09%22Execute%20aBlock%20for%20each%20method%20category%20with%0A%09its%20collection%20of%20methods%20in%20the%20sort%20order%20of%20category%20name.%22%0A%0A%09%7C%20methodsByCategory%20%7C%0A%09methodsByCategory%20%3A%3D%20Dictionary%20new.%0A%09self%20methodDictionary%20values%20do%3A%20%5B%3Am%20%7C%0A%09%09%28methodsByCategory%20at%3A%20m%20category%20ifAbsentPut%3A%20%5BArray%20new%5D%29%0A%20%09%09%09add%3A%20m%5D.%20%0A%09self%20protocols%20do%3A%20%5B%3Acategory%20%7C%0A%09%09aBlock%20value%3A%20category%20value%3A%20%28methodsByCategory%20at%3A%20category%29%5D'),
 messageSends: ["new", "do:", "values", "methodDictionary", "add:", "at:ifAbsentPut:", "category", "protocols", "value:value:", "at:"],
-referencedClasses: [smalltalk.nil,smalltalk.Array]
+referencedClasses: [smalltalk.Dictionary,smalltalk.Array]
 }),
 smalltalk.Behavior);
 
@@ -2412,7 +2412,7 @@ return self;},
 args: ["aString", "anotherString"],
 source: unescape('compile%3A%20aString%20category%3A%20anotherString%0A%09%7C%20method%20%7C%0A%09method%20%3A%3D%20Compiler%20new%20load%3A%20aString%20forClass%3A%20self.%0A%09method%20category%3A%20anotherString.%0A%09self%20addCompiledMethod%3A%20method'),
 messageSends: ["load:forClass:", "new", "category:", "addCompiledMethod:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.Compiler]
 }),
 smalltalk.Behavior);
 
@@ -2579,7 +2579,7 @@ return self;},
 args: ["aString", "aString2", "aString3"],
 source: unescape('subclass%3A%20aString%20instanceVariableNames%3A%20aString2%20package%3A%20aString3%0A%09%5EClassBuilder%20new%0A%09%20%20%20%20superclass%3A%20self%20subclass%3A%20aString%20instanceVariableNames%3A%20aString2%20package%3A%20aString3'),
 messageSends: ["superclass:subclass:instanceVariableNames:package:", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.ClassBuilder]
 }),
 smalltalk.Class);
 
@@ -2614,7 +2614,7 @@ return self;},
 args: ["aCollection"],
 source: unescape('instanceVariableNames%3A%20aCollection%0A%09ClassBuilder%20new%0A%09%20%20%20%20class%3A%20self%20instanceVariableNames%3A%20aCollection'),
 messageSends: ["class:instanceVariableNames:", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.ClassBuilder]
 }),
 smalltalk.Metaclass);
 
@@ -3199,7 +3199,7 @@ return self;},
 args: [],
 source: unescape('atRandom%0A%20%20%20%20%5E%28Random%20new%20next%20*%20self%29%20truncated%20+%201'),
 messageSends: [unescape("+"), "truncated", unescape("*"), "next", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.Random]
 }),
 smalltalk.Number);
 
@@ -3215,7 +3215,7 @@ return self;},
 args: ["aNumber"],
 source: unescape('@%20aNumber%0A%09%5EPoint%20x%3A%20self%20y%3A%20aNumber'),
 messageSends: ["x:y:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.Point]
 }),
 smalltalk.Number);
 
@@ -3231,7 +3231,7 @@ return self;},
 args: [],
 source: unescape('asPoint%0A%09%5EPoint%20x%3A%20self%20y%3A%20self'),
 messageSends: ["x:y:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.Point]
 }),
 smalltalk.Number);
 
@@ -3424,6 +3424,38 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+unescape('_deepCopy'),
+smalltalk.method({
+selector: unescape('deepCopy'),
+category: 'copying',
+fn: function (){
+var self=this;
+return smalltalk.send(self, "_copy", []);
+return self;},
+args: [],
+source: unescape('deepCopy%0A%09%5Eself%20copy'),
+messageSends: ["copy"],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+unescape('_copy'),
+smalltalk.method({
+selector: unescape('copy'),
+category: 'copying',
+fn: function (){
+var self=this;
+return self;
+return self;},
+args: [],
+source: unescape('copy%0A%09%5Eself'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 
 smalltalk.addMethod(
 unescape('_pi'),
@@ -4818,7 +4850,7 @@ return self;},
 args: ["aString", "aString2", "aString3"],
 source: unescape('subclass%3A%20aString%20instanceVariableNames%3A%20aString2%20package%3A%20aString3%0A%09%5EClassBuilder%20new%0A%09%20%20%20%20superclass%3A%20self%20subclass%3A%20aString%20instanceVariableNames%3A%20aString2%20package%3A%20aString3'),
 messageSends: ["superclass:subclass:instanceVariableNames:package:", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.ClassBuilder]
 }),
 smalltalk.UndefinedObject);
 
@@ -5265,7 +5297,7 @@ return self;},
 args: [],
 source: unescape('asSet%0A%09%5ESet%20withAll%3A%20self'),
 messageSends: ["withAll:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.Set]
 }),
 smalltalk.Collection);
 
@@ -5330,7 +5362,7 @@ return self;},
 args: [],
 source: unescape('streamClass%0A%09%20%20%20%20%5EStream'),
 messageSends: [],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.Stream]
 }),
 smalltalk.Collection.klass);
 
@@ -5714,6 +5746,22 @@ referencedClasses: []
 }),
 smalltalk.SequenceableCollection);
 
+smalltalk.addMethod(
+unescape('_atRandom'),
+smalltalk.method({
+selector: unescape('atRandom'),
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.send(self, "_at_", [smalltalk.send(smalltalk.send(self, "_size", []), "_atRandom", [])]);
+return self;},
+args: [],
+source: unescape('atRandom%0A%09%5E%20self%20at%3A%20self%20size%20atRandom'),
+messageSends: ["at:", "atRandom", "size"],
+referencedClasses: []
+}),
+smalltalk.SequenceableCollection);
+
 
 
 smalltalk.addClass('String', smalltalk.SequenceableCollection, [], 'Kernel');
@@ -6539,7 +6587,7 @@ return self;},
 args: [],
 source: unescape('streamClass%0A%09%20%20%20%20%5EStringStream'),
 messageSends: [],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.StringStream]
 }),
 smalltalk.String.klass);
 
@@ -7992,41 +8040,6 @@ referencedClasses: []
 }),
 smalltalk.ClassBuilder);
 
-smalltalk.addMethod(
-unescape('_superclass_subclass_instanceVariableNames_module_'),
-smalltalk.method({
-selector: unescape('superclass%3Asubclass%3AinstanceVariableNames%3Amodule%3A'),
-category: 'class creation',
-fn: function (aClass, aString, aString2, aString3){
-var self=this;
-var newClass=nil;
-newClass=smalltalk.send(self, "_addSubclassOf_named_instanceVariableNames_module_", [aClass, aString, smalltalk.send(self, "_instanceVariableNamesFor_", [aString2]), (($receiver = aString3) == nil || $receiver == undefined) ? (function(){return "unclassified";})() : $receiver]);
-smalltalk.send(self, "_setupClass_", [newClass]);
-return self;},
-args: ["aClass", "aString", "aString2", "aString3"],
-source: unescape('superclass%3A%20aClass%20subclass%3A%20aString%20instanceVariableNames%3A%20aString2%20module%3A%20aString3%0A%09%7C%20newClass%20%7C%0A%09newClass%20%3A%3D%20self%20addSubclassOf%3A%20aClass%0A%09%09%09%09named%3A%20aString%20instanceVariableNames%3A%20%28self%20instanceVariableNamesFor%3A%20aString2%29%0A%09%09%09%09module%3A%20%28aString3%20ifNil%3A%20%5B%27unclassified%27%5D%29.%0A%09self%20setupClass%3A%20newClass'),
-messageSends: ["addSubclassOf:named:instanceVariableNames:module:", "instanceVariableNamesFor:", "ifNil:", "setupClass:"],
-referencedClasses: []
-}),
-smalltalk.ClassBuilder);
-
-smalltalk.addMethod(
-unescape('_addSubclassOf_named_instanceVariableNames_module_'),
-smalltalk.method({
-selector: unescape('addSubclassOf%3Anamed%3AinstanceVariableNames%3Amodule%3A'),
-category: 'private',
-fn: function (aClass, aString, aCollection, moduleName){
-var self=this;
-smalltalk.addClass(aString, aClass, aCollection, moduleName);
-	    return smalltalk[aString];
-return self;},
-args: ["aClass", "aString", "aCollection", "moduleName"],
-source: unescape('addSubclassOf%3A%20aClass%20named%3A%20aString%20instanceVariableNames%3A%20aCollection%20module%3A%20moduleName%0A%09%3Csmalltalk.addClass%28aString%2C%20aClass%2C%20aCollection%2C%20moduleName%29%3B%0A%09%20%20%20%20return%20smalltalk%5BaString%5D%3E'),
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.ClassBuilder);
-
 smalltalk.addMethod(
 unescape('_superclass_subclass_instanceVariableNames_package_'),
 smalltalk.method({
@@ -8037,9 +8050,10 @@ var self=this;
 var newClass=nil;
 newClass=smalltalk.send(self, "_addSubclassOf_named_instanceVariableNames_package_", [aClass, aString, smalltalk.send(self, "_instanceVariableNamesFor_", [aString2]), (($receiver = aString3) == nil || $receiver == undefined) ? (function(){return "unclassified";})() : $receiver]);
 smalltalk.send(self, "_setupClass_", [newClass]);
+return newClass;
 return self;},
 args: ["aClass", "aString", "aString2", "aString3"],
-source: unescape('superclass%3A%20aClass%20subclass%3A%20aString%20instanceVariableNames%3A%20aString2%20package%3A%20aString3%0A%09%7C%20newClass%20%7C%0A%09newClass%20%3A%3D%20self%20addSubclassOf%3A%20aClass%0A%09%09%09%09named%3A%20aString%20instanceVariableNames%3A%20%28self%20instanceVariableNamesFor%3A%20aString2%29%0A%09%09%09%09package%3A%20%28aString3%20ifNil%3A%20%5B%27unclassified%27%5D%29.%0A%09self%20setupClass%3A%20newClass'),
+source: unescape('superclass%3A%20aClass%20subclass%3A%20aString%20instanceVariableNames%3A%20aString2%20package%3A%20aString3%0A%09%7C%20newClass%20%7C%0A%09newClass%20%3A%3D%20self%20addSubclassOf%3A%20aClass%0A%09%09%09%09named%3A%20aString%20instanceVariableNames%3A%20%28self%20instanceVariableNamesFor%3A%20aString2%29%0A%09%09%09%09package%3A%20%28aString3%20ifNil%3A%20%5B%27unclassified%27%5D%29.%0A%09self%20setupClass%3A%20newClass.%0A%09%5EnewClass'),
 messageSends: ["addSubclassOf:named:instanceVariableNames:package:", "instanceVariableNamesFor:", "ifNil:", "setupClass:"],
 referencedClasses: []
 }),
@@ -8078,7 +8092,7 @@ return self;},
 args: [],
 source: unescape('initialize%0A%09super%20initialize.%0A%09chunkParser%20%3A%3D%20ChunkParser%20new.'),
 messageSends: ["initialize", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.ChunkParser]
 }),
 smalltalk.ClassCategoryReader);
 
@@ -8131,7 +8145,7 @@ return self;},
 args: ["aString"],
 source: unescape('compileMethod%3A%20aString%0A%09%7C%20method%20%7C%0A%09method%20%3A%3D%20Compiler%20new%20load%3A%20aString%20forClass%3A%20class.%0A%09method%20category%3A%20category.%0A%09class%20addCompiledMethod%3A%20method'),
 messageSends: ["load:forClass:", "new", "category:", "addCompiledMethod:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.Compiler]
 }),
 smalltalk.ClassCategoryReader);
 
@@ -8699,7 +8713,7 @@ return self;},
 args: [],
 source: unescape('initialize%0A%09super%20initialize.%0A%09chunkParser%20%3A%3D%20ChunkParser%20new.'),
 messageSends: ["initialize", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.ChunkParser]
 }),
 smalltalk.ClassCommentReader);
 
@@ -9571,6 +9585,205 @@ smalltalk.Set);
 
 
 
+smalltalk.addClass('Transcript', smalltalk.Object, ['textarea'], 'Kernel');
+
+smalltalk.Transcript.klass.iVarNames = ['current'];
+smalltalk.addMethod(
+unescape('_open'),
+smalltalk.method({
+selector: unescape('open'),
+category: 'instance creation',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_open", []);
+return self;},
+args: [],
+source: unescape('open%0A%20%20%20%20self%20current%20open'),
+messageSends: ["open", "current"],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_new'),
+smalltalk.method({
+selector: unescape('new'),
+category: 'instance creation',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_shouldNotImplement", []);
+return self;},
+args: [],
+source: unescape('new%0A%20%20%20%20self%20shouldNotImplement'),
+messageSends: ["shouldNotImplement"],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_current'),
+smalltalk.method({
+selector: unescape('current'),
+category: 'instance creation',
+fn: function (){
+var self=this;
+return self['@current'];
+return self;},
+args: [],
+source: unescape('current%0A%20%20%20%20%5Ecurrent'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_show_'),
+smalltalk.method({
+selector: unescape('show%3A'),
+category: 'printing',
+fn: function (anObject){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_show_", [anObject]);
+return self;},
+args: ["anObject"],
+source: unescape('show%3A%20anObject%0A%20%20%20%20self%20current%20show%3A%20anObject'),
+messageSends: ["show:", "current"],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_cr'),
+smalltalk.method({
+selector: unescape('cr'),
+category: 'printing',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_show_", [smalltalk.send((smalltalk.String || String), "_cr", [])]);
+return self;},
+args: [],
+source: unescape('cr%0A%20%20%20%20self%20current%20show%3A%20String%20cr'),
+messageSends: ["show:", "current", "cr"],
+referencedClasses: [smalltalk.String]
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_clear'),
+smalltalk.method({
+selector: unescape('clear'),
+category: 'printing',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_current", []), "_clear", []);
+return self;},
+args: [],
+source: unescape('clear%0A%20%20%20%20self%20current%20clear'),
+messageSends: ["clear", "current"],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+smalltalk.addMethod(
+unescape('_register_'),
+smalltalk.method({
+selector: unescape('register%3A'),
+category: 'instance creation',
+fn: function (aTranscript){
+var self=this;
+self['@current']=aTranscript;
+return self;},
+args: ["aTranscript"],
+source: unescape('register%3A%20aTranscript%0A%09current%20%3A%3D%20aTranscript'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Transcript.klass);
+
+
+smalltalk.addClass('ConsoleTranscript', smalltalk.Object, ['textarea'], 'Kernel');
+smalltalk.addMethod(
+unescape('_clear'),
+smalltalk.method({
+selector: unescape('clear'),
+category: 'printing',
+fn: function (){
+var self=this;
+
+return self;},
+args: [],
+source: unescape('clear%0A%09%22no%20op%22'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ConsoleTranscript);
+
+smalltalk.addMethod(
+unescape('_cr'),
+smalltalk.method({
+selector: unescape('cr'),
+category: 'printing',
+fn: function (){
+var self=this;
+
+return self;},
+args: [],
+source: unescape('cr%0A%09%22no%20op%22'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ConsoleTranscript);
+
+smalltalk.addMethod(
+unescape('_show_'),
+smalltalk.method({
+selector: unescape('show%3A'),
+category: 'printing',
+fn: function (anObject){
+var self=this;
+console.log(String(anObject._asString()));
+return self;},
+args: ["anObject"],
+source: unescape('show%3A%20anObject%0A%09%3Cconsole.log%28String%28anObject._asString%28%29%29%29%3E'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ConsoleTranscript);
+
+smalltalk.addMethod(
+unescape('_open'),
+smalltalk.method({
+selector: unescape('open'),
+category: 'actions',
+fn: function (){
+var self=this;
+
+return self;},
+args: [],
+source: unescape('open'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ConsoleTranscript);
+
+
+smalltalk.addMethod(
+unescape('_initialize'),
+smalltalk.method({
+selector: unescape('initialize'),
+category: 'initialization',
+fn: function (){
+var self=this;
+smalltalk.send((smalltalk.Transcript || Transcript), "_register_", [smalltalk.send(self, "_new", [])]);
+return self;},
+args: [],
+source: unescape('initialize%0A%09Transcript%20register%3A%20self%20new'),
+messageSends: ["register:", "new"],
+referencedClasses: [smalltalk.Transcript]
+}),
+smalltalk.ConsoleTranscript.klass);
+
+
 smalltalk.addPackage('FileServer', []);
 smalltalk.addClass('FileServer', smalltalk.Object, ['path', 'http', 'fs', 'url', 'port', 'basePath', 'sys'], 'FileServer');
 smalltalk.addMethod(
@@ -9938,5 +10151,4 @@ smalltalk.classes()._do_(function(each) {each._initialize()});
 
 if(this.smalltalkReady) {
     this.smalltalkReady();
-}
-smalltalk.FileServer._main()
+}smalltalk.FileServer._main()

+ 12 - 18
st/Canvas.st

@@ -214,6 +214,14 @@ li: anObject
 
 ul: anObject
     ^self ul with: anObject
+!
+
+span: anObject
+    ^self span with: anObject
+!
+
+style: aString
+	^ self style with: aString; yourself
 ! !
 
 !HTMLCanvas class methodsFor: 'instance creation'!
@@ -338,6 +346,10 @@ width: aString
 
 height: aString
     self  at: 'height' put: aString
+!
+
+value: aString
+    self  at: 'value' put: aString
 ! !
 
 !TagBrush methodsFor: 'converting'!
@@ -416,24 +428,6 @@ Object subclass: #Widget
 	instanceVariableNames: ''
 	category: 'Canvas'!
 
-!Widget methodsFor: 'actions'!
-
-alert: aString
-    <alert(aString)>
-!
-
-confirm: aString
-    <return window.confirm(aString)>
-!
-
-prompt: aString
-    ^self prompt: aString default: ''
-!
-
-prompt: aString default: anotherString
-    <return window.prompt(aString, anotherString)>
-! !
-
 !Widget methodsFor: 'adding'!
 
 appendToBrush: aTagBrush

+ 164 - 126
st/IDE.st

@@ -1,4 +1,5 @@
 Smalltalk current createPackage: 'IDE' properties: #{}!
+
 Widget subclass: #TabManager
 	instanceVariableNames: 'selectedTab tabs opened ul input'
 	category: 'IDE'!
@@ -120,7 +121,7 @@ initialize
 	addClass: 'jtalkBody'.
     self appendToJQuery: '#jtalk' asJQuery.
     self 
-	addTab: Transcript current;
+	addTab: IDETranscript current;
 	addTab: Workspace new;
 	addTab: TestRunner new.
     self selectTab: self tabs last.
@@ -339,79 +340,8 @@ renderButtonsOn: html
 	onClick: [self clearWorkspace]
 ! !
 
-TabWidget subclass: #Transcript
-	instanceVariableNames: 'textarea'
-	category: 'IDE'!
-
-!Transcript methodsFor: 'accessing'!
-
-label
-    ^'Transcript'
-! !
-
-!Transcript methodsFor: 'actions'!
-
-show: anObject
-    textarea asJQuery val: textarea asJQuery val, anObject asString.
-!
-
-cr
-    textarea asJQuery val: textarea asJQuery val, String cr.
-!
-
-clear
-    textarea asJQuery val: ''
-! !
-
-!Transcript methodsFor: 'rendering'!
-
-renderBoxOn: html
-    textarea := html textarea.
-    textarea 
-	class: 'jt_transcript';
-	at: 'spellcheck' put: 'false'
-!
-
-renderButtonsOn: html
-    html button
-	with: 'Clear transcript';
-	onClick: [self clear]
-! !
-
-Transcript class instanceVariableNames: 'current'!
-
-!Transcript class methodsFor: 'instance creation'!
-
-open
-    TabManager current 
-	open;
-	selectTab: self current
-!
-
-new
-    self shouldNotImplement
-!
-
-current
-    ^current ifNil: [current := super new]
-! !
-
-!Transcript class methodsFor: 'printing'!
-
-show: anObject
-    self current show: anObject
-!
-
-cr
-    self current show: String cr
-!
-
-clear
-    self current clear
-! !
-
 TabWidget subclass: #Browser
-	instanceVariableNames: 'selectedPackage selectedClass selectedProtocol selectedMethod commitButton packagesList classesList protocolsList methodsList sourceArea tabsList selectedTab saveButton classButtons methodButtons unsavedChanges renameButton deleteButton'
+	instanceVariableNames: 'selectedPackage selectedClass selectedProtocol selectedMethod packagesList classesList protocolsList methodsList sourceArea tabsList selectedTab saveButton classButtons methodButtons unsavedChanges'
 	category: 'IDE'!
 
 !Browser methodsFor: 'accessing'!
@@ -498,9 +428,9 @@ declarationSource
 !
 
 classDeclarationSource
-    | stream |
-    stream := '' writeStream.
-    selectedClass ifNotNil: [
+	| stream |
+	stream := '' writeStream.
+	selectedClass ifNil: [^self classDeclarationTemplate].
 	stream 
 	    nextPutAll: selectedClass superclass asString;
 	    nextPutAll: ' subclass: #';
@@ -514,8 +444,8 @@ classDeclarationSource
 	    nextPutAll: '''', String lf, String tab;
 	    nextPutAll: 'package: ''';
 	    nextPutAll: selectedClass category;
-	    nextPutAll: ''''].
-    ^stream contents
+	    nextPutAll: ''''.
+	^stream contents
 !
 
 metaclassDeclarationSource
@@ -539,6 +469,16 @@ classCommentSource
 
 selectedClass
 	^selectedClass
+!
+
+classDeclarationTemplate
+	^'Object subclass: #NameOfSubclass
+	instanceVariableNames: ''''
+	package: ''', self selectedPackage, ''''
+!
+
+selectedPackage
+	^selectedPackage
 ! !
 
 !Browser methodsFor: 'actions'!
@@ -588,21 +528,23 @@ compileMethodDefinition
 !
 
 compileMethodDefinitionFor: aClass
-    | compiler method source node |
+    | compiler method source node | 
     source := sourceArea val.
     selectedProtocol ifNil: [selectedProtocol := selectedMethod category].
     compiler := Compiler new.
     compiler source: source.
     node := compiler parse: source.
     node isParseFailure ifTrue: [
-	^self alert: 'PARSE ERROR: ', node reason, ', position: ', node position asString].
+	^window alert: 'PARSE ERROR: ', node reason, ', position: ', node position asString].
     compiler currentClass: aClass.
     method := compiler eval: (compiler compileNode: node).
     method category: selectedProtocol.
     compiler unknownVariables do: [:each |
-	(self confirm: 'Declare ''', each, ''' as instance variable?') ifTrue: [
-		self addInstanceVariableNamed: each toClass: aClass.
-		^self compileMethodDefinitionFor: aClass]].
+         "Do not try to redeclare javascript's objects"
+         (window at: each) ifNil: [
+	 	(window confirm: 'Declare ''', each, ''' as instance variable?') ifTrue: [
+			self addInstanceVariableNamed: each toClass: aClass.
+			^self compileMethodDefinitionFor: aClass]]].
     aClass addCompiledMethod: method.
     compiler setupClass: aClass.
     self updateMethodsList.
@@ -615,17 +557,18 @@ compileDefinition
     self 
 	resetClassesList;
 	updateCategoriesList;
-	updateClassesList
+	updateClassesList.
+    self selectClass: newClass
 !
 
 cancelChanges
     ^unsavedChanges 
-	ifTrue: [self confirm: 'Cancel changes?']
+	ifTrue: [window confirm: 'Cancel changes?']
 	ifFalse: [true]
 !
 
 removeClass
-    (self confirm: 'Do you really want to remove ', selectedClass name, '?')
+    (window confirm: 'Do you really want to remove ', selectedClass name, '?')
 	ifTrue: [
 	    Smalltalk current removeClass: selectedClass.
 	    self resetClassesList.
@@ -634,7 +577,7 @@ removeClass
 
 removeMethod
     self cancelChanges ifTrue: [
-	(self confirm: 'Do you really want to remove #', selectedMethod selector, '?')
+	(window confirm: 'Do you really want to remove #', selectedMethod selector, '?')
 	    ifTrue: [
 		selectedTab = #instance 
 			ifTrue: [selectedClass removeCompiledMethod: selectedMethod]
@@ -658,7 +601,7 @@ setMethodProtocol: aString
 
 addNewProtocol
     | newProtocol |
-    newProtocol := self prompt: 'New method protocol'.
+    newProtocol := window prompt: 'New method protocol'.
     (newProtocol notNil and: [newProtocol notEmpty]) ifTrue: [
 	selectedMethod category: newProtocol.
 	self setMethodProtocol: newProtocol]
@@ -716,8 +659,8 @@ selectTab: aString
 
 renameClass
     | newName |
-    newName := self prompt: 'Rename class ', selectedClass name.
-    newName notEmpty ifTrue: [
+    newName := window prompt: 'Rename class ', selectedClass name.
+    (newName notNil and: [newName notEmpty]) ifTrue: [
 	selectedClass rename: newName.
 	self 
 		updateClassesList;
@@ -766,28 +709,28 @@ commitPackage
 			options: #{
 				'type' -> 'PUT'.
 				'data' -> (Exporter new exportPackage: selectedPackage).
-				'error' -> [self alert: 'Commit failed!!']
+				'error' -> [window alert: 'Commit failed!!']
 			}.
 		jQuery 
 			ajax: self class commitPathJs, '/', selectedPackage, '.deploy.js'
 			options: #{
 				'type' -> 'PUT'.
 				'data' -> (StrippedExporter new exportPackage: selectedPackage).
-				'error' -> [self alert: 'Commit failed!!']
+				'error' -> [window alert: 'Commit failed!!']
 			}.
 		jQuery 
 			ajax: self class commitPathSt, '/', selectedPackage, '.st'
 			options: #{
 				'type' -> 'PUT'.
 				'data' -> (ChunkExporter new exportPackage: selectedPackage).
-				'error' -> [self alert: 'Commit failed!!']
+				'error' -> [window alert: 'Commit failed!!']
 			}]
 !
 
 renamePackage
 
   | newName |
-  newName := self prompt: 'Rename package ', selectedPackage.
+  newName := window prompt: 'Rename package ', selectedPackage.
   newName ifNotNil: [
     newName notEmpty ifTrue: [
 	Smalltalk current renamePackage: selectedPackage to: newName.
@@ -796,10 +739,29 @@ renamePackage
 
 removePackage
 
-  (self confirm: 'Do you really want to remove the whole package ', selectedPackage, ' with all its classes?')
+  (window confirm: 'Do you really want to remove the whole package ', selectedPackage, ' with all its classes?')
 	ifTrue: [
 	    Smalltalk current removePackage: selectedPackage.
 	    self updateCategoriesList]
+!
+
+commitPackageToLocalStorage
+	| key sourceCode |
+	selectedPackage ifNotNil: [
+          	key := 'smalltalk.packages.' , selectedPackage.
+		sourceCode := (Exporter new exportPackage: selectedPackage).
+		<localStorage[key] = sourceCode>]
+!
+
+addNewClass
+	| className |
+	className := window prompt: 'New class'.
+	(className notNil and: [className notEmpty]) ifTrue: [
+		Object subclass: className instanceVariableNames: '' package: self selectedPackage.
+          	 self 
+			resetClassesList;
+			updateClassesList.
+		self selectClass: (Smalltalk current at: className)]
 ! !
 
 !Browser methodsFor: 'initialization'!
@@ -807,6 +769,7 @@ removePackage
 initialize
     super initialize.
     selectedTab := #instance.
+    selectedPackage := self packages first.
     unsavedChanges := false
 ! !
 
@@ -820,35 +783,37 @@ renderBoxOn: html
 !
 
 renderTopPanelOn: html
-    html div 
-	class: 'top'; 
-	with: [
-	    packagesList := html ul class: 'jt_column browser packages'.
-	    commitButton := html button 
-		class: 'jt_commit';
-		title: 'Commit classes in this package to disk';
-		onClick: [self commitPackage];
-		with: 'Commit package'.
-            renameButton := html button 
-		class: 'jt_rename';
-		title: 'Rename this package';
-		onClick: [self renamePackage];
-		with: 'Rename package'.
-            deleteButton := html button 
-		class: 'jt_delete';
-		title: 'Remove this package from the system';
-		onClick: [self removePackage];
-		with: 'Remove package'.
-	    classesList := ClassesList on: self.
-	    classesList renderOn: html.
-	    protocolsList := html ul class: 'jt_column browser protocols'.
-	    methodsList := html ul class: 'jt_column browser methods'.
-	    self
-		updateCategoriesList;
-		updateClassesList;
-		updateProtocolsList;
-		updateMethodsList.
-	    html div class: 'jt_clear']
+	html div 
+		class: 'top'; 
+		with: [
+			packagesList := html ul class: 'jt_column browser packages'.
+          		html div class: 'jt_packagesButtons'; with: [
+				html button 
+					title: 'Commit classes in this package to disk';
+					onClick: [self commitPackage];
+					with: 'Commit'.
+        			html button 
+					title: 'Commit classes in this package to local storage';
+					onClick: [self commitPackageToLocalStorage];
+					with: 'Local'.
+        			html button
+					title: 'Rename package';
+					onClick: [self renamePackage];
+					with: 'Rename'.
+        			html button
+					title: 'Remove this package from the system';
+					onClick: [self removePackage];
+					with: 'Remove'].
+			classesList := ClassesList on: self.
+			classesList renderOn: html.
+			protocolsList := html ul class: 'jt_column browser protocols'.
+			methodsList := html ul class: 'jt_column browser methods'.
+			self
+				updateCategoriesList;
+				updateClassesList;
+				updateProtocolsList;
+				updateMethodsList.
+			html div class: 'jt_clear']
 !
 
 renderTabsOn: html
@@ -976,6 +941,10 @@ updateTabsList
 updateSourceAndButtons
 	self disableSaveButton.
 	classButtons contents: [:html |
+		html button
+			title: 'Create a new class';
+			onClick: [self addNewClass];
+			with: 'New class'.
 		html button
 			with: 'Rename class';
 			onClick: [self renameClass].
@@ -1439,7 +1408,7 @@ setEditorOn: aTextarea
                 lineNumbers: true,
                 enterMode: 'classic',
                 matchBrackets: true,
-                electricChars: false,
+                electricChars: false
 	})>
 !
 
@@ -1486,7 +1455,7 @@ eval: aString
 	| compiler  |
 	compiler := Compiler new.
 	[compiler parseExpression: aString] on: Error do: [:ex |
-		^self alert: ex messageText].
+		^window alert: ex messageText].
 	^(compiler load: 'doIt ^[', aString, '] value' forClass: DoIt) fn applyTo: self receiver arguments: #()
 !
 
@@ -2214,6 +2183,75 @@ updateStatusDiv
 		html span with: self statusInfo]
 ! !
 
+TabWidget subclass: #IDETranscript
+	instanceVariableNames: 'textarea'
+	category: 'IDE'!
+
+!IDETranscript methodsFor: 'accessing'!
+
+label
+    ^'Transcript'
+! !
+
+!IDETranscript methodsFor: 'actions'!
+
+clear
+    textarea asJQuery val: ''
+!
+
+cr
+    textarea asJQuery val: textarea asJQuery val, String cr.
+!
+
+show: anObject
+    textarea asJQuery val: textarea asJQuery val, anObject asString.
+!
+
+open
+    TabManager current 
+	open;
+	selectTab: self
+! !
+
+!IDETranscript methodsFor: 'rendering'!
+
+renderBoxOn: html
+    textarea := html textarea.
+    textarea 
+	class: 'jt_transcript';
+	at: 'spellcheck' put: 'false'
+!
+
+renderButtonsOn: html
+    html button
+	with: 'Clear transcript';
+	onClick: [self clear]
+! !
+
+IDETranscript class instanceVariableNames: 'current'!
+
+!IDETranscript class methodsFor: 'initialization'!
+
+initialize
+	Transcript register: self current
+! !
+
+!IDETranscript class methodsFor: 'instance creation'!
+
+new
+    self shouldNotImplement
+!
+
+open
+    TabManager current 
+	open;
+	selectTab: self current
+!
+
+current
+	^current ifNil: [current := super new]
+! !
+
 !Object methodsFor: '*IDE'!
 
 inspect

+ 7 - 4
st/Kernel-Tests.st

@@ -155,7 +155,7 @@ TestCase subclass: #NumberTest
 	instanceVariableNames: ''
 	category: 'Kernel-Tests'!
 
-!NumberTest methodsFor: 'not yet classified'!
+!NumberTest methodsFor: 'tests'!
 
 testPrintShowingDecimalPlaces
 	self assert: '23.00' equals: (23 printShowingDecimalPlaces: 2).
@@ -171,9 +171,7 @@ testPrintShowingDecimalPlaces
 	self assert: '2.57' equals: (2.567 printShowingDecimalPlaces: 2).
 	self assert: '-2.57' equals: (-2.567 printShowingDecimalPlaces: 2).
 	self assert: '0.00' equals: (0 printShowingDecimalPlaces: 2).
-! !
-
-!NumberTest methodsFor: 'tests'!
+!
 
 testEquality
 	self assert: 1 = 1.
@@ -238,6 +236,11 @@ testTruncated
 	self assert: 3 truncated = 3.
 	self assert: 3.212 truncated = 3.
 	self assert: 3.51 truncated = 3
+!
+
+testCopying
+	self assert: 1 copy = 1.
+	self assert: 1 deepCopy = 1
 ! !
 
 TestCase subclass: #JSObjectProxyTest

+ 83 - 14
st/Kernel.st

@@ -947,6 +947,16 @@ to: stop by: step
 	^array
 ! !
 
+!Number methodsFor: 'copying'!
+
+deepCopy
+	^self copy
+!
+
+copy
+	^self
+! !
+
 !Number methodsFor: 'enumerating'!
 
 timesRepeat: aBlock
@@ -1756,6 +1766,10 @@ indexOf: anObject startingAt: start
 	within the receiver. If the receiver does not contain anElement, 
 	answer 0."
 	^self indexOf: anObject startingAt: start ifAbsent: [0]
+!
+
+atRandom
+	^ self at: self size atRandom
 ! !
 
 !SequenceableCollection methodsFor: 'adding'!
@@ -2598,20 +2612,13 @@ class: aClass instanceVariableNames: aString
 	self setupClass: aClass
 !
 
-superclass: aClass subclass: aString instanceVariableNames: aString2 module: aString3
-	| newClass |
-	newClass := self addSubclassOf: aClass
-				named: aString instanceVariableNames: (self instanceVariableNamesFor: aString2)
-				module: (aString3 ifNil: ['unclassified']).
-	self setupClass: newClass
-!
-
 superclass: aClass subclass: aString instanceVariableNames: aString2 package: aString3
 	| newClass |
 	newClass := self addSubclassOf: aClass
 				named: aString instanceVariableNames: (self instanceVariableNamesFor: aString2)
 				package: (aString3 ifNil: ['unclassified']).
-	self setupClass: newClass
+	self setupClass: newClass.
+	^newClass
 ! !
 
 !ClassBuilder methodsFor: 'private'!
@@ -2629,11 +2636,6 @@ setupClass: aClass
 	<smalltalk.init(aClass);>
 !
 
-addSubclassOf: aClass named: aString instanceVariableNames: aCollection module: moduleName
-	<smalltalk.addClass(aString, aClass, aCollection, moduleName);
-	    return smalltalk[aString]>
-!
-
 addSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName
 	<smalltalk.addClass(aString, aClass, aCollection, packageName);
 	    return smalltalk[aString]>
@@ -3202,3 +3204,70 @@ includes: anObject
 	^elements includes: anObject
 ! !
 
+Object subclass: #Transcript
+	instanceVariableNames: 'textarea'
+	category: 'Kernel'!
+
+Transcript class instanceVariableNames: 'current'!
+
+!Transcript class methodsFor: 'instance creation'!
+
+open
+    self current open
+!
+
+new
+    self shouldNotImplement
+!
+
+current
+    ^current
+!
+
+register: aTranscript
+	current := aTranscript
+! !
+
+!Transcript class methodsFor: 'printing'!
+
+show: anObject
+    self current show: anObject
+!
+
+cr
+    self current show: String cr
+!
+
+clear
+    self current clear
+! !
+
+Object subclass: #ConsoleTranscript
+	instanceVariableNames: 'textarea'
+	category: 'Kernel'!
+
+!ConsoleTranscript methodsFor: 'actions'!
+
+open
+! !
+
+!ConsoleTranscript methodsFor: 'printing'!
+
+clear
+	"no op"
+!
+
+cr
+	"no op"
+!
+
+show: anObject
+	<console.log(String(anObject._asString()))>
+! !
+
+!ConsoleTranscript class methodsFor: 'initialization'!
+
+initialize
+	Transcript register: self new
+! !
+

Some files were not shown because too many files changed in this diff