Skip to content

Commit 574d13f

Browse files
committed
Merge branch 'gh-pages' of https://github.com/LivelyKernel/lively4-core into gh-pages
2 parents 41c1d28 + 9af4ce2 commit 574d13f

File tree

23 files changed

+1019
-148
lines changed

23 files changed

+1019
-148
lines changed

demos/leo/dice_roller.js

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
export default class DiceRoller {
2+
3+
onMouseDownOverAmount(evt, currentAmount) {
4+
evt.preventDefault();
5+
evt.stopPropagation();
6+
7+
// reset
8+
var all = currentAmount.parentElement.parentElement.parentElement.querySelectorAll("div[name='value']")
9+
all.forEach(e => e.style.border = "1px lightgray solid")
10+
// mark and save new
11+
currentAmount.style.border = "1px black solid";
12+
this.amount = currentAmount;
13+
}
14+
15+
onMouseOverType(evt, currentType) {
16+
evt.preventDefault();
17+
evt.stopPropagation();
18+
19+
if (this.amount) {
20+
// reset
21+
var all = currentType.parentElement.parentElement.parentElement.querySelectorAll("div[name='value']")
22+
all.forEach(e => e.style.border = "1px lightgray solid")
23+
// mark and save new
24+
currentType.style.border = "1px black solid";
25+
this.type = currentType;
26+
}
27+
}
28+
29+
onMouseOverBonus(evt, currentBonus) {
30+
evt.preventDefault();
31+
evt.stopPropagation();
32+
33+
if (this.amount) {
34+
// reset
35+
var all = currentBonus.parentElement.parentElement.parentElement.querySelectorAll("div[name='value']")
36+
all.forEach(e => e.style.border = "1px lightgray solid")
37+
// mark and save new
38+
currentBonus.style.border = "1px black solid";
39+
this.bonus = currentBonus;
40+
}
41+
}
42+
43+
onMouseUp(evt) {
44+
if (this.amount && this.type) {
45+
var output = this.amount.value + this.type.value
46+
if (this.bonus){
47+
output = output + this.bonus.value
48+
}
49+
this.output.value = output;
50+
}
51+
[this.amount, this.type, this.bonus].forEach(e => {
52+
if (e) e.style.border = "1px lightgray solid";
53+
})
54+
this.amount = undefined;
55+
this.type = undefined;
56+
this.bonus = undefined;
57+
}
58+
59+
create() {
60+
61+
// amount
62+
var table = <table style="width:100%"></table>
63+
var amount = <div style="padding:5px">
64+
<div style="border: 1px solid black; margin:auto">
65+
{table}
66+
</div>
67+
</div>
68+
69+
for (var i = 1; i <= 4; i++) {
70+
var value = <div name="value" style="width:max; text-align:center; background-color: lightgray; border: 1px lightgray solid; cursor: grab">{i}</div>
71+
value.value = i;
72+
var del = <div style="width:max; text-align:right; cursor: pointer">X</div>;
73+
74+
const currentAmount = value
75+
value.addEventListener('mousedown', (evt) => this.onMouseDownOverAmount(evt, currentAmount));
76+
77+
var cell =
78+
<tr>
79+
<td style="width: 33%"></td>
80+
<td style="width: 33%">{value}</td>
81+
<td style="width: 33%">{del}</td>
82+
</tr>
83+
table.appendChild(cell)
84+
}
85+
86+
87+
// type
88+
var typeTable = <table style="width:100%"></table>;
89+
var type = <div style="padding:5px">
90+
<div style="border: 1px solid black; margin:auto">
91+
{typeTable}
92+
</div>
93+
</div>;
94+
95+
["d4", "d6", "d8", "d10", "d12", "d20"].forEach(e => {
96+
var value = <div name="value" style="width:max; text-align:center; background-color: lightgray; border: 1px lightgray solid; cursor: grab">{e}</div>
97+
value.value = e;
98+
var del = <div style="width:max; text-align:right; cursor: pointer">X</div>;
99+
100+
const currentType = value
101+
102+
value.addEventListener('mouseover', (evt) => this.onMouseOverType(evt, currentType));
103+
104+
var cell =
105+
<tr>
106+
<td style="width: 33%"></td>
107+
<td style="width: 33%">{value}</td>
108+
<td style="width: 33%">{del}</td>
109+
</tr>
110+
typeTable.appendChild(cell)
111+
})
112+
113+
114+
// bonus
115+
var bonusTable = <table style="width:100%"></table>;
116+
var bonus = <div style="padding:5px">
117+
<div style="border: 1px solid black; margin:auto">
118+
{bonusTable}
119+
</div>
120+
</div>;
121+
122+
["-1", "0", "+1", "+2", "+3", "+4"].forEach(e => {
123+
var value = <div name="value" style="width:max; text-align:center; background-color: lightgray; border: 1px lightgray solid; cursor: grab">{e}</div>
124+
value.value = e;
125+
var del = <div style="width:max; text-align:right; cursor: pointer">X</div>;
126+
127+
const currentBonus = value
128+
129+
value.addEventListener('mouseover', (evt) => this.onMouseOverBonus(evt, currentBonus));
130+
131+
var cell =
132+
<tr>
133+
<td style="width: 33%"></td>
134+
<td style="width: 33%">{value}</td>
135+
<td style="width: 33%">{del}</td>
136+
</tr>
137+
bonusTable.appendChild(cell)
138+
})
139+
140+
this.output = <input></input>
141+
142+
var roller =
143+
<table style="width:100%, height:100%; border: 1px lightgray solid">
144+
<tr>
145+
<th style="width:33%">Amount</th>
146+
<th style="width:33%">Type</th>
147+
<th style="width:33%">Bonus</th>
148+
</tr>
149+
<tr>
150+
<td>{amount}</td>
151+
<td>{type}</td>
152+
<td>{bonus}</td>
153+
</tr>
154+
<tr>
155+
{this.output}
156+
</tr>
157+
</table>
158+
roller.addEventListener('mouseleave', (evt) => this.onMouseUp(evt));
159+
roller.addEventListener('mouseup', (evt) => this.onMouseUp(evt));
160+
161+
return roller
162+
}
163+
}

