Skip to content

Commit 5ed2fa5

Browse files
authored
Dynamic examples page (#705)
* Dynamic examples page (fix #287) This patch removes the static examples page, reimplementing it in Links. Most functionality was straightforward to port over, however we needed two additional JS library functions: domGetAnchor and jsSetWindowEvent. * Remove old JS code * Typecheck examplesPage * grr
1 parent 9746686 commit 5ed2fa5

File tree

7 files changed

+235
-212
lines changed

7 files changed

+235
-212
lines changed

core/lib.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,10 @@ let env : (string * (located_primitive * Types.datatype * pure)) list = [
970970
(`Client, datatype "(String) ~> ()",
971971
IMPURE);
972972

973+
"domGetAnchor",
974+
(`Client, datatype "() ~> String",
975+
IMPURE);
976+
973977
(* Cookies *)
974978
"setCookie",
975979
(p2D (fun cookieName cookieVal req_data ->
@@ -1374,6 +1378,9 @@ let env : (string * (located_primitive * Types.datatype * pure)) list = [
13741378
"jsSetOnEvent",
13751379
(`Client, datatype "(DomNode, String, (Event) ~e~> (), Bool) ~e~> ()", IMPURE);
13761380

1381+
"jsSetWindowEvent",
1382+
(`Client, datatype "(String, (Event) ~e~> (), Bool) ~e~> ()", IMPURE);
1383+
13771384
"jsSetOnLoad",
13781385
(`Client, datatype "((Event) ~e~> ()) ~e~> ()", IMPURE);
13791386

examples/examplesPage.links

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
fun main() {
2+
var _ = spawnClient {
3+
var examples = "examples/";
4+
var frame = getNodeById("exampleFrame");
5+
var nav = getNodeById("navigation");
6+
var loadingOverlay = getNodeById("loadingOverlay");
7+
8+
fun isMobile() {
9+
var navWidth = stringToInt(domGetPropertyFromRef(nav, "offsetWidth"));
10+
var bodyWidth = stringToInt(domGetPropertyFromRef(getNodeById("container"), "offsetWidth"));
11+
not(navWidth < (bodyWidth / 2))
12+
}
13+
14+
fun replaceExample(url) {
15+
var exampleUrl = "/" ^^ examples ^^ url;
16+
domSetStyleAttrFromRef(loadingOverlay, "display", "flex");
17+
if (isMobile()) {
18+
redirect(exampleUrl)
19+
} else {
20+
domSetPropertyFromRef(frame, "data", exampleUrl)
21+
}
22+
}
23+
24+
fun interceptNavigation() {
25+
var anchor = domGetAnchor();
26+
if (anchor <> "") {
27+
var newLoc = implode(tl(explode(anchor)));
28+
replaceExample(newLoc)
29+
} else {
30+
()
31+
}
32+
}
33+
34+
jsSetOnEvent(frame, "load", fun(_) {
35+
domSetStyleAttrFromRef(loadingOverlay, "display", "none")
36+
}, false);
37+
jsSetWindowEvent("hashchange", fun(_) {
38+
interceptNavigation()
39+
}, false)
40+
};
41+
42+
page
43+
<html>
44+
<head>
45+
<meta charset="utf-8" />
46+
<meta name="viewport" content="width=device-width, initial-scale=1" />
47+
<title>Links examples</title>
48+
<link rel="stylesheet" type="text/css" href="/examples/css/doc.css" />
49+
</head>
50+
<body>
51+
<div id="container">
52+
<header>
53+
<h1>Links examples</h1>
54+
</header>
55+
<nav id="navigation">
56+
<section>
57+
<h3>The following examples are described in <a href="http://links-lang.org/papers/links-fmco06.pdf">Links: Web Programming Without Tiers</a></h3>
58+
<ul>
59+
<li>
60+
<a class="frame-link" l:onclick="{domSetAnchor("dictionary/dictSuggestUpdate.links")}" href="/examples/dictionary/dictSuggestUpdate.links" >Dictionary suggestion with database update</a>
61+
<a href="/examplessrc/dictionary/dictSuggestUpdate.links" target="_blank">source</a>
62+
</li>
63+
<li>
64+
<a class="frame-link" l:onclick="{domSetAnchor("draggable.links")}" href="/examples/draggable.links" >Draggable lists</a>
65+
<a href="/examplessrc/draggable.links" target="_blank">source</a>
66+
</li>
67+
<li>
68+
<a class="frame-link" l:onclick="{domSetAnchor("progress.links")}" href="/examples/progress.links" >Progress bar</a>
69+
<a href="/examplessrc/progress.links" target="_blank">source</a>
70+
</li>
71+
</ul>
72+
</section>
73+
<section>
74+
<h3>The following examples appeared in earlier drafts of the same paper</h3>
75+
<ul>
76+
<li>
77+
<a class="frame-link" l:onclick="{domSetAnchor("factorial.links")}" href="/examples/factorial.links" >Factorial</a>
78+
<a href="/examplessrc/factorial.links" target="_blank">source</a>
79+
</li>
80+
<li>
81+
<a class="frame-link" l:onclick="{domSetAnchor("dictionary/dictSuggest.links")}" href="/examples/dictionary/dictSuggest.links" >Dictionary suggestion (with styles)</a>
82+
<a href="/examplessrc/dictionary/dictSuggest.links" target="_blank">source</a>
83+
</li>
84+
<li>
85+
<a class="frame-link" l:onclick="{domSetAnchor("dictionary/dictSuggestLite.links")}" href="/examples/dictionary/dictSuggestLite.links" >Dictionary suggestion (no styles)</a>
86+
<a href="/examplessrc/dictionary/dictSuggestLite.links" target="_blank">source</a>
87+
</li>
88+
<li>
89+
<a class="frame-link" l:onclick="{domSetAnchor("draggableDb.links")}" href="/examples/draggableDb.links" >Draggable lists (database version)</a>
90+
<a href="/examplessrc/draggableDb.links" target="_blank">source</a>
91+
</li>
92+
</ul>
93+
</section>
94+
<section>
95+
<h3>Formlets examples</h3>
96+
<ul>
97+
<li>
98+
<a class="frame-link" l:onclick="{domSetAnchor("buttons.links")}" href="/examples/buttons.links" >Buttons</a>
99+
<a href="/examplessrc/buttons.links" target="_blank">source</a>
100+
</li>
101+
<li>
102+
<a class="frame-link" l:onclick="{domSetAnchor("formsTest.links")}" href="/examples/formsTest.links" >A simple test formlet</a>
103+
<a href="/examplessrc/formsTest.links" target="_blank">source</a>
104+
</li>
105+
<li>
106+
<a class="frame-link" l:onclick="{domSetAnchor("validate.links")}" href="/examples/validate.links" >Validation</a>
107+
<a href="/examplessrc/validate.links" target="_blank">source</a>
108+
</li>
109+
</ul>
110+
</section>
111+
<section>
112+
<h3>Other examples</h3>
113+
<ul>
114+
<li>
115+
<a class="frame-link" l:onclick="{domSetAnchor("loginFlow.links")}" href="/examples/loginFlow.links" >Login flow using <code>sendSuspend</code></a>
116+
<a href="/examplessrc/loginFlow.links" target="_blank">source</a>
117+
</li>
118+
<li>
119+
<a class="frame-link" l:onclick="{domSetAnchor("paginate.links")}" href="/examples/paginate.links" >Pagination</a>
120+
<a href="/examplessrc/paginate.links" target="_blank">source</a>
121+
</li>
122+
<li>
123+
<a class="frame-link" l:onclick="{domSetAnchor("mandelbrot.links")}" href="/examples/mandelbrot.links" >Mandelbrot sets</a>
124+
<a href="/examplessrc/mandelbrot.links" target="_blank">source</a>
125+
</li>
126+
<li>
127+
<a class="frame-link" l:onclick="{domSetAnchor("mandelcolor.links")}" href="/examples/mandelcolor.links" >Multi-coloured mandelbrot set</a>
128+
<a href="/examplessrc/mandelcolor.links" target="_blank">source</a>
129+
</li>
130+
<li>
131+
<a class="frame-link" l:onclick="{domSetAnchor("todo.links")}" href="/examples/todo.links" >Todo list (client)</a>
132+
<a href="/examplessrc/todo.links" target="_blank">source</a>
133+
</li>
134+
<li>
135+
<a class="frame-link" l:onclick="{domSetAnchor("todoDb.links")}" href="/examples/todoDb.links" >Todo list (server)</a>
136+
<a href="/examplessrc/todoDb.links" target="_blank">source</a>
137+
</li>
138+
<li>
139+
<a class="frame-link" l:onclick="{domSetAnchor("crop.links")}" href="/examples/crop.links" >Draggable Cropping Frame</a>
140+
<a href="/examplessrc/crop.links" target="_blank">source</a>
141+
</li>
142+
<li>
143+
<a class="frame-link" l:onclick="{domSetAnchor("wine.links")}" href="/examples/wine.links" >Winestore</a>
144+
<a href="/examplessrc/wine.links" target="_blank">source</a>
145+
</li>
146+
<li>
147+
<a class="frame-link" l:onclick="{domSetAnchor("filter.links")}" href="/examples/filter.links" >Dynamic wine filtering</a>
148+
<a href="/examplessrc/filter.links" target="_blank">source</a>
149+
</li>
150+
<li>
151+
<a class="frame-link" l:onclick="{domSetAnchor("citations.links")}" href="/examples/citations.links" >Citeseer data</a>
152+
<a href="/examplessrc/citations.links" target="_blank">source</a>
153+
</li>
154+
</ul>
155+
</section>
156+
<section>
157+
<h3>Game examples</h3>
158+
<ul>
159+
<li>
160+
<a class="frame-link" l:onclick="{domSetAnchor("games/twentyfortyeight.links")}" href="/examples/games/twentyfortyeight.links" >2048 in Links</a>
161+
<a href="/examplessrc/games/twentyfortyeight.links" target="_blank">source</a>
162+
</li>
163+
<li>
164+
<a class="frame-link" l:onclick="{domSetAnchor("games/breakout.links")}" href="/examples/games/breakout.links" >Breakout in Links</a>
165+
<a href="/examplessrc/games/breakout.links" target="_blank">source</a>
166+
</li>
167+
<li>
168+
<a class="frame-link" l:onclick="{domSetAnchor("games/tetris.links")}" href="/examples/games/tetris.links" >Tetris in Links</a>
169+
<a href="/examplessrc/games/tetris.links" target="_blank">source</a>
170+
</li>
171+
<li>
172+
<a class="frame-link" l:onclick="{domSetAnchor("games/pacman.links")}" href="/examples/games/pacman.links" >Pillman</a>
173+
<a href="/examplessrc/games/pacman.links" target="_blank">source</a>
174+
</li>
175+
</ul>
176+
</section>
177+
</nav>
178+
<main>
179+
<div class="loading-overlay" id="loadingOverlay">
180+
<div>
181+
<div class="sk-folding-cube sk-blue">
182+
<div class="sk-cube1 sk-cube"></div>
183+
<div class="sk-cube2 sk-cube"></div>
184+
<div class="sk-cube3 sk-cube"></div>
185+
</div>
186+
<div class="sk-folding-cube sk-red">
187+
<div class="sk-cube1 sk-cube"></div>
188+
<div class="sk-cube2 sk-cube"></div>
189+
<div class="sk-cube3 sk-cube"></div>
190+
</div>
191+
</div>
192+
<span>Loading example</span>
193+
</div>
194+
<object type="text/html" id="exampleFrame"></object>
195+
</main>
196+
</div>
197+
</body>
198+
</html>
199+
}
200+
201+
main()

0 commit comments

Comments
 (0)