Browse Source

guardContents, fix nested [trap-data] tags, lot is in html now

Herbert Vojčík 11 years ago
parent
commit
9b01ac1387
5 changed files with 139 additions and 134 deletions
  1. 21 87
      js/Trapped-Demo.js
  2. 66 10
      js/Trapped-Frontend.js
  3. 13 2
      meta/demo.html
  4. 8 31
      st/Trapped-Demo.st
  5. 31 4
      st/Trapped-Frontend.st

+ 21 - 87
js/Trapped-Demo.js

@@ -231,8 +231,8 @@ smalltalk.AppModel);
 
 
 
-smalltalk.addClass('TemporaryWidget', smalltalk.Widget, [], 'Trapped-Demo');
-smalltalk.TemporaryWidget.comment="<!-- Code from AngularJS Todo example, http://angularjs.org/#todo-html -->\x0a  <body>\x0a    <h2>Todo</h2>\x0a    <div ng-controller=\x22TodoCtrl\x22>\x0a      <span>{{remaining()}} of {{todos.length}} remaining</span>\x0a      [ <a href=\x22\x22 ng-click=\x22archive()\x22>archive</a> ]\x0a      <ul class=\x22unstyled\x22>\x0a        <li ng-repeat=\x22todo in todos\x22>\x0a          <input type=\x22checkbox\x22 ng-model=\x22todo.done\x22>\x0a          <span class=\x22done-{{todo.done}}\x22>{{todo.text}}</span>\x0a        </li>\x0a      </ul>\x0a      <form ng-submit=\x22addTodo()\x22>\x0a        <input type=\x22text\x22 ng-model=\x22todoText\x22  size=\x2230\x22\x0a               placeholder=\x22add new todo here\x22>\x0a        <input class=\x22btn-primary\x22 type=\x22submit\x22 value=\x22add\x22>\x0a      </form>\x0a    </div>\x0a  </body>";
+smalltalk.addClass('TodoItemsWidget', smalltalk.Widget, [], 'Trapped-Demo');
+smalltalk.TodoItemsWidget.comment="<!-- Code from AngularJS Todo example, http://angularjs.org/#todo-html -->\x0a  <body>\x0a    <h2>Todo</h2>\x0a    <div ng-controller=\x22TodoCtrl\x22>\x0a      <span>{{remaining()}} of {{todos.length}} remaining</span>\x0a      [ <a href=\x22\x22 ng-click=\x22archive()\x22>archive</a> ]\x0a      <ul class=\x22unstyled\x22>\x0a        <li ng-repeat=\x22todo in todos\x22>\x0a          <input type=\x22checkbox\x22 ng-model=\x22todo.done\x22>\x0a          <span class=\x22done-{{todo.done}}\x22>{{todo.text}}</span>\x0a        </li>\x0a      </ul>\x0a      <form ng-submit=\x22addTodo()\x22>\x0a        <input type=\x22text\x22 ng-model=\x22todoText\x22  size=\x2230\x22\x0a               placeholder=\x22add new todo here\x22>\x0a        <input class=\x22btn-primary\x22 type=\x22submit\x22 value=\x22add\x22>\x0a      </form>\x0a    </div>\x0a  </body>";
 smalltalk.addMethod(
 smalltalk.method({
 selector: "renderOn:",
@@ -240,97 +240,31 @@ category: 'rendering',
 fn: function (html){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$12,$13,$14,$15,$11;
-$1=_st(html)._span();
-$ctx1.sendIdx["span"]=1;
-_st($1)._trap_([["remaining"]]);
-$ctx1.sendIdx["trap:"]=1;
-_st(html)._with_(" of ");
-$ctx1.sendIdx["with:"]=1;
-$2=_st(html)._span();
-$ctx1.sendIdx["span"]=2;
-_st($2)._trap_([["todos"], ["size"]]);
-$ctx1.sendIdx["trap:"]=2;
-_st(html)._with_(" remaining [ ");
-$ctx1.sendIdx["with:"]=2;
-$3=_st(html)._a();
-_st($3)._href_("");
-_st($3)._trap_processors_([],[["signal", "archive"], "whenClicked"]);
-$ctx1.sendIdx["trap:processors:"]=1;
-$4=_st($3)._with_("archive");
-$ctx1.sendIdx["with:"]=3;
-_st(html)._with_(" ]");
-$ctx1.sendIdx["with:"]=4;
-_st(_st(html)._ul())._with_((function(){
+var $1,$2,$3,$4,$5;
+_st(html)._trapIter_tag_do_([],"li",(function(each){
 return smalltalk.withContext(function($ctx2) {
-return _st(html)._trapIter_tag_do_([["todos"]],"li",(function(each){
+$1=_st(html)._root();
+$ctx2.sendIdx["root"]=1;
+_st($1)._empty();
+$2=_st(html)._input();
+_st($2)._type_("checkbox");
+$3=_st($2)._trap_processors_(["done"],["inputChecked"]);
+$3;
+$4=_st(html)._span();
+_st($4)._trap_read_(["done"],(function(model){
 return smalltalk.withContext(function($ctx3) {
-$5=_st(html)._root();
-$ctx3.sendIdx["root"]=1;
-_st($5)._empty();
-$6=_st(html)._input();
-$ctx3.sendIdx["input"]=1;
-_st($6)._type_("checkbox");
-$ctx3.sendIdx["type:"]=1;
-$7=_st($6)._trap_processors_(["done"],["inputChecked"]);
-$ctx3.sendIdx["trap:processors:"]=2;
-$7;
-$8=_st(html)._span();
-_st($8)._trap_read_(["done"],(function(model){
-return smalltalk.withContext(function($ctx4) {
 return _st(_st(html)._root())._class_("done-".__comma(model));
-$ctx4.sendIdx["class:"]=1;
-}, function($ctx4) {$ctx4.fillBlock({model:model},$ctx3,3)})}));
-$9=_st($8)._trap_(["text"]);
-return $9;
-}, function($ctx3) {$ctx3.fillBlock({each:each},$ctx2,2)})}));
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
-$ctx1.sendIdx["with:"]=5;
-$10=_st(html)._form();
-_st($10)._trap_processors_([],[["signal", "addTodo"], "whenSubmitted"]);
-$ctx1.sendIdx["trap:processors:"]=3;
-$11=_st($10)._with_((function(){
-return smalltalk.withContext(function($ctx2) {
-$12=_st(html)._input();
-$ctx2.sendIdx["input"]=2;
-_st($12)._type_("text");
-$ctx2.sendIdx["type:"]=2;
-_st($12)._trap_processors_([["todoText"]],["inputValue"]);
-_st($12)._at_put_("size",(30));
-$13=_st($12)._placeholder_("add new todo here");
-$13;
-$14=_st(html)._input();
-_st($14)._class_("btn-primary");
-_st($14)._type_("submit");
-$15=_st($14)._value_("add");
-return $15;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,4)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"renderOn:",{html:html},smalltalk.TemporaryWidget)})},
-args: ["html"],
-source: "renderOn: html\x0a        html span trap:#((remaining)).\x0a        html with: ' of '.\x0a        html span trap: #((todos) (size)).\x0a        html with: ' remaining [ '.\x0a        html a\x0a\x09\x09\x09href:'';\x0a\x09\x09\x09trap: #() processors: #((signal archive) whenClicked);\x0a\x09\x09\x09with: 'archive'.\x0a        html with: ' ]'.\x0a        html ul with: [ html trapIter: #((todos)) tag: #li do: [ :each |\x0a            html root empty.\x0a            html input type: 'checkbox'; trap: #('done') processors: #(inputChecked).\x0a            html span trap: #('done') read: [ :model | html root class: 'done-', model ]; trap: #('text').\x0a        ]].\x0a        html form trap: #() processors: #((signal addTodo) whenSubmitted); with: [\x0a            html input type: 'text'; trap: #((todoText)) processors: #(inputValue); at: 'size' put: 30; placeholder: 'add new todo here'.\x0a            html input class: 'btn-primary'; type: 'submit'; value: 'add'.\x0a        ]",
-messageSends: ["trap:", "span", "with:", "href:", "a", "trap:processors:", "ul", "trapIter:tag:do:", "empty", "root", "type:", "input", "trap:read:", "class:", ",", "form", "at:put:", "placeholder:", "value:"],
-referencedClasses: []
-}),
-smalltalk.TemporaryWidget);
-
-
-
-smalltalk.addClass('TemporaryWidget2', smalltalk.Widget, [], 'Trapped-Demo');
-smalltalk.addMethod(
-smalltalk.method({
-selector: "renderOn:",
-category: 'rendering',
-fn: function (html){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(_st(html)._root())._contents_("Loading ...");
-return self}, function($ctx1) {$ctx1.fill(self,"renderOn:",{html:html},smalltalk.TemporaryWidget2)})},
+}, function($ctx3) {$ctx3.fillBlock({model:model},$ctx2,2)})}));
+$5=_st($4)._trap_(["text"]);
+return $5;
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"renderOn:",{html:html},smalltalk.TodoItemsWidget)})},
 args: ["html"],
-source: "renderOn: html\x0a\x09html root contents: 'Loading ...'",
-messageSends: ["contents:", "root"],
+source: "renderOn: html\x0a\x09html trapIter: #() tag: #li do: [ :each |\x0a\x09\x09html root empty.\x0a\x09\x09html input type: 'checkbox'; trap: #('done') processors: #(inputChecked).\x0a\x09\x09html span trap: #('done') read: [ :model | html root class: 'done-', model ]; trap: #('text').\x0a\x09]",
+messageSends: ["trapIter:tag:do:", "empty", "root", "type:", "input", "trap:processors:", "trap:read:", "span", "class:", ",", "trap:"],
 referencedClasses: []
 }),
-smalltalk.TemporaryWidget2);
+smalltalk.TodoItemsWidget);
 
 
 });

