Skip to content

Commit 4e491b3

Browse files
committed
Merge branch 'gh-pages' of https://github.com/LivelyKernel/lively4-core into gh-pages
2 parents 8a2027d + b728e9e commit 4e491b3

File tree

5 files changed

+221
-7
lines changed

5 files changed

+221
-7
lines changed
822 KB
Loading

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

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
## 2021-03-18 #CustomNavbarItems
2+
*Author: @JensLincke*
3+
4+
![](custom-navbar-items.png)
5+
6+
7+
And just for backups... the markdown app in my local movie dir.
8+
9+
```javascript
10+
# Movies
11+
12+
13+
<script>
14+
15+
var container = lively.query(this, "lively-container");
16+
import ContextMenu from 'src/client/contextmenu.js';
17+
18+
(async () => {
19+
var dir = container.getDir()
20+
21+
// "cached://" +
22+
var listSource = await fetch( dir + "/movies.jsonl").then(r => r.text())
23+
24+
var files = listSource.split("\n").map(ea => {
25+
try {
26+
return JSON.parse(ea)
27+
} catch(e) {
28+
return null
29+
}
30+
}).filter(ea => ea)
31+
32+
33+
var movies = files
34+
.filter(ea => ea.imdb)
35+
.map(ea => ea.imdb)
36+
.uniq().map(ea => {
37+
var all =files.filter(file => file.imdb == ea)
38+
var first = all[0]
39+
first.files = all
40+
return first
41+
})
42+
.filter(ea => ea.year)
43+
44+
var genres = new Map()
45+
for(let movie of movies) {
46+
for(let genre of (movie.genre || "").split(/, /)) {
47+
var bag = genres.get(genre) || []
48+
bag.push(movie)
49+
genres.set(genre, bag)
50+
}
51+
}
52+
53+
let serverURL = lively.files.serverURL(dir)
54+
// does only make sense when accessing a localhost server,
55+
// otherwise a pdf viewer would be opened on a remote machine?
56+
57+
var style = document.createElement("style")
58+
style.textContent = `
59+
.poster img {
60+
width: 120px;
61+
}
62+
.poster {
63+
height: 185px;
64+
overflow: hidden;
65+
}
66+
67+
.movie {
68+
font-size: 10pt;
69+
text-align: center;
70+
padding: 10px;
71+
width: 160px;
72+
height: 250px;
73+
display: inline-block;
74+
overflow: hidden;
75+
}
76+
77+
.year {
78+
color: gray;
79+
}
80+
81+
.genre {
82+
color: gray;
83+
font-style: italic;
84+
font-size:8pt;
85+
}
86+
.file {
87+
font-size:6pt;
88+
white-space: nowrap;
89+
}
90+
91+
`
92+
let playFile = (file) => {
93+
var url = dir + "/"+ encodeURI(file.filename)
94+
let playPath = url.replace(serverURL,"").replace(/^\//,"")
95+
var openURL = serverURL + "/_open/" + playPath
96+
lively.notify("open " + openURL)
97+
fetch(openURL)
98+
}
99+
100+
101+
var movieItems = movies.map(movie => {
102+
var title = <a class="title" click={() => {
103+
lively.openInspector(movie)
104+
}}></a>
105+
title.innerHTML = movie.files[0].title // contains HTML
106+
107+
var item = <div class="movie">
108+
<div class="poster">
109+
<img src={dir + "_imdb_/posters/" + movie.imdb+ ".jpg"}
110+
click={() => window.open("https://www.imdb.com/title/" + movie.imdb)}
111+
></img>
112+
</div>
113+
{title}
114+
<span class="year">({movie.files[0].year})</span>
115+
<br />
116+
<span class="genre">{movie.files[0].genre || ""}</span>
117+
{... movie.files.map(file => {
118+
var fileItem = <div class="file"><a click={() => {
119+
playFile(file)
120+
}}>{file.filename.replace(/.*\//,"")}</a></div>
121+
fileItem.addEventListener('contextmenu', evt => {
122+
if (!evt.shiftKey) {
123+
evt.stopPropagation();
124+
evt.preventDefault();
125+
var menu = new ContextMenu(fileItem, [
126+
["open", () => playFile(file)],
127+
]);
128+
menu.openIn(document.body, evt, fileItem);
129+
return true;
130+
}
131+
132+
}, false);
133+
134+
return fileItem
135+
136+
})}
137+
</div>
138+
139+
item.movie = movie
140+
return item
141+
});
142+
143+
144+
let pane = <div class="movies">
145+
{...movieItems}
146+
</div>
147+
148+
149+
let sortByYear = () => {
150+
pane.innerHTML = ""
151+
movieItems.sortBy(ea => ea.movie.year).reverse().forEach(ea => {
152+
pane.appendChild(ea)
153+
})
154+
155+
}
156+
157+
let filterGenre = (genre) => {
158+
debugger
159+
pane.innerHTML = ""
160+
movieItems
161+
.sortBy(ea => ea.movie.year)
162+
.reverse()
163+
.filter(ea => ea.movie.genre && ea.movie.genre.match(genre))
164+
.forEach(ea => {
165+
pane.appendChild(ea)
166+
})
167+
}
168+
var navbar = container.get("lively-container-navbar")
169+
var navbarDetails = navbar.get("#details")
170+
171+
let createGenreButton = (genre) => {
172+
var bag = genres.get(genre)
173+
174+
var detailsItem = navbar.createDetailsItem(genre)
175+
detailsItem.classList.add("subitem")
176+
detailsItem.classList.add("level2")
177+
navbarDetails.querySelector("ul").appendChild(detailsItem)
178+
detailsItem.addEventListener("click", () => filterGenre(genre))
179+
180+
return <button click={() => filterGenre(genre)}>{genre} ({bag.length})</button>
181+
}
182+
183+
184+
return <div>
185+
{style}
186+
<div>
187+
<button click={() => sortByYear()}>by year</button>
188+
{...Array.from(genres.keys()).map(genre => createGenreButton(genre))}
189+
</div>
190+
{pane}
191+
</div>
192+
})()
193+
194+
195+
196+
</script>
197+
```
198+
199+
200+
201+
202+

