Skip to content

Commit a742d0d

Browse files
committed
update ui and test features
1 parent b3ee56c commit a742d0d

5 files changed

Lines changed: 111 additions & 67 deletions

File tree

wasm/notebook/src/index.ejs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<a href="#" id="run-btn" class="bg-orange text-white mr-px-5">run &#9658; </a>
2727
<ul class="list-inline" id="buffers-list"></ul>
2828
<a href="#" id="new-tab" class="bg-light mr-px-5 text-black">new tab</a>
29-
<a href="#" id="import-code" class="bg-light mr-px-5 text-black">import code</a>
29+
<a href="#popup" id="import-code" class="bg-light mr-px-5 text-black">import code</a>
3030
</div>
3131

3232
<div class="nav-bar-links d-flex">
@@ -54,9 +54,9 @@
5454
<div class="popup">
5555
<div id="popup-header">Header Placeholder</div>
5656
<a class="popup-close" href="#">&times;</a>
57-
<div class="popup-content mt-1">
57+
<div class="popup-content mt-px-5">
5858
<input type="url" name="popup-url" id="popup-url">
59-
<button id="popup-import" class="btn bg-black">import</button>
59+
<button id="popup-import" class="btn bg-black text-white">import</button>
6060
</div>
6161
</div>
6262
</div>

wasm/notebook/src/index.js

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import {
1717
newBuf
1818
} from './editor';
1919