+ 66 - 10
js/Trapped-Frontend.js

@@ -597,20 +597,39 @@ referencedClasses: ["TrappedProcessorContents"]
 }),
 smalltalk.TrappedProcessor.klass);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "guardContents:",
+category: 'factory',
+fn: function (anArray){
+var self=this;
+function $TrappedProcessorGuardContents(){return smalltalk.TrappedProcessorGuardContents||(typeof TrappedProcessorGuardContents=="undefined"?nil:TrappedProcessorGuardContents)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st($TrappedProcessorGuardContents())._new_(anArray);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"guardContents:",{anArray:anArray},smalltalk.TrappedProcessor.klass)})},
+args: ["anArray"],
+source: "guardContents: anArray\x0a\x09^TrappedProcessorGuardContents new: anArray",
+messageSends: ["new:"],
+referencedClasses: ["TrappedProcessorGuardContents"]
+}),
+smalltalk.TrappedProcessor.klass);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "guardProc:",
 category: 'factory',
-fn: function (aString){
+fn: function (anArray){
 var self=this;
 function $TrappedProcessorGuardProc(){return smalltalk.TrappedProcessorGuardProc||(typeof TrappedProcessorGuardProc=="undefined"?nil:TrappedProcessorGuardProc)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st($TrappedProcessorGuardProc())._new_(aString);
+$1=_st($TrappedProcessorGuardProc())._new_(anArray);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"guardProc:",{aString:aString},smalltalk.TrappedProcessor.klass)})},
-args: ["aString"],
-source: "guardProc: aString\x0a\x09^TrappedProcessorGuardProc new: aString",
+}, function($ctx1) {$ctx1.fill(self,"guardProc:",{anArray:anArray},smalltalk.TrappedProcessor.klass)})},
+args: ["anArray"],
+source: "guardProc: anArray\x0a\x09^TrappedProcessorGuardProc new: anArray",
 messageSends: ["new:"],
 referencedClasses: ["TrappedProcessorGuardProc"]
 }),
