Web-Snippets.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  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/web/Web-JQuery"];
  6. //>>excludeStart("imports", pragmas.excludeImports);
  7. $pkg.isReady = new Promise(function (resolve, reject) { requirejs(["amber/core/Platform-DOM", "amber/web/Web-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})});
  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. pragmas: [],
  43. messageSends: ["do:", "snippetsFromJQuery:", "installSnippetFromJQuery:", "asJQuery"]
  44. }),
  45. $globals.HTMLSnippet);
  46. $core.addMethod(
  47. $core.method({
  48. selector: "installSnippetFromJQuery:",
  49. protocol: "snippet installation",
  50. fn: function (element){
  51. var self=this,$self=this;
  52. var name;
  53. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  54. return $core.withContext(function($ctx1) {
  55. //>>excludeEnd("ctx");
  56. var $1,$2;
  57. name=$recv(element)._attr_("data-snippet");
  58. $1=$recv(name).__eq("*");
  59. if(!$core.assert($1)){
  60. $2=$recv("^\x5c*"._asRegexp())._test_(name);
  61. if($core.assert($2)){
  62. name=$recv(name)._allButFirst();
  63. $recv(element)._attr_put_("data-snippet","*");
  64. } else {
  65. $recv(element)._removeAttr_("data-snippet");
  66. }
  67. $self._snippetAt_install_(name,$recv($recv(element)._detach())._get_((0)));
  68. }
  69. return self;
  70. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  71. }, function($ctx1) {$ctx1.fill(self,"installSnippetFromJQuery:",{element:element,name:name})});
  72. //>>excludeEnd("ctx");
  73. },
  74. //>>excludeStart("ide", pragmas.excludeIdeData);
  75. args: ["element"],
  76. 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) ]",
  77. referencedClasses: [],
  78. //>>excludeEnd("ide");
  79. pragmas: [],
  80. messageSends: ["attr:", "ifFalse:", "=", "ifTrue:ifFalse:", "test:", "asRegexp", "allButFirst", "attr:put:", "removeAttr:", "snippetAt:install:", "get:", "detach"]
  81. }),
  82. $globals.HTMLSnippet);
  83. $core.addMethod(
  84. $core.method({
  85. selector: "snippetAt:",
  86. protocol: "accessing",
  87. fn: function (aString){
  88. var self=this,$self=this;
  89. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  90. return $core.withContext(function($ctx1) {
  91. //>>excludeEnd("ctx");
  92. return $recv($self._snippets())._at_(aString);
  93. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  94. }, function($ctx1) {$ctx1.fill(self,"snippetAt:",{aString:aString})});
  95. //>>excludeEnd("ctx");
  96. },
  97. //>>excludeStart("ide", pragmas.excludeIdeData);
  98. args: ["aString"],
  99. source: "snippetAt: aString\x0a\x09^ self snippets at: aString",
  100. referencedClasses: [],
  101. //>>excludeEnd("ide");
  102. pragmas: [],
  103. messageSends: ["at:", "snippets"]
  104. }),
  105. $globals.HTMLSnippet);
  106. $core.addMethod(
  107. $core.method({
  108. selector: "snippetAt:compile:",
  109. protocol: "method generation",
  110. fn: function (aString,anElement){
  111. var self=this,$self=this;
  112. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  113. return $core.withContext(function($ctx1) {
  114. //>>excludeEnd("ctx");
  115. var $2,$1;
  116. $2=$recv($recv((function(htmlReceiver){
  117. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  118. return $core.withContext(function($ctx2) {
  119. //>>excludeEnd("ctx");
  120. return $recv(htmlReceiver)._snippet_(anElement);
  121. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  122. }, function($ctx2) {$ctx2.fillBlock({htmlReceiver:htmlReceiver},$ctx1,1)});
  123. //>>excludeEnd("ctx");
  124. }))._currySelf())._asCompiledMethod_(aString);
  125. $recv($2)._protocol_("**snippets");
  126. $1=$recv($2)._yourself();
  127. $recv($globals.HTMLCanvas)._addCompiledMethod_($1);
  128. return self;
  129. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  130. }, function($ctx1) {$ctx1.fill(self,"snippetAt:compile:",{aString:aString,anElement:anElement})});
  131. //>>excludeEnd("ctx");
  132. },
  133. //>>excludeStart("ide", pragmas.excludeIdeData);
  134. args: ["aString", "anElement"],
  135. 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\x09HTMLCanvas addCompiledMethod:\x0a\x09\x09(([ :htmlReceiver | htmlReceiver snippet: anElement ]\x0a\x09\x09\x09currySelf asCompiledMethod: aString) protocol: '**snippets'; yourself)",
  136. referencedClasses: ["HTMLCanvas"],
  137. //>>excludeEnd("ide");
  138. pragmas: [],
  139. messageSends: ["addCompiledMethod:", "protocol:", "asCompiledMethod:", "currySelf", "snippet:", "yourself"]
  140. }),
  141. $globals.HTMLSnippet);
  142. $core.addMethod(
  143. $core.method({
  144. selector: "snippetAt:install:",
  145. protocol: "snippet installation",
  146. fn: function (aString,anElement){
  147. var self=this,$self=this;
  148. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  149. return $core.withContext(function($ctx1) {
  150. //>>excludeEnd("ctx");
  151. $recv($self._snippets())._at_put_(aString,anElement);
  152. $self._snippetAt_compile_(aString,anElement);
  153. return self;
  154. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  155. }, function($ctx1) {$ctx1.fill(self,"snippetAt:install:",{aString:aString,anElement:anElement})});
  156. //>>excludeEnd("ctx");
  157. },
  158. //>>excludeStart("ide", pragmas.excludeIdeData);
  159. args: ["aString", "anElement"],
  160. source: "snippetAt: aString install: anElement\x0a\x09self snippets at: aString put: anElement.\x0a\x09self snippetAt: aString compile: anElement",
  161. referencedClasses: [],
  162. //>>excludeEnd("ide");
  163. pragmas: [],
  164. messageSends: ["at:put:", "snippets", "snippetAt:compile:"]
  165. }),
  166. $globals.HTMLSnippet);
  167. $core.addMethod(
  168. $core.method({
  169. selector: "snippets",
  170. protocol: "accessing",
  171. fn: function (){
  172. var self=this,$self=this;
  173. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  174. return $core.withContext(function($ctx1) {
  175. //>>excludeEnd("ctx");
  176. var $1,$receiver;
  177. $1=$self.snippets;
  178. if(($receiver = $1) == null || $receiver.a$nil){
  179. $self.snippets=$globals.HashedCollection._newFromPairs_([]);
  180. return $self.snippets;
  181. } else {
  182. return $1;
  183. }
  184. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  185. }, function($ctx1) {$ctx1.fill(self,"snippets",{})});
  186. //>>excludeEnd("ctx");
  187. },
  188. //>>excludeStart("ide", pragmas.excludeIdeData);
  189. args: [],
  190. source: "snippets\x0a\x09^ snippets ifNil: [ snippets := #{} ]",
  191. referencedClasses: [],
  192. //>>excludeEnd("ide");
  193. pragmas: [],
  194. messageSends: ["ifNil:"]
  195. }),
  196. $globals.HTMLSnippet);
  197. $core.addMethod(
  198. $core.method({
  199. selector: "snippetsFromJQuery:",
  200. protocol: "private",
  201. fn: function (aJQuery){
  202. var self=this,$self=this;
  203. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  204. return $core.withContext(function($ctx1) {
  205. //>>excludeEnd("ctx");
  206. return $recv($recv(aJQuery)._find_("[data-snippet]"))._toArray();
  207. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  208. }, function($ctx1) {$ctx1.fill(self,"snippetsFromJQuery:",{aJQuery:aJQuery})});
  209. //>>excludeEnd("ctx");
  210. },
  211. //>>excludeStart("ide", pragmas.excludeIdeData);
  212. args: ["aJQuery"],
  213. source: "snippetsFromJQuery: aJQuery\x0a\x09^ (aJQuery find: '[data-snippet]') toArray",
  214. referencedClasses: [],
  215. //>>excludeEnd("ide");
  216. pragmas: [],
  217. messageSends: ["toArray", "find:"]
  218. }),
  219. $globals.HTMLSnippet);
  220. $core.setSlots($globals.HTMLSnippet.a$cls, ["current"]);
  221. $core.addMethod(
  222. $core.method({
  223. selector: "current",
  224. protocol: "instance creation",
  225. fn: function (){
  226. var self=this,$self=this;
  227. return $self.current;
  228. },
  229. //>>excludeStart("ide", pragmas.excludeIdeData);
  230. args: [],
  231. source: "current\x0a\x09^ current",
  232. referencedClasses: [],
  233. //>>excludeEnd("ide");
  234. pragmas: [],
  235. messageSends: []
  236. }),
  237. $globals.HTMLSnippet.a$cls);
  238. $core.addMethod(
  239. $core.method({
  240. selector: "ensureCurrent",
  241. protocol: "initialization",
  242. fn: function (){
  243. var self=this,$self=this;
  244. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  245. return $core.withContext(function($ctx1) {
  246. //>>excludeEnd("ctx");
  247. var $1,$2,$receiver;
  248. $1=$self.current;
  249. if(($receiver = $1) == null || $receiver.a$nil){
  250. $2=(
  251. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  252. $ctx1.supercall = true,
  253. //>>excludeEnd("ctx");
  254. ($globals.HTMLSnippet.a$cls.superclass||$boot.nilAsClass).fn.prototype._new.apply($self, []));
  255. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  256. $ctx1.supercall = false;
  257. //>>excludeEnd("ctx");;
  258. $recv($2)._initializeFromJQuery_($recv(document)._asJQuery());
  259. $self.current=$recv($2)._yourself();
  260. $self.current;
  261. } else {
  262. $1;
  263. }
  264. return self;
  265. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  266. }, function($ctx1) {$ctx1.fill(self,"ensureCurrent",{})});
  267. //>>excludeEnd("ctx");
  268. },
  269. //>>excludeStart("ide", pragmas.excludeIdeData);
  270. args: [],
  271. source: "ensureCurrent\x0a\x09current ifNil: [\x0a\x09\x09current := super new\x0a\x09\x09\x09initializeFromJQuery: document asJQuery;\x0a\x09\x09\x09yourself ]",
  272. referencedClasses: [],
  273. //>>excludeEnd("ide");
  274. pragmas: [],
  275. messageSends: ["ifNil:", "initializeFromJQuery:", "new", "asJQuery", "yourself"]
  276. }),
  277. $globals.HTMLSnippet.a$cls);
  278. $core.addMethod(
  279. $core.method({
  280. selector: "initialize",
  281. protocol: "initialization",
  282. fn: function (){
  283. var self=this,$self=this;
  284. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  285. return $core.withContext(function($ctx1) {
  286. //>>excludeEnd("ctx");
  287. var $1;
  288. (
  289. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  290. $ctx1.supercall = true,
  291. //>>excludeEnd("ctx");
  292. ($globals.HTMLSnippet.a$cls.superclass||$boot.nilAsClass).fn.prototype._initialize.apply($self, []));
  293. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  294. $ctx1.supercall = false;
  295. //>>excludeEnd("ctx");;
  296. $1=$recv($globals.PlatformDom)._isFeasible();
  297. if($core.assert($1)){
  298. $self._ensureCurrent();
  299. }
  300. return self;
  301. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  302. }, function($ctx1) {$ctx1.fill(self,"initialize",{})});
  303. //>>excludeEnd("ctx");
  304. },
  305. //>>excludeStart("ide", pragmas.excludeIdeData);
  306. args: [],
  307. source: "initialize\x0a\x09super initialize.\x0a\x09PlatformDom isFeasible ifTrue: [\x0a\x09\x09self ensureCurrent ]",
  308. referencedClasses: ["PlatformDom"],
  309. //>>excludeEnd("ide");
  310. pragmas: [],
  311. messageSends: ["initialize", "ifTrue:", "isFeasible", "ensureCurrent"]
  312. }),
  313. $globals.HTMLSnippet.a$cls);
  314. $core.addMethod(
  315. $core.method({
  316. selector: "new",
  317. protocol: "instance creation",
  318. fn: function (){
  319. var self=this,$self=this;
  320. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  321. return $core.withContext(function($ctx1) {
  322. //>>excludeEnd("ctx");
  323. $self._shouldNotImplement();
  324. return self;
  325. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  326. }, function($ctx1) {$ctx1.fill(self,"new",{})});
  327. //>>excludeEnd("ctx");
  328. },
  329. //>>excludeStart("ide", pragmas.excludeIdeData);
  330. args: [],
  331. source: "new\x0a\x09self shouldNotImplement",
  332. referencedClasses: [],
  333. //>>excludeEnd("ide");
  334. pragmas: [],
  335. messageSends: ["shouldNotImplement"]
  336. }),
  337. $globals.HTMLSnippet.a$cls);
  338. $core.addMethod(
  339. $core.method({
  340. selector: "snippet:",
  341. protocol: "*Web-Snippets",
  342. fn: function (anElement){
  343. var self=this,$self=this;
  344. var clone,caret;
  345. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  346. return $core.withContext(function($ctx1) {
  347. //>>excludeEnd("ctx");
  348. var $1;
  349. clone=$recv($recv(anElement)._asJQuery())._clone();
  350. $1=$recv($globals.TagBrush)._fromJQuery_canvas_(clone,self);
  351. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  352. $ctx1.sendIdx["fromJQuery:canvas:"]=1;
  353. //>>excludeEnd("ctx");
  354. $self._with_($1);
  355. caret=$recv(clone)._find_("[data-snippet=\x22*\x22]");
  356. $recv($recv(caret)._toArray())._ifEmpty_((function(){
  357. caret=clone;
  358. return caret;
  359. }));
  360. return $recv($globals.TagBrush)._fromJQuery_canvas_($recv(caret)._removeAttr_("data-snippet"),self);
  361. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  362. }, function($ctx1) {$ctx1.fill(self,"snippet:",{anElement:anElement,clone:clone,caret:caret})});
  363. //>>excludeEnd("ctx");
  364. },
  365. //>>excludeStart("ide", pragmas.excludeIdeData);
  366. args: ["anElement"],
  367. 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",
  368. referencedClasses: ["TagBrush"],
  369. //>>excludeEnd("ide");
  370. pragmas: [],
  371. messageSends: ["clone", "asJQuery", "with:", "fromJQuery:canvas:", "find:", "ifEmpty:", "toArray", "removeAttr:"]
  372. }),
  373. $globals.HTMLCanvas);
  374. $core.addMethod(
  375. $core.method({
  376. selector: "asSnippet",
  377. protocol: "*Web-Snippets",
  378. fn: function (){
  379. var self=this,$self=this;
  380. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  381. return $core.withContext(function($ctx1) {
  382. //>>excludeEnd("ctx");
  383. return $recv($recv($globals.HTMLSnippet)._current())._snippetAt_($self._asString());
  384. //>>excludeStart("ctx", pragmas.excludeDebugContexts);
  385. }, function($ctx1) {$ctx1.fill(self,"asSnippet",{})});
  386. //>>excludeEnd("ctx");
  387. },
  388. //>>excludeStart("ide", pragmas.excludeIdeData);
  389. args: [],
  390. source: "asSnippet\x0a\x09^ HTMLSnippet current snippetAt: self asString",
  391. referencedClasses: ["HTMLSnippet"],
  392. //>>excludeEnd("ide");
  393. pragmas: [],
  394. messageSends: ["snippetAt:", "current", "asString"]
  395. }),
  396. $globals.String);
  397. });