demos/leo/dice_roller.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Dice Roller
2+
3+
<script>
4+
import DiceRoller from "./dice_roller.js";
5+
6+
var d = new DiceRoller();
7+
8+
d.create();
9+
</script>
688 KB
Loading

doc/journal/2021-03-29.md/index.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
## 2021-03-29
2+
*Author: @JensLincke*
3+
4+
# Lively4Loader
5+
6+
Some lively scripting on a web page
7+
8+
```javascript
9+
var downloads = document.body.querySelectorAll("input")
10+
.filter(ea => ea.getAttribute('onclick') && ea.getAttribute('onclick').match("download"))
11+
var category = document.body.querySelector(`font[color="darkblue"]`).textContent
12+
var script = ""
13+
var cookie=document.cookie
14+
for(var d of downloads) {
15+
var parsed = d.getAttribute("onclick").split("'")
16+
var item = parsed[1]
17+
var key = parsed[3]
18+
var description = d.parentElement.parentElement.querySelector(`font[color="black"]`).childNodes[1].textContent
19+
20+
if (description) {
21+
var dir = description.replace(/[:\/\\'`"#@%?]/g,"_");
22+
script +=`# ${item}\n mkdir "${dir}";\n pushd "${dir}";\n curl -X POST -b "${cookie}" -O -J -F item='${item}' -F key='${key}' -F click=1 https://docs.dev-docs.org/htm/download.php;\n popd;\n`
23+
}
24+
}
25+
script = `mkdir "${category}";\npushd "${category}";\n${script};\n popd`
26+
lively.files.saveFile(`http://localhost:9005/tmp/robert/${category}.sh`, script)
27+
```
28+
29+
30+
![](lively4loaderScripting.png)
31+
32+
## Fuck, I lost some valuable progress...
33+
34+
because scripting on lively auto saved desktop is not versioned... and I had multiple tabs open... and closed an old one after a new one... the old one has overridden the new content :/
35+
36+
This is what I got... but there was some fancy Makefile, and auto reloading logic that evolved on that page that is now lost.
37+
38+
So let's recreate it.
39+
40+
```javascript
41+
var downloads = document.body.querySelectorAll("input")
42+
.filter(ea => ea.getAttribute('onclick') && ea.getAttribute('onclick').match("download"))
43+
var category = document.body.querySelector(`font[color="darkblue"]`).textContent
44+
var script = ""
45+
var cookie=document.cookie
46+
for(var d of downloads) {
47+
var parsed = d.getAttribute("onclick").split("'")
48+
var item = parsed[1]
49+
var key = parsed[3]
50+
var description = d.parentElement.parentElement.querySelector(`font[color="black"]`).childNodes[1].textContent
51+
52+
if (description) {
53+
var dir = description.replace(/[:\/\\'`"#@%?]/g,"_");
54+
script +=`if [ ! -d "${dir}" ];
55+
then mkdir "${dir}";
56+
pushd "${dir}";
57+
curl -X POST -b "${cookie}" -O -J -F item='${item}' -F key='${key}' -F click=1 https://docs.dev-docs.org/htm/download.php;
58+
popd;
59+
else
60+
echo "skip ${dir}";
61+
fi
62+
`
63+
}
64+
}
65+
script = `
66+
mkdir "${category}"
67+
rm "${category}"/*/download.php
68+
rmdir "${category}"/*
69+
pushd "${category}"
70+
${script}
71+
popd` ;
72+
73+
74+
75+
(async () => {
76+
await lively.files.saveFile(`http://localhost:9005/tmp/robert/${category}.sh`, script)
77+
var makefile = `
78+
all:
79+
\t\tbash "${category}.sh"
80+
81+
`
82+
await lively.files.saveFile(`http://localhost:9005/tmp/robert/Makefile`, makefile)
83+
var buildPath = "tmp/robert/"
84+
var serverURL = "http://localhost:9005"
85+
var makeURL = serverURL + "/_make/" + buildPath
86+
87+
document.body.querySelector("#log").value = "run script"
88+
var result = await fetch(makeURL, {}).then(r => r.text())
89+
document.body.querySelector("#log").value = result
90+
if (result.match("% Total % Received")) {
91+
lively.warn("not finished yet")
92+
await lively.sleep(1000)
93+
location.reload()
94+
} else {
95+
lively.success("finished")
96+
}
97+
})()
98+
99+
document.cookie.replace(/(?<=^|;).+?(?=\=|;|$)/g, name => location.hostname.split('.').reverse().reduce(domain => (domain=domain.replace(/^\.?[^.]+/, ''),document.cookie=`${name}=;max-age=0;path=/;domain=${domain}`,domain), location.hostname));
100+
101+
```
102+
103+
A specialty of the workspace is that it executes itself on page load automatically, by attaching a lively-script to its parent window.
104+
```javascript
105+
function livelyLoad() {
106+
lively.sleep(1000).then(() => {
107+
this.target.boundEval(this.target.value)
108+
})
109+
}
110+
```
111+
112+
And it triggers a page reload with `location.reload()` that way it keeps executing across page reloads, allowing the page to get new cookies and generate and execute new download scripts until the downloads are finished. The whole mess could be replaced be getting the fresh cookie and extracting items, keys, and descriptions on the command line. But for this one-time-script it is not worth it... and the downloads are automated enough.
113+
114+
115+
116+
117+
![](docs_works_again.png)
393 KB
Loading

src/client/dependency-graph/graph.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export class DependencyGraph {
3232
}
3333

3434
getAllActiveExpressions () {
35+
if(!this.programPath) return [];
3536
const allAExpr = [];
3637
this.programPath.traverse({
3738
CallExpression(path) {
@@ -44,6 +45,7 @@ export class DependencyGraph {
4445
}
4546

4647
get hasActiveExpressionsDirective() {
48+
if(!this.programPath) return false;
4749
return this.programPath.node.directives.some(node => {
4850
return node.value.value === "enable aexpr";
4951
});
@@ -62,6 +64,7 @@ export class DependencyGraph {
6264
}
6365

6466
enrich() {
67+
if(!this.programPath) return;
6568
let self = this;
6669
this.programPath.traverse({
6770
enter(path) {

src/client/lively.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1473,7 +1473,7 @@ export default class Lively {
14731473
var pattern = patternOrPosition;
14741474
}
14751475

1476-
if (!url || !url.match(/^[a-z]+:\/\//)) url = lively4url;
1476+
if (!url || !url.match(/^[a-z]+:/)) url = lively4url;
14771477
var livelyContainer;
14781478
var containerPromise;
14791479
let existingFound = false;

src/client/reactive/active-expression-rewriting/active-expression-rewriting.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ class Dependency {
210210

211211
getAsDependencyDescription() {
212212
const [context, identifier, value] = this.contextIdentifierValue();
213-
debugger;
214213

215214
if (this.isMemberDependency()) {
216215
return {

src/client/reactive/active-expression/active-expression.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ window.__compareAExprResults__ = false;
1414
self.__aexprRegistry_eventTarget__ = self.__aexprRegistry_eventTarget__ || new EventTarget();
1515
self.__aexprRegistry_aexprs__ = self.__aexprRegistry_aexprs__ || new Set();
1616
self.__aexprRegistry_idCounters__ = self.__aexprRegistry_idCounters__ || new Map();
17+
self.__aexprRegistry_callbackStack__ = self.__aexprRegistry_callbackStack__ || [];
1718

1819
/*MD ## Registry of Active Expressions MD*/
1920
export const AExprRegistry = {
@@ -42,7 +43,19 @@ export const AExprRegistry = {
4243
off(type, callback) {
4344
return self.__aexprRegistry_eventTarget__.removeEventListener(type, callback);
4445
},
46+
47+
addToCallbackStack(ae) {
48+
self.__aexprRegistry_callbackStack__.push(ae);
49+
},
4550

51+
popCallbackStack() {
52+
self.__aexprRegistry_callbackStack__.pop();
53+
},
54+
55+
callbackStack() {
56+
return self.__aexprRegistry_callbackStack__;
57+
},
58+
4659
buildIdFor(ae) {
4760
let locationId;
4861
if (ae.meta().has('location')) {
@@ -329,8 +342,9 @@ export class BaseActiveExpression {
329342
}
330343
const lastValue = this.lastValue;
331344
this.storeResult(value);
345+
const parentAE = AExprRegistry.callbackStack()[AExprRegistry.callbackStack().length - 1];
332346
Promise.resolve(location)
333-
.then(trigger => this.logEvent('changed value', { value, trigger, dependency, hook, lastValue }));
347+
.then(trigger => this.logEvent('changed value', { value, trigger, dependency, hook, lastValue, parentAE}));
334348

335349
this.notify(value, {
336350
lastValue,
@@ -407,7 +421,9 @@ export class BaseActiveExpression {
407421
}
408422

409423
notify(...args) {
424+
AExprRegistry.addToCallbackStack(this);
410425
this.callbacks.forEach(callback => callback(...args));
426+
AExprRegistry.popCallbackStack();
411427
AExprRegistry.updateAExpr(this);
412428
}
413429

0 commit comments

Comments
 (0)