@@ -1029,6 +1048,44 @@ referencedClasses: []
 smalltalk.TrappedProcessorGuardBase.klass);
 
 
+smalltalk.addClass('TrappedProcessorGuardContents', smalltalk.TrappedProcessorGuardBase, [], 'Trapped-Frontend');
+smalltalk.TrappedProcessorGuardContents.comment="I am used to guard contents of the brush I am installed on.\x0a\x0aI save the brush contents, then I observe guard expression in the model,\x0aand when it changes to nil or false, I delete the brush contents;\x0aon the other hand, when it changes to non-nil and non-false,\x0aI restore it from remembered state and interpret all contained\x0adata-trap attributes inside.";
+smalltalk.addMethod(
+smalltalk.method({
+selector: "toView:",
+category: 'data transformation',
+fn: function (aDataCarrier){
+var self=this;
+var frozen,contents;
+function $Trapped(){return smalltalk.Trapped||(typeof Trapped=="undefined"?nil:Trapped)}
+return smalltalk.withContext(function($ctx1) { 
+var $3,$2,$1,$5,$4;
+frozen=_st(aDataCarrier)._copy();
+$3=_st(frozen)._target();
+$ctx1.sendIdx["target"]=1;
+$2=_st($3)._asJQuery();
+$ctx1.sendIdx["asJQuery"]=1;
+$1=_st($2)._contents();
+contents=_st($1)._detach();
+_st(_st(frozen)._target())._trapGuard_contents_(self["@guardPath"],(function(html){
+return smalltalk.withContext(function($ctx2) {
+$5=_st(html)._root();
+$ctx2.sendIdx["root"]=1;
+$4=_st($5)._asJQuery();
+$ctx2.sendIdx["asJQuery"]=2;
+_st($4)._append_(contents);
+return _st(_st($Trapped())._current())._injectToJQuery_(_st(_st(html)._root())._asJQuery());
+}, function($ctx2) {$ctx2.fillBlock({html:html},$ctx1,1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"toView:",{aDataCarrier:aDataCarrier,frozen:frozen,contents:contents},smalltalk.TrappedProcessorGuardContents)})},
+args: ["aDataCarrier"],
+source: "toView: aDataCarrier\x0a\x09| frozen contents |\x0a\x09frozen := aDataCarrier copy.\x0a\x09contents := frozen target asJQuery contents detach.\x0a\x09frozen target trapGuard: guardPath contents: [ :html |\x0a\x09\x09html root asJQuery append: contents.\x0a\x09\x09Trapped current injectToJQuery: html root asJQuery ]",
+messageSends: ["copy", "detach", "contents", "asJQuery", "target", "trapGuard:contents:", "append:", "root", "injectToJQuery:", "current"],
+referencedClasses: ["Trapped"]
+}),
+smalltalk.TrappedProcessorGuardContents);
+
+
+
 smalltalk.addClass('TrappedProcessorGuardProc', smalltalk.TrappedProcessorGuardBase, [], 'Trapped-Frontend');
 smalltalk.TrappedProcessorGuardProc.comment="I am used to guard contents filling process of the brush I am installed on.\x0a\x0aI observe guard expression in the model,\x0aand when it changes to nil or false, I delete the brush contents;\x0aon the other hand, when it changes to non-nil and non-false,\x0aI run the rest on the chain, which should be one-time\x0athat sets up the contents,";
 smalltalk.addMethod(
@@ -1399,21 +1456,20 @@ var parsed;
 parsed=_st($Trapped())._parse_(_st(jq)._attr_("data-trap"));
 parsed;
 _st(jq)._removeAttr_("data-trap");
-return _st(parsed)._do_((function(rule){
+_st(parsed)._do_((function(rule){
 return smalltalk.withContext(function($ctx3) {
 return _st(_st(_st($HTMLCanvas())._onJQuery_(jq))._root())._trap_processors_(_st(rule)._first(),_st(rule)._at_ifAbsent_((2),(function(){
 return smalltalk.withContext(function($ctx4) {
 return [];
 }, function($ctx4) {$ctx4.fillBlock({},$ctx3,4)})})));
 }, function($ctx3) {$ctx3.fillBlock({rule:rule},$ctx2,3)})}));
-} else {
-return self._injectToJQuery_(_st(jq)._children());
 };
+return self._injectToJQuery_(_st(jq)._children());
 }, function($ctx2) {$ctx2.fillBlock({index:index,elem:elem,jq:jq},$ctx1,1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"injectToJQuery:",{aJQuery:aJQuery},smalltalk.Trapped)})},
 args: ["aJQuery"],
-source: "injectToJQuery: aJQuery\x0a\x09aJQuery each: [ :index :elem |\x0a\x09\x09| jq |\x0a\x09\x09jq := elem asJQuery.\x0a\x09\x09(jq is: '[data-trap]')\x0a\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09| parsed |\x0a\x09\x09\x09\x09parsed := Trapped parse: (jq attr: 'data-trap').\x0a\x09\x09\x09\x09jq removeAttr: 'data-trap'.\x0a\x09\x09\x09\x09parsed do: [ :rule |\x0a\x09\x09\x09\x09\x09(HTMLCanvas onJQuery: jq) root trap: rule first processors: (rule at: 2 ifAbsent: [#()]) ] ]\x0a\x09\x09\x09ifFalse: [ self injectToJQuery: jq children ] ]",
-messageSends: ["each:", "asJQuery", "ifTrue:ifFalse:", "is:", "parse:", "attr:", "removeAttr:", "do:", "trap:processors:", "root", "onJQuery:", "first", "at:ifAbsent:", "injectToJQuery:", "children"],
+source: "injectToJQuery: aJQuery\x0a\x09aJQuery each: [ :index :elem |\x0a\x09\x09| jq |\x0a\x09\x09jq := elem asJQuery.\x0a\x09\x09(jq is: '[data-trap]')\x0a\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09| parsed |\x0a\x09\x09\x09\x09parsed := Trapped parse: (jq attr: 'data-trap').\x0a\x09\x09\x09\x09jq removeAttr: 'data-trap'.\x0a\x09\x09\x09\x09parsed do: [ :rule |\x0a\x09\x09\x09\x09\x09(HTMLCanvas onJQuery: jq) root trap: rule first processors: (rule at: 2 ifAbsent: [#()]) ] ].\x0a\x09\x09\x09self injectToJQuery: jq children ]",
+messageSends: ["each:", "asJQuery", "ifTrue:", "is:", "parse:", "attr:", "removeAttr:", "do:", "trap:processors:", "root", "onJQuery:", "first", "at:ifAbsent:", "injectToJQuery:", "children"],
 referencedClasses: ["Trapped", "HTMLCanvas"]
 }),
 smalltalk.Trapped);

+ 13 - 2
meta/demo.html

@@ -1,6 +1,9 @@
 <html data-trap="App: path">
 <head>
     <title data-trap="#title"></title>
+    <style>
+        [data-trap] { display: none }
+    </style>
     <script src="../bower_components/amber/support/amber.js"></script>
     <script type='text/javascript' src='../bower_components/amber/support/requirejs/require.min.js'></script>
     <link rel="stylesheet" href="demo.css" />
@@ -30,7 +33,15 @@
     );
 </script>
 <h2 data-trap="#title"></h2>
-<div data-trap=": (guardProc (#todos #notNil)) (widget TemporaryWidget)"></div>
-<p data-trap=": (guardProc (#todos #isNil)) (widget TemporaryWidget2)"></p>
+<div data-trap=": (guardContents (#todos #notNil))">
+    <span data-trap="#remaining" ></span> of <span data-trap="#todos #size"></span> remaning
+    [ <a href="" data-trap=": (signal archive) whenClicked">archive</a> ]
+    <ul data-trap="#todos: (widget TodoItemsWidget)"></ul>
+    <form data-trap=": (signal addTodo) whenSubmitted">
+        <input type="text" data-trap="#todoText: inputValue" size="30" placeholder="add new todo here" />
+        <input type="submit" class="btn-primary" value="add" />
+    </form>
+</div>
+<p data-trap=": (guardContents (#todos #isNil))">Loading ...</p>
 </body>
 </html>

+ 8 - 31
st/Trapped-Demo.st

@@ -121,10 +121,10 @@ archive
     self todos: self todosNotDone
 ! !
 
-Widget subclass: #TemporaryWidget
+Widget subclass: #TodoItemsWidget
 	instanceVariableNames: ''
 	package: 'Trapped-Demo'!
-!TemporaryWidget commentStamp!
+!TodoItemsWidget commentStamp!
 <!!-- Code from AngularJS Todo example, http://angularjs.org/#todo-html -->
   <body>
     <h2>Todo</h2>
@@ -145,36 +145,13 @@ Widget subclass: #TemporaryWidget
     </div>
   </body>!
 
-!TemporaryWidget methodsFor: 'rendering'!
+!TodoItemsWidget methodsFor: 'rendering'!
 
 renderOn: html
-        html span trap:#((remaining)).
-        html with: ' of '.
-        html span trap: #((todos) (size)).
-        html with: ' remaining [ '.
-        html a
-			href:'';
-			trap: #() processors: #((signal archive) whenClicked);
-			with: 'archive'.
-        html with: ' ]'.
-        html ul with: [ html trapIter: #((todos)) tag: #li do: [ :each |
-            html root empty.
-            html input type: 'checkbox'; trap: #('done') processors: #(inputChecked).
-            html span trap: #('done') read: [ :model | html root class: 'done-', model ]; trap: #('text').
-        ]].
-        html form trap: #() processors: #((signal addTodo) whenSubmitted); with: [
-            html input type: 'text'; trap: #((todoText)) processors: #(inputValue); at: 'size' put: 30; placeholder: 'add new todo here'.
-            html input class: 'btn-primary'; type: 'submit'; value: 'add'.
-        ]
-! !
-
-Widget subclass: #TemporaryWidget2
-	instanceVariableNames: ''
-	package: 'Trapped-Demo'!
-
-!TemporaryWidget2 methodsFor: 'rendering'!
-
-renderOn: html
-	html root contents: 'Loading ...'
+	html trapIter: #() tag: #li do: [ :each |
+		html root empty.
+		html input type: 'checkbox'; trap: #('done') processors: #(inputChecked).
+		html span trap: #('done') read: [ :model | html root class: 'done-', model ]; trap: #('text').
+	]
 ! !
 