src/components/tools/lively-container-navbar.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import Strings from "src/client/strings.js"
1111

1212
import FileIndex from "src/client/fileindex.js"
1313
import SearchRoots from "src/client/search-roots.js"
14+
import _ from 'src/external/lodash/lodash.js'
15+
1416
/*MD # Navbar
1517
1618
![](lively-container-navbar.png){width=300px}
@@ -537,7 +539,7 @@ export default class LivelyContainerNavbar extends Morph {
537539
if (prefix.length < 4) {
538540
prefix = ""
539541
}
540-
link.innerHTML = icon + title.replace(new RegExp("^" + prefix), "<span class='prefix'>" +prefix +"</span>")
542+
link.innerHTML = icon + title.replace(new RegExp("^" + _.escapeRegExp(prefix)), "<span class='prefix'>" +prefix +"</span>")
541543
this.lastTitle = title
542544

543545
var href = ea.href || ea.name;
@@ -699,7 +701,20 @@ export default class LivelyContainerNavbar extends Morph {
699701
["copy path to clipboard", () => copyTextToClipboard(otherUrl), "", '<i class="fa fa-clipboard" aria-hidden="true"></i>'],
700702
["copy file name to clipboard", () => copyTextToClipboard(otherUrl::fileName()), "", '<i class="fa fa-clipboard" aria-hidden="true"></i>'],
701703
])
704+
705+
let serverURL = lively.files.serverURL(otherUrl)
706+
if (serverURL && serverURL.match("localhost")) {
707+
// does only make sense when accessing a localhost server,
708+
// otherwise a pdf viewer would be opened on a remote machine?
709+
menuElements.push(["open externally", async () => {
710+
let buildPath = otherUrl.replace(serverURL,"").replace(/^\//,"")
711+
var openURL = serverURL + "/_open/" + buildPath
712+
fetch(openURL)
713+
}])
714+
}
715+
702716
}
717+
703718
if (isDir) {
704719

705720
if(SearchRoots.isSearchRoot(otherUrl)) {
@@ -802,8 +817,6 @@ export default class LivelyContainerNavbar extends Morph {
802817
createDetailsItem(name) {
803818
var item = <li class="link" click={evt => this.onDetailsItemClick(item, evt)}><a>{name}</a></li>
804819
item.name = name
805-
"I was here"
806-
807820
item.addEventListener('contextmenu', (evt) => {
808821
if (!evt.shiftKey) {
809822
this.onDetailsContextMenu(evt, item)

src/components/tools/lively-index-search.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ export default class IndexSearch extends Morph {
271271

272272
var newText = file.text.replace(new RegExp(this.pattern, "g"), this.replace)
273273
file.replaced = newText
274-
var replacedText = this.hightlightPattern(newText, RegExp.escape(this.replace))
274+
var replacedText = this.hightlightPattern(newText, _.escapeRegExp(this.replace))
275275
var replacePreviewColumn = <td id="replace">{replacedText}</td>
276276
file.item.appendChild(replacePreviewColumn)
277277

test.workspace

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
{
2-
"source": "https://lively-kernel.org/lively4/lively4-tom/test.js",
2+
"source": "https://lively-kernel.org/lively4/aexpr/test.js",
33
"sources": [
4-
"https://lively-kernel.org/lively4/lively4-tom/test.js",
5-
"https://lively-kernel.org/lively4/lively4-tom/test-loader.js"
4+
"https://lively-kernel.org/lively4/aexpr/test.js"
65
],
76
"options": {
87
"systemJS": false,

0 commit comments

Comments
 (0)