Web-Snippets.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. define(["amber/boot", "require", "amber/core/Kernel-Collections", "amber/core/Kernel-Objects", "amber/web/Web"], function($boot,requirejs){"use strict";
  2. var $core=$boot.api,nil=$boot.nilAsValue,$nil=$boot.nilAsReceiver,$recv=$boot.asReceiver,$globals=$boot.globals;
  3. var $pkg = $core.addPackage("Web-Snippets");
  4. $pkg.innerEval = function (expr) { return eval(expr); };
  5. $pkg.imports = ["amber/core/Platform-DOM", "amber/jquery/Wrappers-JQuery"];
  6. //>>excludeStart("imports", pragmas.excludeImports);
  7. $pkg.isReady = new Promise(function (resolve, reject) { requirejs(["amber/core/Platform-DOM", "amber/jquery/Wrappers-JQuery"], function () {resolve();}, reject); });
  8. //>>excludeEnd("imports");
  9. $pkg.transport = {"type":"amd","amdNamespace":"amber/web"};
  10. $core.addClass("HTMLSnippet", $globals.Object, ["snippets"], "Web-Snippets");
  11. //>>excludeStart("ide", pragmas.excludeIdeData);
  12. $globals.HTMLSnippet.comment="My sole instance is the registry of html snippets.\x0a`HTMLSnippet current` is the public singleton instance.\x0a\x0aOn startup, it scans the document for any html elements\x0awith `'data-snippet=\x22foo\x22'` attribute and takes them off the document,\x0aremembering them in the store under the specified name.\x0aIt also install method #foo into HTMLCanvas dynamically.\x0a\x0aEvery html snippet should mark a 'caret', a place where contents\x0acan be inserted, by 'data-snippet=\x22*\x22' (a special name for caret).\x0aFor example:\x0a\x0a`<li data-snippet='menuelement' class='...'><a data-snippet='*'></a></li>`\x0a\x0adefines a list element with a link inside; the link itself is marked as a caret.\x0a\x0aYou can later issue\x0a\x0a`html menuelement href: '/foo'; with: 'A foo'`\x0a\x0ato insert the whole snippet and directly manipulate the caret, so it renders:\x0a\x0a`<li class='...'><a href='/foo'>A foo</a></li>`\x0a\x0aFor a self-careting tags (not very useful, but you do not need to fill class etc.\x0ayou can use\x0a\x0a`<div class='lots of classes' attr1='one' attr2='two' data-snippet='*bar'></div>`\x0a\x0aand in code later do:\x0a\x0a`html bar with: [ xxx ]`\x0a\x0ato render\x0a\x0a`<div class='lots of classes' attr1='one' attr2='two'>...added by xxx...</div>`";
  13. //>>excludeEnd("ide");
  14. $core.addMethod(
  15. $core.method({
  16. selector: "initializeFromJQuery:",
  17. protocol: "initialization",
  18. fn: function (aJQuery){
  19. var self=this,$self=this;
  20. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  21. return $core.withContext(function($ctx1) {
  22. //>>excludeEnd("ctx");
  23. $recv($self._snippetsFromJQuery_(aJQuery))._do_((function(each){
  24. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  25. return $core.withContext(function($ctx2) {
  26. //>>excludeEnd("ctx");
  27. return $self._installSnippetFromJQuery_($recv(each)._asJQuery());
  28. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  29. }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
  30. //>>excludeEnd("ctx");
  31. }));
  32. return self;
  33. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  34. }, function($ctx1) {$ctx1.fill(self,"initializeFromJQuery:",{aJQuery:aJQuery},$globals.HTMLSnippet)});
  35. //>>excludeEnd("ctx");
  36. },
  37. //>>excludeStart("ide", pragmas.excludeIdeData);
  38. args: ["aJQuery"],
  39. source: "initializeFromJQuery: aJQuery\x0a\x09\x22Finds and takes out all snippets out of aJQuery.\x0a\x09Installs it into self.\x22\x0a\x09\x0a\x09(self snippetsFromJQuery: aJQuery) do: [ :each |\x0a\x09\x09self installSnippetFromJQuery: each asJQuery ]",
  40. referencedClasses: [],
  41. //>>excludeEnd("ide");
  42. messageSends: ["do:", "snippetsFromJQuery:", "installSnippetFromJQuery:", "asJQuery"]
  43. }),
  44. $globals.HTMLSnippet);
  45. $core.addMethod(
  46. $core.method({
  47. selector: "installSnippetFromJQuery:",
  48. protocol: "snippet installation",
  49. fn: function (element){
  50. var self=this,$self=this;
  51. var name;
  52. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  53. return $core.withContext(function($ctx1) {
  54. //>>excludeEnd("ctx");
  55. var $1,$2;
  56. name=$recv(element)._attr_("data-snippet");
  57. $1=$recv(name).__eq("*");
  58. if(!$core.assert($1)){
  59. $2=$recv("^\x5c*"._asRegexp())._test_(name);
  60. if($core.assert($2)){
  61. name=$recv(name)._allButFirst();
  62. $recv(element)._attr_put_("data-snippet","*");
  63. } else {
  64. $recv(element)._removeAttr_("data-snippet");
  65. }
  66. $self._snippetAt_install_(name,$recv($recv(element)._detach())._get_((0)));
  67. }
  68. return self;
  69. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  70. }, function($ctx1) {$ctx1.fill(self,"installSnippetFromJQuery:",{element:element,name:name},$globals.HTMLSnippet)});
  71. //>>excludeEnd("ctx");
  72. },
  73. //>>excludeStart("ide", pragmas.excludeIdeData);
  74. args: ["element"],
  75. source: "installSnippetFromJQuery: element\x0a\x09| name |\x0a\x09name := element attr: 'data-snippet'.\x0a\x09name = '*' ifFalse: [\x0a\x09\x09('^\x5c*' asRegexp test: name)\x0a\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09name := name allButFirst.\x0a\x09\x09\x09\x09element attr: 'data-snippet' put: '*' ]\x0a\x09\x09\x09ifFalse: [\x0a\x09\x09\x09\x09element removeAttr: 'data-snippet' ].\x0a\x09\x09self snippetAt: name install: (element detach get: 0) ]",
  76. referencedClasses: [],
  77. //>>excludeEnd("ide");
  78. messageSends: ["attr:", "ifFalse:", "=", "ifTrue:ifFalse:", "test:", "asRegexp", "allButFirst", "attr:put:", "removeAttr:", "snippetAt:install:", "get:", "detach"]
  79. }),
  80. $globals.HTMLSnippet);
  81. $core.addMethod(
  82. $core.method({
  83. selector: "snippetAt:",
  84. protocol: "accessing",
  85. fn: function (aString){
  86. var self=this,$self=this;
  87. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  88. return $core.withContext(function($ctx1) {
  89. //>>excludeEnd("ctx");
  90. return $recv($self._snippets())._at_(aString);
  91. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  92. }, function($ctx1) {$ctx1.fill(self,"snippetAt:",{aString:aString},$globals.HTMLSnippet)});
  93. //>>excludeEnd("ctx");
  94. },
  95. //>>excludeStart("ide", pragmas.excludeIdeData);
  96. args: ["aString"],
  97. source: "snippetAt: aString\x0a\x09^ self snippets at: aString",
  98. referencedClasses: [],
  99. //>>excludeEnd("ide");
  100. messageSends: ["at:", "snippets"]
  101. }),
  102. $globals.HTMLSnippet);
  103. $core.addMethod(
  104. $core.method({
  105. selector: "snippetAt:compile:",
  106. protocol: "method generation",
  107. fn: function (aString,anElement){
  108. var self=this,$self=this;
  109. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  110. return $core.withContext(function($ctx1) {
  111. //>>excludeEnd("ctx");
  112. $recv($recv($globals.ClassBuilder)._new())._installMethod_forClass_protocol_($recv($recv((function(htmlReceiver){
  113. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  114. return $core.withContext(function($ctx2) {
  115. //>>excludeEnd("ctx");
  116. return $recv(htmlReceiver)._snippet_(anElement);
  117. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  118. }, function($ctx2) {$ctx2.fillBlock({htmlReceiver:htmlReceiver},$ctx1,1)});
  119. //>>excludeEnd("ctx");
  120. }))._currySelf())._asCompiledMethod_(aString),$globals.HTMLCanvas,"**snippets");
  121. return self;
  122. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  123. }, function($ctx1) {$ctx1.fill(self,"snippetAt:compile:",{aString:aString,anElement:anElement},$globals.HTMLSnippet)});
  124. //>>excludeEnd("ctx");
  125. },
  126. //>>excludeStart("ide", pragmas.excludeIdeData);
  127. args: ["aString", "anElement"],
  128. source: "snippetAt: aString compile: anElement\x0a\x09\x22Method generation for the snippet.\x0a\x09The selector is aString, the method block uses anElement\x22\x0a\x09\x0a\x09ClassBuilder new\x0a\x09\x09installMethod: ([ :htmlReceiver | htmlReceiver snippet: anElement ]\x0a\x09\x09\x09currySelf asCompiledMethod: aString)\x0a\x09\x09forClass: HTMLCanvas\x0a\x09\x09protocol: '**snippets'",
  129. referencedClasses: ["ClassBuilder", "HTMLCanvas"],
  130. //>>excludeEnd("ide");
  131. messageSends: ["installMethod:forClass:protocol:", "new", "asCompiledMethod:", "currySelf", "snippet:"]
  132. }),
  133. $globals.HTMLSnippet);
  134. $core.addMethod(
  135. $core.method({
  136. selector: "snippetAt:install:",
  137. protocol: "snippet installation",
  138. fn: function (aString,anElement){
  139. var self=this,$self=this;
  140. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  141. return $core.withContext(function($ctx1) {
  142. //>>excludeEnd("ctx");
  143. $recv($self._snippets())._at_put_(aString,anElement);
  144. $self._snippetAt_compile_(aString,anElement);
  145. return self;
  146. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  147. }, function($ctx1) {$ctx1.fill(self,"snippetAt:install:",{aString:aString,anElement:anElement},$globals.HTMLSnippet)});
  148. //>>excludeEnd("ctx");
  149. },
  150. //>>excludeStart("ide", pragmas.excludeIdeData);
  151. args: ["aString", "anElement"],
  152. source: "snippetAt: aString install: anElement\x0a\x09self snippets at: aString put: anElement.\x0a\x09self snippetAt: aString compile: anElement",
  153. referencedClasses: [],
  154. //>>excludeEnd("ide");
  155. messageSends: ["at:put:", "snippets", "snippetAt:compile:"]
  156. }),
  157. $globals.HTMLSnippet);
  158. $core.addMethod(
  159. $core.method({
  160. selector: "snippets",
  161. protocol: "accessing",
  162. fn: function (){
  163. var self=this,$self=this;
  164. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  165. return $core.withContext(function($ctx1) {
  166. //>>excludeEnd("ctx");
  167. var $1,$receiver;
  168. $1=$self["@snippets"];
  169. if(($receiver = $1) == null || $receiver.a$nil){
  170. $self["@snippets"]=$globals.HashedCollection._newFromPairs_([]);
  171. return $self["@snippets"];
  172. } else {
  173. return $1;
  174. }
  175. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  176. }, function($ctx1) {$ctx1.fill(self,"snippets",{},$globals.HTMLSnippet)});
  177. //>>excludeEnd("ctx");
  178. },
  179. //>>excludeStart("ide", pragmas.excludeIdeData);
  180. args: [],
  181. source: "snippets\x0a\x09^ snippets ifNil: [ snippets := #{} ]",
  182. referencedClasses: [],
  183. //>>excludeEnd("ide");
  184. messageSends: ["ifNil:"]
  185. }),
  186. $globals.HTMLSnippet);
  187. $core.addMethod(
  188. $core.method({
  189. selector: "snippetsFromJQuery:",
  190. protocol: "private",
  191. fn: function (aJQuery){
  192. var self=this,$self=this;
  193. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  194. return $core.withContext(function($ctx1) {
  195. //>>excludeEnd("ctx");
  196. return $recv($recv(aJQuery)._find_("[data-snippet]"))._toArray();
  197. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  198. }, function($ctx1) {$ctx1.fill(self,"snippetsFromJQuery:",{aJQuery:aJQuery},$globals.HTMLSnippet)});
  199. //>>excludeEnd("ctx");
  200. },
  201. //>>excludeStart("ide", pragmas.excludeIdeData);
  202. args: ["aJQuery"],
  203. source: "snippetsFromJQuery: aJQuery\x0a\x09^ (aJQuery find: '[data-snippet]') toArray",
  204. referencedClasses: [],
  205. //>>excludeEnd("ide");
  206. messageSends: ["toArray", "find:"]
  207. }),
  208. $globals.HTMLSnippet);
  209. $globals.HTMLSnippet.a$cls.iVarNames = ["current"];
  210. $core.addMethod(
  211. $core.method({
  212. selector: "current",
  213. protocol: "instance creation",
  214. fn: function (){
  215. var self=this,$self=this;
  216. return $self["@current"];
  217. },
  218. //>>excludeStart("ide", pragmas.excludeIdeData);
  219. args: [],
  220. source: "current\x0a\x09^ current",
  221. referencedClasses: [],
  222. //>>excludeEnd("ide");
  223. messageSends: []
  224. }),
  225. $globals.HTMLSnippet.a$cls);
  226. $core.addMethod(
  227. $core.method({
  228. selector: "ensureCurrent",
  229. protocol: "initialization",
  230. fn: function (){
  231. var self=this,$self=this;
  232. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  233. return $core.withContext(function($ctx1) {
  234. //>>excludeEnd("ctx");
  235. var $1,$2,$receiver;
  236. $1=$self["@current"];
  237. if(($receiver = $1) == null || $receiver.a$nil){
  238. $2=(
  239. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  240. $ctx1.supercall = true,
  241. //>>excludeEnd("ctx");
  242. ($globals.HTMLSnippet.a$cls.superclass||$boot.nilAsClass).fn.prototype._new.apply($self, []));
  243. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  244. $ctx1.supercall = false;
  245. //>>excludeEnd("ctx");;
  246. $recv($2)._initializeFromJQuery_($recv(document)._asJQuery());
  247. $self["@current"]=$recv($2)._yourself();
  248. $self["@current"];
  249. } else {
  250. $1;
  251. }
  252. return self;
  253. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  254. }, function($ctx1) {$ctx1.fill(self,"ensureCurrent",{},$globals.HTMLSnippet.a$cls)});
  255. //>>excludeEnd("ctx");
  256. },
  257. //>>excludeStart("ide", pragmas.excludeIdeData);
  258. args: [],
  259. source: "ensureCurrent\x0a\x09current ifNil: [\x0a\x09\x09current := super new\x0a\x09\x09\x09initializeFromJQuery: document asJQuery;\x0a\x09\x09\x09yourself ]",
  260. referencedClasses: [],
  261. //>>excludeEnd("ide");
  262. messageSends: ["ifNil:", "initializeFromJQuery:", "new", "asJQuery", "yourself"]
  263. }),
  264. $globals.HTMLSnippet.a$cls);
  265. $core.addMethod(
  266. $core.method({
  267. selector: "initialize",
  268. protocol: "initialization",
  269. fn: function (){
  270. var self=this,$self=this;
  271. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  272. return $core.withContext(function($ctx1) {
  273. //>>excludeEnd("ctx");
  274. var $1;
  275. (
  276. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  277. $ctx1.supercall = true,
  278. //>>excludeEnd("ctx");
  279. ($globals.HTMLSnippet.a$cls.superclass||$boot.nilAsClass).fn.prototype._initialize.apply($self, []));
  280. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  281. $ctx1.supercall = false;
  282. //>>excludeEnd("ctx");;
  283. $1=$recv($globals.PlatformDom)._isFeasible();
  284. if($core.assert($1)){
  285. $self._ensureCurrent();
  286. }
  287. return self;
  288. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  289. }, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.HTMLSnippet.a$cls)});
  290. //>>excludeEnd("ctx");
  291. },
  292. //>>excludeStart("ide", pragmas.excludeIdeData);
  293. args: [],
  294. source: "initialize\x0a\x09super initialize.\x0a\x09PlatformDom isFeasible ifTrue: [\x0a\x09\x09self ensureCurrent ]",
  295. referencedClasses: ["PlatformDom"],
  296. //>>excludeEnd("ide");
  297. messageSends: ["initialize", "ifTrue:", "isFeasible", "ensureCurrent"]
  298. }),
  299. $globals.HTMLSnippet.a$cls);
  300. $core.addMethod(
  301. $core.method({
  302. selector: "new",
  303. protocol: "instance creation",
  304. fn: function (){
  305. var self=this,$self=this;
  306. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  307. return $core.withContext(function($ctx1) {
  308. //>>excludeEnd("ctx");
  309. $self._shouldNotImplement();
  310. return self;
  311. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  312. }, function($ctx1) {$ctx1.fill(self,"new",{},$globals.HTMLSnippet.a$cls)});
  313. //>>excludeEnd("ctx");
  314. },
  315. //>>excludeStart("ide", pragmas.excludeIdeData);
  316. args: [],
  317. source: "new\x0a\x09self shouldNotImplement",
  318. referencedClasses: [],
  319. //>>excludeEnd("ide");
  320. messageSends: ["shouldNotImplement"]
  321. }),
  322. $globals.HTMLSnippet.a$cls);
  323. $core.addMethod(
  324. $core.method({
  325. selector: "snippet:",
  326. protocol: "*Web-Snippets",
  327. fn: function (anElement){
  328. var self=this,$self=this;
  329. var clone,caret;
  330. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  331. return $core.withContext(function($ctx1) {
  332. //>>excludeEnd("ctx");
  333. var $1;
  334. clone=$recv($recv(anElement)._asJQuery())._clone();
  335. $1=$recv($globals.TagBrush)._fromJQuery_canvas_(clone,self);
  336. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  337. $ctx1.sendIdx["fromJQuery:canvas:"]=1;
  338. //>>excludeEnd("ctx");
  339. $self._with_($1);
  340. caret=$recv(clone)._find_("[data-snippet=\x22*\x22]");
  341. $recv($recv(caret)._toArray())._ifEmpty_((function(){
  342. caret=clone;
  343. return caret;
  344. }));
  345. return $recv($globals.TagBrush)._fromJQuery_canvas_($recv(caret)._removeAttr_("data-snippet"),self);
  346. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  347. }, function($ctx1) {$ctx1.fill(self,"snippet:",{anElement:anElement,clone:clone,caret:caret},$globals.HTMLCanvas)});
  348. //>>excludeEnd("ctx");
  349. },
  350. //>>excludeStart("ide", pragmas.excludeIdeData);
  351. args: ["anElement"],
  352. source: "snippet: anElement\x0a\x09\x22Adds clone of anElement, finds [data-snippet=\x22\x22*\x22\x22] subelement\x0a\x09and returns TagBrush as if that subelement was just added.\x0a\x09\x0a\x09Rarely needed to use directly, use `html foo` dynamically installed method\x0a\x09for a snippet named foo.\x22\x0a\x09\x0a\x09| clone caret |\x0a\x09\x0a\x09clone := anElement asJQuery clone.\x0a\x09self with: (TagBrush fromJQuery: clone canvas: self).\x0a\x09caret := clone find: '[data-snippet=\x22*\x22]'.\x0a\x09caret toArray ifEmpty: [ caret := clone ].\x0a\x09^ TagBrush fromJQuery: (caret removeAttr: 'data-snippet') canvas: self",
  353. referencedClasses: ["TagBrush"],
  354. //>>excludeEnd("ide");
  355. messageSends: ["clone", "asJQuery", "with:", "fromJQuery:canvas:", "find:", "ifEmpty:", "toArray", "removeAttr:"]
  356. }),
  357. $globals.HTMLCanvas);
  358. $core.addMethod(
  359. $core.method({
  360. selector: "asSnippet",
  361. protocol: "*Web-Snippets",
  362. fn: function (){
  363. var self=this,$self=this;
  364. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  365. return $core.withContext(function($ctx1) {
  366. //>>excludeEnd("ctx");
  367. return $recv($recv($globals.HTMLSnippet)._current())._snippetAt_($self._asString());
  368. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  369. }, function($ctx1) {$ctx1.fill(self,"asSnippet",{},$globals.String)});
  370. //>>excludeEnd("ctx");
  371. },
  372. //>>excludeStart("ide", pragmas.excludeIdeData);
  373. args: [],
  374. source: "asSnippet\x0a\x09^ HTMLSnippet current snippetAt: self asString",
  375. referencedClasses: ["HTMLSnippet"],
  376. //>>excludeEnd("ide");
  377. messageSends: ["snippetAt:", "current", "asString"]
  378. }),
  379. $globals.String);
  380. });