+ 31 - 4
st/Trapped-Frontend.st

@@ -202,8 +202,12 @@ contents
 	^TrappedProcessorContents new
 !
 
-guardProc: aString
-	^TrappedProcessorGuardProc new: aString
+guardContents: anArray
+	^TrappedProcessorGuardContents new: anArray
+!
+
+guardProc: anArray
+	^TrappedProcessorGuardProc new: anArray
 !
 
 inputChecked
@@ -377,6 +381,29 @@ new: anArray
 		yourself
 ! !
 
+TrappedProcessorGuardBase subclass: #TrappedProcessorGuardContents
+	instanceVariableNames: ''
+	package: 'Trapped-Frontend'!
+!TrappedProcessorGuardContents commentStamp!
+I am used to guard contents of the brush I am installed on.
+
+I save the brush contents, then I observe guard expression in the model,
+and when it changes to nil or false, I delete the brush contents;
+on the other hand, when it changes to non-nil and non-false,
+I restore it from remembered state and interpret all contained
+data-trap attributes inside.!
+
+!TrappedProcessorGuardContents methodsFor: 'data transformation'!
+
+toView: aDataCarrier
+	| frozen contents |
+	frozen := aDataCarrier copy.
+	contents := frozen target asJQuery contents detach.
+	frozen target trapGuard: guardPath contents: [ :html |
+		html root asJQuery append: contents.
+		Trapped current injectToJQuery: html root asJQuery ]
+! !
+
 TrappedProcessorGuardBase subclass: #TrappedProcessorGuardProc
 	instanceVariableNames: ''
 	package: 'Trapped-Frontend'!
@@ -558,8 +585,8 @@ injectToJQuery: aJQuery
 				parsed := Trapped parse: (jq attr: 'data-trap').
 				jq removeAttr: 'data-trap'.
 				parsed do: [ :rule |
-					(HTMLCanvas onJQuery: jq) root trap: rule first processors: (rule at: 2 ifAbsent: [#()]) ] ]
-			ifFalse: [ self injectToJQuery: jq children ] ]
+					(HTMLCanvas onJQuery: jq) root trap: rule first processors: (rule at: 2 ifAbsent: [#()]) ] ].
+			self injectToJQuery: jq children ]
 !
 
 start: args