20+
import { genericFetch } from './tools'
21+
2022
// parsing: copied from the iodide project
2123
// https://github.com/iodide-project/iodide/blob/master/src/editor/iomd-tools/iomd-parser.js
2224
import {
@@ -26,6 +28,7 @@ import {
2628
// processing: execute/render editor's content
2729
import {
2830
runPython,
31+
runJS,
2932
addCSS,
3033
checkCssStatus,
3134
renderMarkdown,
@@ -56,46 +59,49 @@ const notebook = document.getElementById('rp-notebook');
5659
// By default only the primary is visible.
5760
// On click of split view, secondary editor is visible
5861
// Each editor can display multiple documents and doc types.
59-
// the created ones are main/tab1/css
60-
// user has the option to add their own document.
62+
// the created ones are main/python/js/css
63+
// user has the option to add their own documents.
6164
// all new documents are python docs
6265
// adapted/inspired from https://codemirror.net/demo/buffers.html
63-
const primaryEditor = CodeMirror(document.getElementById("primary-editor"), {
64-
theme: "ayu-mirage",
66+
const primaryEditor = CodeMirror(document.getElementById('primary-editor'), {
67+
theme: 'ayu-mirage',
6568
lineNumbers: true,
6669
lineWrapping: true,
6770
});
6871

69-
const secondaryEditor = CodeMirror(document.getElementById("secondary-editor"), {
72+
const secondaryEditor = CodeMirror(document.getElementById('secondary-editor'), {
7073
lineNumbers: true,
7174
lineWrapping: true
7275
});
7376

7477
const buffers = {};
7578

7679
// list of buffers (displayed on UI as inline list item next to run)
77-
const buffersList = document.getElementById("buffers-list");
80+
const buffersList = document.getElementById('buffers-list');
7881

7982
// dropdown of buffers (visible on click of split view)
80-
const buffersDropDown = document.getElementById("buffers-selection");
83+
const buffersDropDown = document.getElementById('buffers-selection');
8184

8285
// By default open 3 buffers, main, tab1 and css
8386
// TODO: add a JS option
8487
// Params for OpenBuffer (buffers object, name of buffer to create, default content, type, link in UI 1, link in UI 2)
85-
openBuffer(buffers, "main",
86-
"# python code or code blocks that start with %%py, %%md %%math.", "notebook",
88+
openBuffer(buffers, 'main',
89+
'# python code or code blocks that start with %%py, %%md %%math.', 'notebook',
8790
buffersDropDown, buffersList);
8891

89-
openBuffer(buffers, "tab1", "# Python code", "python",
92+
openBuffer(buffers, 'python', '# Python code', 'python',
9093
buffersDropDown, buffersList);
9194

92-
// openBuffer(buffers, "js", "// Javascript code go here", "javascript", buffersDropDown, buffersList);
93-
openBuffer(buffers, "css", "/* CSS */", "css", buffersDropDown,
95+
openBuffer(buffers, 'js', '// Javascript code go here', 'javascript',
96+
buffersDropDown, buffersList);
97+
98+
openBuffer(buffers, 'css', '/* CSS goes here */', 'css', buffersDropDown,
9499
buffersList);
95100

96-
// select main buffer by default
97-
selectBuffer(primaryEditor, buffers, "main");
98-
selectBuffer(secondaryEditor, buffers, "main");
101+
// select main buffer by default and set the main tab to active
102+
selectBuffer(primaryEditor, buffers, 'main');
103+
selectBuffer(secondaryEditor, buffers, 'main');
104+
document.querySelector('ul#buffers-list li:first-child').classList.add('active');
99105

100106
function onReady() {
101107
/* By default the notebook has the keyword "loading"
@@ -124,7 +130,7 @@ function readEditors() {
124130
// get the content of the css editor
125131
// and add the css to the head
126132
// use dataset.status for a flag to know when to update
127-
let cssCode = buffers["css"].getValue();
133+
let cssCode = buffers['css'].getValue();
128134
let cssStatus = checkCssStatus();
129135
switch (cssStatus) {
130136
case 'none':
@@ -139,13 +145,18 @@ function readEditors() {
139145
// do nothing
140146
}
141147

142-
// get all the buffers, except css and main
148+
//
149+
let jsCode = buffers['js'].getValue();
150+
runJS(jsCode);
151+
152+
// get all the buffers, except css, js and main
143153
// css is auto executed at the start
144154
// main is parsed then executed at the end
145155
// main can have md, math and python function calls
146156
let {
147157
css,
148158
main,
159+
js,
149160
...pythonBuffers
150161
} = buffers;
151162

@@ -169,7 +180,7 @@ function parseCodeFromMainEditor() {
169180
// runJS(js_code);
170181

171182
// gets code from main editor
172-
let mainCode = buffers["main"].getValue();
183+
let mainCode = buffers['main'].getValue();
173184
/*
174185
Split code into chunks.
175186
Uses %%keyword or %% keyword as separator
@@ -190,9 +201,9 @@ function parseCodeFromMainEditor() {
190201
runPython(content, notebook, error);
191202
break;
192203
// TODO: fix how js is injected and ran
193-
// case 'js':
194-
// runJS(content);
195-
// break;
204+
case 'js':
205+
runJS(content);
206+
break;
196207
case 'md':
197208
notebook.innerHTML += renderMarkdown(content);
198209
break;
@@ -205,49 +216,53 @@ function parseCodeFromMainEditor() {
205216
});
206217
}
207218

219+
function updatePopup(type, message) {
220+
document.getElementById('popup').dataset.type = type ;
221+
document.getElementById('popup-header').textContent = message;
222+
}
223+
208224
// import button
209225
// show a url input + fetch button
210226
// takes a url where there is raw code
211-
// document.getElementById('popup-import').addEventListener('click', async function () {
212-
// const url = document.getElementById('popup-url').value;
213-
// const type = document.getElementById('popup').dataset.type;
214-
// const code = await genericFetch(url, type);
215-
// switch (type) {
216-
// case '':
217-
// case 'py':
218-
// pyEditor.setValue(code);
219-
// break;
220-
// case 'js':
221-
// jsEditor.setValue(code);
222-
// break;
223-
// default:
224-
// //do nothing
225-
// }
226-
// });
227-
// document.getElementById('import-code').addEventListener('click' , function() {
228-
// updatePopup('python', 'URL (raw text format)');
229-
// });
227+
document.getElementById('popup-import').addEventListener('click', async function () {
228+
let url = document.getElementById('popup-url').value;
229+
let type = document.getElementById('popup').dataset.type;
230+
let code = await genericFetch(url, type);
231+
primaryEditor.setValue(code);
232+
});
233+
234+
document.getElementById('import-code').addEventListener('click' , function() {
235+
updatePopup('python', 'URL (raw text format)');
236+
});
230237

231238
// click on an item in the list
232-
CodeMirror.on(buffersList, "click", function(e) {
239+
CodeMirror.on(buffersList, 'click', function(e) {
233240
selectBuffer(primaryEditor, buffers, e.target.dataset.language);
234241
});
235242

236243
// select an item in the dropdown
237-
CodeMirror.on(buffersDropDown, "change", function() {
244+
CodeMirror.on(buffersDropDown, 'change', function() {
238245
selectBuffer(secondaryEditor, buffers, buffersDropDown.options[
239246
buffersDropDown.selectedIndex].value);
240247
});
241248

242249
// when css code editor changes
243250
// update data attribute flag to modified
244-
CodeMirror.on(buffers["css"], "change", function() {
251+
CodeMirror.on(buffers['css'], 'change', function() {
245252
let style = document.getElementsByTagName('style')[0];
246253
if (style) {
247-
style.dataset.status = "modified";
254+
style.dataset.status = 'modified';
248255
}
249256
});
250257

258+
document.getElementById('buffers-list').addEventListener('click' , function(event) {
259+
let elem = document.querySelector('.active');
260+
if (elem) {
261+
elem.classList.remove('active');
262+
}
263+
event.target.classList.add('active');
264+
});
265+
251266
// new tab, new buffer
252267
document.getElementById('new-tab')
253268
.addEventListener('click', function() {

wasm/notebook/src/process.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,20 @@ function checkCssStatus() {
5858
}
5959
}
6060

61-
// function runJS(code) {
62-
// const script = document.createElement('script');
63-
// const doc = document.body || document.documentElement;
64-
// const blob = new Blob([code], { type: 'text/javascript' });
65-
// const url = URL.createObjectURL(blob);
66-
// script.src = url;
67-
// doc.appendChild(script);
68-
// try {
69-
// URL.revokeObjectURL(url);
70-
// doc.removeChild(script);
71-
// } catch (e) {
72-
// // ignore if body is changed and script is detached
73-
// console.log(e);
74-
// }
75-
// }
61+
function runJS(code) {
62+
const script = document.createElement('script');
63+
const doc = document.body || document.documentElement;
64+
const blob = new Blob([code], { type: 'text/javascript' });
65+
const url = URL.createObjectURL(blob);
66+
script.src = url;
67+
doc.appendChild(script);
68+
try {
69+
URL.revokeObjectURL(url);
70+
doc.removeChild(script);
71+
} catch (e) {
72+
// ignore if body is changed and script is detached
73+
console.log(e);
74+
}
75+
}
7676

77-
export { runPython, renderMarkdown, renderMath, addCSS, checkCssStatus }
77+
export { runPython, runJS, renderMarkdown, renderMath, addCSS, checkCssStatus }

wasm/notebook/src/style.css

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ h2,
1111
h3,
1212
h4,
1313
h5,
14-
h6,
15-
p {
14+
h6 {
1615
margin: 0 0 10px;
1716
}
1817

@@ -113,7 +112,7 @@ ul.list-inline li {
113112
line-height: 30px;
114113
}
115114

116-
ul.list-inline li:first-child {
115+
.active {
117116
background-color: #1f2430;
118117
color: #fff;
119118
}
@@ -175,11 +174,17 @@ input[type='url'] {
175174
border: 1px solid black;
176175
border-radius: 0px;
177176
width: 85%;
178-
font-size: 0.9rem;
177+
font-size: 1rem;
179178
padding: 4px;
180179
font-family: monospace;
181180
}
182181

182+
.btn {
183+
height: 25px;
184+
border: 1px solid black;
185+
font-size: 1rem;
186+
}
187+
183188
#error {
184189
color: #f74c00;
185190
margin-top: 10px;

wasm/notebook/src/tools.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export const getResponseTypeFromFetchType = fetchEntry => {
2+
if (fetchEntry === "python") return "text";
3+
if (fetchEntry === "javascript") return "text";
4+
if (fetchEntry === "css") return "text";
5+
if (fetchEntry === "js") return "blob";
6+
if (fetchEntry === "plugin") return "text";
7+
if (fetchEntry === "bytes") return "arrayBuffer";
8+
return fetchEntry;
9+
};
10+
11+
export function genericFetch(path, fetchType) {
12+
const responseType = getResponseTypeFromFetchType(fetchType);
13+
return fetch(path)
14+
.then(r => {
15+
if (!r.ok) throw new Error(`${r.status} ${r.statusText} (${path})`);
16+
return r[responseType]();
17+
})
18+
.then(r => {
19+
if (fetchType === "bytes") {
20+
return new Uint8Array(r);
21+
}
22+
return r;
23+
});
24+
}

0 commit comments

Comments
 (0)