Merge branch 'main' into CollaborationGit
52
book/_static/bimodal_field.mtl
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Blender 4.0.2 MTL File: 'bimodal_distribution_v06_to_obj.blend'
|
||||
# www.blender.org
|
||||
|
||||
newmtl bedrock_dark
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl grass_flat
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.261166 0.800000 0.226093
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl gravel
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.155926 0.127438 0.088656
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl soil
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.372228 0.272421 0.169322
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl water
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.026867 0.549270 0.800000
|
||||
Ks 1.000000 1.000000 1.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 0.500000
|
||||
illum 2
|
||||
27187
book/_static/bimodal_field.obj
Normal file
155
book/_static/element_render_box.html
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Subsurface</title>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
#c {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="c"></canvas>
|
||||
|
||||
<script type="module">
|
||||
|
||||
// Path to object
|
||||
var path_obj = "bimodal_field.obj";
|
||||
var path_mtl = "bimodal_field.mtl";
|
||||
|
||||
|
||||
// Three.js - Load .OBJ and .MTL file - Windmill2
|
||||
// from https://threejsfundamentals.org/threejs/threejs-load-obj-materials-windmill2.html
|
||||
|
||||
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/build/three.module.js';
|
||||
import { OrbitControls } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/controls/OrbitControls.js';
|
||||
import { OBJLoader } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/loaders/OBJLoader.js';
|
||||
import { MTLLoader } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/loaders/MTLLoader.js';
|
||||
|
||||
function main() {
|
||||
const canvas = document.querySelector('#c');
|
||||
const renderer = new THREE.WebGLRenderer({ canvas });
|
||||
|
||||
const fov = 45;
|
||||
const aspect = 2; // the canvas default
|
||||
const near = 0.1;
|
||||
const far = 100;
|
||||
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
|
||||
camera.position.set(0, 10, 20);
|
||||
|
||||
const controls = new OrbitControls(camera, canvas);
|
||||
controls.target.set(0, 5, 0);
|
||||
controls.update();
|
||||
|
||||
const scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color('white');
|
||||
|
||||
{
|
||||
const skyColor = 0xB1E1FF; // light blue
|
||||
const groundColor = 0xB97A20; // brownish orange
|
||||
const intensity = 1;
|
||||
const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
|
||||
scene.add(light);
|
||||
}
|
||||
|
||||
{
|
||||
const color = 0xFFFFFF;
|
||||
const intensity = 1;
|
||||
const light = new THREE.DirectionalLight(color, intensity);
|
||||
light.position.set(5, 10, 2);
|
||||
scene.add(light);
|
||||
scene.add(light.target);
|
||||
}
|
||||
|
||||
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
|
||||
const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
|
||||
const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
|
||||
const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
|
||||
// compute a unit vector that points in the direction the camera is now
|
||||
// in the xz plane from the center of the box
|
||||
const direction = (new THREE.Vector3())
|
||||
.subVectors(camera.position, boxCenter)
|
||||
.multiply(new THREE.Vector3(1, 0, 1))
|
||||
.normalize();
|
||||
|
||||
// move the camera to a position distance units way from the center
|
||||
// in whatever direction the camera was from the center already
|
||||
camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
|
||||
|
||||
// pick some near and far values for the frustum that
|
||||
// will contain the box.
|
||||
camera.near = boxSize / 100;
|
||||
camera.far = boxSize * 100;
|
||||
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
// point the camera to look at the center of the box
|
||||
camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
|
||||
}
|
||||
|
||||
{
|
||||
const mtlLoader = new MTLLoader();
|
||||
mtlLoader.load(path_mtl, (mtl) => {
|
||||
mtl.preload();
|
||||
const objLoader = new OBJLoader();
|
||||
objLoader.setMaterials(mtl);
|
||||
objLoader.load(path_obj, (root) => {
|
||||
scene.add(root);
|
||||
|
||||
// compute the box that contains all the stuff
|
||||
// from root and below
|
||||
const box = new THREE.Box3().setFromObject(root);
|
||||
|
||||
const boxSize = box.getSize(new THREE.Vector3()).length();
|
||||
const boxCenter = box.getCenter(new THREE.Vector3());
|
||||
|
||||
// set the camera to frame the box
|
||||
frameArea(boxSize * 1.2, boxSize, boxCenter, camera);
|
||||
|
||||
// update the Trackball controls to handle the new size
|
||||
controls.maxDistance = boxSize * 10;
|
||||
controls.target.copy(boxCenter);
|
||||
controls.update();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function resizeRendererToDisplaySize(renderer) {
|
||||
const canvas = renderer.domElement;
|
||||
const width = canvas.clientWidth;
|
||||
const height = canvas.clientHeight;
|
||||
const needResize = canvas.width !== width || canvas.height !== height;
|
||||
if (needResize) {
|
||||
renderer.setSize(width, height, false);
|
||||
}
|
||||
return needResize;
|
||||
}
|
||||
|
||||
function render() {
|
||||
|
||||
if (resizeRendererToDisplaySize(renderer)) {
|
||||
const canvas = renderer.domElement;
|
||||
camera.aspect = canvas.clientWidth / canvas.clientHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
}
|
||||
|
||||
renderer.render(scene, camera);
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
main();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,6 +5,7 @@ parts:
|
|||
- caption: Getting started!
|
||||
chapters:
|
||||
- file: installation-and-setup/user_types
|
||||
- file: workflows/github
|
||||
- file: installation-and-setup/overview
|
||||
sections:
|
||||
- file: installation-and-setup/git-setup
|
||||
|
|
@ -23,7 +24,6 @@ parts:
|
|||
- file: workflows/edit_book
|
||||
- file: workflows/merge_request
|
||||
- file: workflows/publish
|
||||
- file: workflows/githubtemplate
|
||||
- caption: Features
|
||||
chapters:
|
||||
- file: basic-features/overview
|
||||
|
|
@ -39,7 +39,10 @@ parts:
|
|||
sections:
|
||||
- file: features/grasple.md
|
||||
- file: features/h5p.md
|
||||
- file: features/adding_basic_HTML_elements.md
|
||||
- file: features/HTML_javascript.md
|
||||
sections:
|
||||
- file: features/adding_HTML_elements.md
|
||||
- file: features/creating_basic_HTML_elements.md
|
||||
- file: features/python_interactivity.md
|
||||
sections:
|
||||
- file: features/live_code.md
|
||||
|
|
|
|||
11
book/features/HTML_javascript.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Interactive HTML/JavaScript elements
|
||||
|
||||
In this section, we will discuss how to [create](creating_basic_HTML_elements.md) and [embed](adding_HTML_elements.md) interactive HTML/Javascript elements created in HTML/JavaScript in a TeachBook. These HTML/Javascript element work very fluently and don't require a python kernel running in the background.
|
||||
|
||||
This could be for example interactive 3d figures:
|
||||
|
||||
<iframe src="../_static/element_render_box.html" width="600" height="400" frameborder="0"></iframe>
|
||||
|
||||
Or other interactive graphs:
|
||||
|
||||
<iframe src="../_static/element_pdf_and_cdf.html" width="600" height="300" frameborder="0"></iframe>
|
||||
197
book/features/adding_HTML_elements.md
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
# Adding interactive HTML/JavaScript elements
|
||||
|
||||
In this section, we will discuss how to embed interactive elements created in HTML/JavaScript in a TeachBook. If you are interested in learning how to create these elements yourself, we will discuss an example in the [next article](creating_basic_HTML_elements.md). As an example, let us discuss how to embed an interactive 3D model of a subsurface environment I created:
|
||||
|
||||
<iframe src="../_static/element_render_box.html" width="600" height="400" frameborder="0"></iframe>
|
||||
|
||||
## Storing the HTML file
|
||||
TeachBooks like this one are built from a Git project, comprising of different files and folders that are assembled into a webpage. It is generally not possible to paste the code of your HTML element directly into one of the project's Markdown files. Instead, you will have to store the files separately somewhere in the folder structure, then embed them later on. For this project, the book's root folder contains a ´_static´ folder which we can use to store our HTML/JS file. Some elemenets - such as the one above - may require additional files. The HTML element above, for instance, specifies a renderer using [THREE.js](https://threejs.org/) that displays a digital model. This model is specified as an .obj file (which defines its geometry) and a .mtl file (which defines its materials - its colors, reflectivity, transparency, and so on). We can store these files in the same ´_static´ folder.
|
||||
|
||||
## Embedding HTML files via iframes
|
||||
If we want to embed our HTML/JS element in a Markdown page, we must use an inline frame, also known as an iframe. In code, an iframe looks like this:
|
||||
|
||||
```html
|
||||
<iframe src="../_static/element_render box.html" width="600" height="300" frameborder="0"></iframe>
|
||||
```
|
||||
|
||||
What does this code do? In HTML, certain active parts of the code are defined as tags surrounded by `<` and `>` symbols. The tag `<iframe>` opens the iframe environment, the `<iframe/>` tag closes it again. Inside the opening tag, we can further specify properties of the iframe. These properties are usually defined as strings, that is to say, surrounded by quotation marks. Some of the more common iframe properties are:
|
||||
- `src`: This specifies the **source** of the iframe, the HTML file it will display.
|
||||
- `width`: This specifies the **width** of the iframe in pixels.
|
||||
- `height`: This specifies the **height** of the iframe in pixels.
|
||||
- `frameborder`: This flag specifies whether a border should be drawn around the iframe (`"1"`) or not (`"0"`).
|
||||
- `scrolling`: Specifies whether or not to display scrollbars for the iframe, in case the embedded content is larger than the iframe. Possible values are `"yes"`, `"no"`, and `"auto"`. I recommend either creating HTML elements of the same size, or adjusting their size dynamically to their contained - in this case, the iframe.
|
||||
- `allowfullscreen`: Specifies whether or not to allow the iframe to be displayed in fullscreen mode.
|
||||
- `loading`: Specifies how the browser should handle the loading of the iframe content. Possible values are eager (load immediately) and lazy (load on demand).
|
||||
|
||||
Let's take a closer look at the source. Since this project uses a local file structure, we can make use of relative paths such as `../_static/element_render box.html`. What does this path do? In this project, the markdown file for this article is located in the directory `book/features/adding_HTML_elements.md`. The HTML element we want to embed is located in the directory `book/_static/element_render_box.html`. The relative path thus works as follows:
|
||||
- We start in the markdown file's directory `book/features/adding_HTML_elements.md`
|
||||
- The string `"../"` tells the iframe to move up one folder to `book`
|
||||
- The following string `"_static/"` tells the iframe to navigate into the `_static` folder. We are now in `book/_static/`.
|
||||
- Finally, the string `"element_render_box.html"` selects the HTML file we want to embed. We are now in `book/_static/element_render_box.html`.
|
||||
|
||||
## Viewing result at local build
|
||||
To view the final result locally, it's required to setup a [local python webserver](setup-local-server).
|
||||
|
||||
## HTML code for the 3D render element
|
||||
|
||||
To conclude, I provide the HTML/JavaScript code for the 3D render element above. To understand what the code below does in more detail, please refer to the [next article](creating_basic_HTML_elements.md). One thing I want to direct your attention to are the paths specified in the first few lines of the `<script>` environment. Here, we do not have to navigate to a different local folder because we initially stored our `.obj` and `.mtl` files in the same folder as the `element_render_box.html` file. If they would be stored in a different folder, we have to specify either an absolute path (e.g., via a URL) or a relative path, as explained above.
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Subsurface</title>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
#c {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="c"></canvas>
|
||||
|
||||
<script type="module">
|
||||
|
||||
// Path to object
|
||||
var path_obj = "bimodal_field.obj";
|
||||
var path_mtl = "bimodal_field.mtl";
|
||||
|
||||
|
||||
// Three.js - Load .OBJ and .MTL file - Windmill2
|
||||
// from https://threejsfundamentals.org/threejs/threejs-load-obj-materials-windmill2.html
|
||||
|
||||
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/build/three.module.js';
|
||||
import { OrbitControls } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/controls/OrbitControls.js';
|
||||
import { OBJLoader } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/loaders/OBJLoader.js';
|
||||
import { MTLLoader } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/loaders/MTLLoader.js';
|
||||
|
||||
function main() {
|
||||
const canvas = document.querySelector('#c');
|
||||
const renderer = new THREE.WebGLRenderer({ canvas });
|
||||
|
||||
const fov = 45;
|
||||
const aspect = 2; // the canvas default
|
||||
const near = 0.1;
|
||||
const far = 100;
|
||||
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
|
||||
camera.position.set(0, 10, 20);
|
||||
|
||||
const controls = new OrbitControls(camera, canvas);
|
||||
controls.target.set(0, 5, 0);
|
||||
controls.update();
|
||||
|
||||
const scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color('white');
|
||||
|
||||
{
|
||||
const skyColor = 0xB1E1FF; // light blue
|
||||
const groundColor = 0xB97A20; // brownish orange
|
||||
const intensity = 1;
|
||||
const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
|
||||
scene.add(light);
|
||||
}
|
||||
|
||||
{
|
||||
const color = 0xFFFFFF;
|
||||
const intensity = 1;
|
||||
const light = new THREE.DirectionalLight(color, intensity);
|
||||
light.position.set(5, 10, 2);
|
||||
scene.add(light);
|
||||
scene.add(light.target);
|
||||
}
|
||||
|
||||
function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
|
||||
const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
|
||||
const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
|
||||
const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
|
||||
// compute a unit vector that points in the direction the camera is now
|
||||
// in the xz plane from the center of the box
|
||||
const direction = (new THREE.Vector3())
|
||||
.subVectors(camera.position, boxCenter)
|
||||
.multiply(new THREE.Vector3(1, 0, 1))
|
||||
.normalize();
|
||||
|
||||
// move the camera to a position distance units way from the center
|
||||
// in whatever direction the camera was from the center already
|
||||
camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
|
||||
|
||||
// pick some near and far values for the frustum that
|
||||
// will contain the box.
|
||||
camera.near = boxSize / 100;
|
||||
camera.far = boxSize * 100;
|
||||
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
// point the camera to look at the center of the box
|
||||
camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
|
||||
}
|
||||
|
||||
{
|
||||
const mtlLoader = new MTLLoader();
|
||||
mtlLoader.load(path_mtl, (mtl) => {
|
||||
mtl.preload();
|
||||
const objLoader = new OBJLoader();
|
||||
objLoader.setMaterials(mtl);
|
||||
objLoader.load(path_obj, (root) => {
|
||||
scene.add(root);
|
||||
|
||||
// compute the box that contains all the stuff
|
||||
// from root and below
|
||||
const box = new THREE.Box3().setFromObject(root);
|
||||
|
||||
const boxSize = box.getSize(new THREE.Vector3()).length();
|
||||
const boxCenter = box.getCenter(new THREE.Vector3());
|
||||
|
||||
// set the camera to frame the box
|
||||
frameArea(boxSize * 1.2, boxSize, boxCenter, camera);
|
||||
|
||||
// update the Trackball controls to handle the new size
|
||||
controls.maxDistance = boxSize * 10;
|
||||
controls.target.copy(boxCenter);
|
||||
controls.update();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function resizeRendererToDisplaySize(renderer) {
|
||||
const canvas = renderer.domElement;
|
||||
const width = canvas.clientWidth;
|
||||
const height = canvas.clientHeight;
|
||||
const needResize = canvas.width !== width || canvas.height !== height;
|
||||
if (needResize) {
|
||||
renderer.setSize(width, height, false);
|
||||
}
|
||||
return needResize;
|
||||
}
|
||||
|
||||
function render() {
|
||||
|
||||
if (resizeRendererToDisplaySize(renderer)) {
|
||||
const canvas = renderer.domElement;
|
||||
camera.aspect = canvas.clientWidth / canvas.clientHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
}
|
||||
|
||||
renderer.render(scene, camera);
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
main();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
```
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Adding basic interactive HTML/JavaScript elements
|
||||
# Creating basic interactive HTML/JavaScript elements
|
||||
|
||||
## Embedding HTML files
|
||||
A straightforward way to create interactive web-based elements is to code them directly using HTML with JavaScript. This allows us to build elements such as the one below, which shows the connection between a probability density function (pdf) and the associated cumulative density function (cdf):
|
||||
|
|
@ -15,9 +15,8 @@
|
|||
" - JupyterQuiz: code-based implementation of multiple-choiche questions and numerical answer questions. This is a basic open course tool which requires you to write your quiz questions in Python language as a `dict` or to a `.json` file.\n",
|
||||
" - H5p: TU-Delft-licensed tool to create questions (and many other interactive elements) using an [online GUI](https://tudelft.h5p.com/). These elements are embedded into the book using an iframe which requires very little coding. This elements are easier to implement than the JupyterQuiz and have more features (although proper numerical answer questions are missing). More information on this is provided in [this subchapter](h5p.md)\n",
|
||||
" - Grasple-exercises: TU-Delft-licensed tool to creating math-based quiz questions. Again, these elements are embedded into the book using an iframe which requiries very little coding. These elements are very well suited to math-based problems as it allows analytical evaluation of numerical values and formulas. Furthermore, Grasple allows parameterization (not required for formative exercises). More information on this is provided in [this subchapter](grasple.md)\n",
|
||||
" - Non-kernel-based widgets: You can create interactive widgets with Python which doesn't need a kernel to run online:\n",
|
||||
" - You can create html/javascript widgets, an example is shown in [this subchapter](adding_basic_HTML_elements.md)\n",
|
||||
" - The use of the [plotly](https://plotly.com/python/getting-started/) package is an example which allows this use.\n",
|
||||
" - Custom HTML/Javascript widgets: You can create and embed html/javascript widgets, an example is shown in [this subchapter](HTML_javascript.md)\n",
|
||||
" - HTML/Javascript widgets using Plotly. The use of the [plotly](https://plotly.com/python/getting-started/) package is an example which allows you to create HTML/Javascript widgets from python code without any knowledge on HTML/Javascript.\n",
|
||||
"\n",
|
||||
"Examples of each type is shown below based on the following problem:\n",
|
||||
"\n",
|
||||
|
|
@ -310,7 +309,18 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Interactive widget without kernel\n",
|
||||
"## HTML/Javascript\n",
|
||||
"\n",
|
||||
"The example below shows a custom HTML/Javascript element\n",
|
||||
"\n",
|
||||
"<iframe src=\"../_static/element_pdf_and_cdf.html\" width=\"600\" height=\"300\" frameborder=\"0\"></iframe>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Plotly graph\n",
|
||||
"\n",
|
||||
"The example below is taken from the FEM-module by Frans van der Meer.\n",
|
||||
"When using Plotly graphs, make sure the notebook is executed in Jupyter Lab / Jupyter Notebook for the figures to be shown in the book. Running the code in VS code might break the result in the book, although the output is visible in VS code. Alternatively, add the following lines of code to your notebook to have a valid output in the book as well:\n",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# JupyterLite-Sphinx: Interactive elements
|
||||
# JupyterLite-Sphinx
|
||||
|
||||
By popular demand: how to include interactive pieces of code in your Jupyter Book. We can do this by using the [JupyterLite](https://github.com/jupyterlite) app, which allows you to run a Jupyter Lab session and execute Python code entirely in-browser. Jupyterlite can be embedded in a Jupyter Book with the [`JupyterLite-Sphinx`](https://github.com/jupyterlite/jupyterlite-sphinx) extension.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Python-enabled interactivity\n",
|
||||
"# Sphinx-thebe\n",
|
||||
"\n",
|
||||
"Our book has been enable to run Python code live in the browser (thanks Max!). This page contains some installation instructions and the other sections show how to use this functionality to create interactive figures and feedback on code\n",
|
||||
"\n",
|
||||
|
|
@ -74,11 +74,7 @@
|
|||
"\n",
|
||||
"## Instructions: local build\n",
|
||||
"\n",
|
||||
"To test the fuctionality, you have to run a local server, otherwise the interactivity doens't work. So, you cannot just open the `index.html` file any more. This can be done with the following steps:\n",
|
||||
"1. build the book by running ` jupyter book build <directory of your book>`. If you are using Windows you should use the Git Bash terminal. Set this as your default in VS Code, then open it using \"New Terminal.\" If you have not already done so, you will need to allow Git Bash to use your Python libraries by running the command `conda init bash`.\n",
|
||||
"2. Set up a server by running `python -m http.server 8000`.\n",
|
||||
"3. Open the book by going to [http://localhost:8000/](http://localhost:8000/) in your browser. You may need to reload the page once the rebuild is complete. You can do this on Chrome by right-clicking somewhere on the page, select \"Inspect\", open the \"Network\" tab, then reload with `CTRL+R`. Or try `ctrl`+`F5`\n",
|
||||
"4. Go to any page that is created from a Jupyter notebook\n",
|
||||
"To test the fuctionality, you have to run a local server, otherwise the interactivity doens't work. So, you cannot just open the `index.html` file any more. This can be done with the steps shown in {ref}`setup-local-server`.\n",
|
||||
"\n",
|
||||
"If you push to main, you can test the interactivity on the book-draft website as well.\n",
|
||||
"\n",
|
||||
|
|
@ -115,11 +111,6 @@
|
|||
"%pip install package_name\n",
|
||||
"```\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 55 KiB |
|
|
@ -9,7 +9,7 @@ Now we will set up your first environment. The following steps will create an An
|
|||
For simplicity we will call this environment `my_new_book`, but you can give it any name you like.
|
||||
|
||||
1. Open the commmand line interface (see above) or continue in the same session if it is still active
|
||||
2. Execute: `conda create --n my_new_book pip` (this may take several minutes)
|
||||
2. Execute: `conda create --name my_new_book pip` (this may take several minutes)
|
||||
3. Activate: `conda activate my_new_book`
|
||||
<br> Check: you should now see your new environment displayed somewhere in the prompt between parenthesis, like this: `(my_new_book)`
|
||||
|
||||
|
|
|
|||
|
|
@ -31,5 +31,6 @@ Some features like JupyterLite and Grasple only work when a webserver serves the
|
|||
1. Start a server from the command line with: `python -m http.server -b 127.0.0.1` (add ` &` if you want to keep using the terminal for other tasks).
|
||||
2. Port 8000 is usually used by default, but depending on your OS it will tell you in the output.
|
||||
3. To visit your site, just enter the address in your web browser, followed by a colon, and then the port number. By default, that would be: `127.0.0.1:8000`.
|
||||
4. You will get a website that looks like a file browser, to visit your site just navigate to `book/_build/html/`.
|
||||
5. The JupyterLite consoles or Grasple iframe exercises should now work as well.
|
||||
4. You will get a website that looks like a file browser, to visit your site just navigate to `book/_build/html/` (if you've started this command from this folder you see the book immediately
|
||||
5. You may need to reload the page once the rebuild is complete. You can do this on Chrome by right-clicking somewhere on the page, select \"Inspect\", open the \"Network\" tab, then reload with `CTRL+R`. Or try `ctrl`+`F5`\n"
|
||||
6. All interactive features like the JupyterLite consoles, Grasple/H5p iframe exercises, Sphinx-thebe python interactivity and HTML/Javascript elements should now work as well.
|
||||
|
|
|
|||
BIN
book/workflows/figures/GitHub_desktop_fork.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
book/workflows/figures/action.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
book/workflows/figures/create_new_repository.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
book/workflows/figures/set_up_pages.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
book/workflows/figures/use_github_pages_website.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
book/workflows/figures/use_template.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
|
|
@ -1,47 +1,52 @@
|
|||
# Start your book using GitHub template
|
||||
# Your first TeachBook using template
|
||||
|
||||
This page shows you how as an example how to create your own Jupyter Book. It including making an edit to a predefined book and hosting that book online. It doesn't elaborate on the collaborative functionalities of Git.
|
||||
This page shows you how as an example how to start your own Jupyter Book and hosting that book online. It doesn't elaborate on the collaborative functionalities of Git or how to edit the book.
|
||||
|
||||
To get started making your Jupyter Book with our functionalities, fork our template book https://github.com/TeachBooks/template :
|
||||
`````{tab-set}
|
||||
````{tab-item} GitHub template
|
||||
|
||||

|
||||
1. To get started making your Jupyter Book with our functionalities, use the [template book](https://github.com/TeachBooks/template) as template:
|
||||
|
||||
Fill in a repository name, this name will be used in the future url of your book:
|
||||
```{figure} figures/use_template.png
|
||||
:name: use-template
|
||||
```
|
||||
|
||||

|
||||
2. Fill in a repository name, this name will be used in the future url of your book:
|
||||
|
||||
Set up the build of your website using GitHub pages by selecting under `Settings` - `Pages` - `Build and deployment` - `Source` - `GitHub Actions`:
|
||||
```{figure} figures/create_new_repository.png
|
||||
:name: create_new_repository
|
||||
```
|
||||
|
||||

|
||||
3. Set source for GitHub pages to under <svg aria-label="Edit repository metadata" role="img" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-gear float-right"> <path d="M8 0a8.2 8.2 0 0 1 .701.031C9.444.095 9.99.645 10.16 1.29l.288 1.107c.018.066.079.158.212.224.231.114.454.243.668.386.123.082.233.09.299.071l1.103-.303c.644-.176 1.392.021 1.82.63.27.385.506.792.704 1.218.315.675.111 1.422-.364 1.891l-.814.806c-.049.048-.098.147-.088.294.016.257.016.515 0 .772-.01.147.038.246.088.294l.814.806c.475.469.679 1.216.364 1.891a7.977 7.977 0 0 1-.704 1.217c-.428.61-1.176.807-1.82.63l-1.102-.302c-.067-.019-.177-.011-.3.071a5.909 5.909 0 0 1-.668.386c-.133.066-.194.158-.211.224l-.29 1.106c-.168.646-.715 1.196-1.458 1.26a8.006 8.006 0 0 1-1.402 0c-.743-.064-1.289-.614-1.458-1.26l-.289-1.106c-.018-.066-.079-.158-.212-.224a5.738 5.738 0 0 1-.668-.386c-.123-.082-.233-.09-.299-.071l-1.103.303c-.644.176-1.392-.021-1.82-.63a8.12 8.12 0 0 1-.704-1.218c-.315-.675-.111-1.422.363-1.891l.815-.806c.05-.048.098-.147.088-.294a6.214 6.214 0 0 1 0-.772c.01-.147-.038-.246-.088-.294l-.815-.806C.635 6.045.431 5.298.746 4.623a7.92 7.92 0 0 1 .704-1.217c.428-.61 1.176-.807 1.82-.63l1.102.302c.067.019.177.011.3-.071.214-.143.437-.272.668-.386.133-.066.194-.158.211-.224l.29-1.106C6.009.645 6.556.095 7.299.03 7.53.01 7.764 0 8 0Zm-.571 1.525c-.036.003-.108.036-.137.146l-.289 1.105c-.147.561-.549.967-.998 1.189-.173.086-.34.183-.5.29-.417.278-.97.423-1.529.27l-1.103-.303c-.109-.03-.175.016-.195.045-.22.312-.412.644-.573.99-.014.031-.021.11.059.19l.815.806c.411.406.562.957.53 1.456a4.709 4.709 0 0 0 0 .582c.032.499-.119 1.05-.53 1.456l-.815.806c-.081.08-.073.159-.059.19.162.346.353.677.573.989.02.03.085.076.195.046l1.102-.303c.56-.153 1.113-.008 1.53.27.161.107.328.204.501.29.447.222.85.629.997 1.189l.289 1.105c.029.109.101.143.137.146a6.6 6.6 0 0 0 1.142 0c.036-.003.108-.036.137-.146l.289-1.105c.147-.561.549-.967.998-1.189.173-.086.34-.183.5-.29.417-.278.97-.423 1.529-.27l1.103.303c.109.029.175-.016.195-.045.22-.313.411-.644.573-.99.014-.031.021-.11-.059-.19l-.815-.806c-.411-.406-.562-.957-.53-1.456a4.709 4.709 0 0 0 0-.582c-.032-.499.119-1.05.53-1.456l.815-.806c.081-.08.073-.159.059-.19a6.464 6.464 0 0 0-.573-.989c-.02-.03-.085-.076-.195-.046l-1.102.303c-.56.153-1.113.008-1.53-.27a4.44 4.44 0 0 0-.501-.29c-.447-.222-.85-.629-.997-1.189l-.289-1.105c-.029-.11-.101-.143-.137-.146a6.6 6.6 0 0 0-1.142 0ZM11 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM9.5 8a1.5 1.5 0 1 0-3.001.001A1.5 1.5 0 0 0 9.5 8Z"></path> </svg>`Settings` - <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-browser">
|
||||
<path d="M0 2.75C0 1.784.784 1 1.75 1h12.5c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 14.25 15H1.75A1.75 1.75 0 0 1 0 13.25ZM14.5 6h-13v7.25c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25Zm-6-3.5v2h6V2.75a.25.25 0 0 0-.25-.25ZM5 2.5v2h2v-2Zm-3.25 0a.25.25 0 0 0-.25.25V4.5h2v-2Z"></path>
|
||||
</svg> `Pages` - `Build and deployment` - `Source` - `GitHub Actions`:
|
||||
|
||||
Enable the predefined workflow to publish your book under `Actions` - `I understand my workflows, go ahead an enable them`:
|
||||
```{figure} figures/set_up_pages.png
|
||||
:name: activate_pages
|
||||
```
|
||||
|
||||

|
||||
4. Set repository website as your GitHub Pages website under <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code UnderlineNav-octicon d-none d-sm-inline">
|
||||
<path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path>
|
||||
</svg>`Code`- `About` - <svg aria-label="Edit repository metadata" role="img" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-gear float-right"> <path d="M8 0a8.2 8.2 0 0 1 .701.031C9.444.095 9.99.645 10.16 1.29l.288 1.107c.018.066.079.158.212.224.231.114.454.243.668.386.123.082.233.09.299.071l1.103-.303c.644-.176 1.392.021 1.82.63.27.385.506.792.704 1.218.315.675.111 1.422-.364 1.891l-.814.806c-.049.048-.098.147-.088.294.016.257.016.515 0 .772-.01.147.038.246.088.294l.814.806c.475.469.679 1.216.364 1.891a7.977 7.977 0 0 1-.704 1.217c-.428.61-1.176.807-1.82.63l-1.102-.302c-.067-.019-.177-.011-.3.071a5.909 5.909 0 0 1-.668.386c-.133.066-.194.158-.211.224l-.29 1.106c-.168.646-.715 1.196-1.458 1.26a8.006 8.006 0 0 1-1.402 0c-.743-.064-1.289-.614-1.458-1.26l-.289-1.106c-.018-.066-.079-.158-.212-.224a5.738 5.738 0 0 1-.668-.386c-.123-.082-.233-.09-.299-.071l-1.103.303c-.644.176-1.392-.021-1.82-.63a8.12 8.12 0 0 1-.704-1.218c-.315-.675-.111-1.422.363-1.891l.815-.806c.05-.048.098-.147.088-.294a6.214 6.214 0 0 1 0-.772c.01-.147-.038-.246-.088-.294l-.815-.806C.635 6.045.431 5.298.746 4.623a7.92 7.92 0 0 1 .704-1.217c.428-.61 1.176-.807 1.82-.63l1.102.302c.067.019.177.011.3-.071.214-.143.437-.272.668-.386.133-.066.194-.158.211-.224l.29-1.106C6.009.645 6.556.095 7.299.03 7.53.01 7.764 0 8 0Zm-.571 1.525c-.036.003-.108.036-.137.146l-.289 1.105c-.147.561-.549.967-.998 1.189-.173.086-.34.183-.5.29-.417.278-.97.423-1.529.27l-1.103-.303c-.109-.03-.175.016-.195.045-.22.312-.412.644-.573.99-.014.031-.021.11.059.19l.815.806c.411.406.562.957.53 1.456a4.709 4.709 0 0 0 0 .582c.032.499-.119 1.05-.53 1.456l-.815.806c-.081.08-.073.159-.059.19.162.346.353.677.573.989.02.03.085.076.195.046l1.102-.303c.56-.153 1.113-.008 1.53.27.161.107.328.204.501.29.447.222.85.629.997 1.189l.289 1.105c.029.109.101.143.137.146a6.6 6.6 0 0 0 1.142 0c.036-.003.108-.036.137-.146l.289-1.105c.147-.561.549-.967.998-1.189.173-.086.34-.183.5-.29.417-.278.97-.423 1.529-.27l1.103.303c.109.029.175-.016.195-.045.22-.313.411-.644.573-.99.014-.031.021-.11-.059-.19l-.815-.806c-.411-.406-.562-.957-.53-1.456a4.709 4.709 0 0 0 0-.582c-.032-.499.119-1.05.53-1.456l.815-.806c.081-.08.073-.159.059-.19a6.464 6.464 0 0 0-.573-.989c-.02-.03-.085-.076-.195-.046l-1.102.303c-.56.153-1.113.008-1.53-.27a4.44 4.44 0 0 0-.501-.29c-.447-.222-.85-.629-.997-1.189l-.289-1.105c-.029-.11-.101-.143-.137-.146a6.6 6.6 0 0 0-1.142 0ZM11 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM9.5 8a1.5 1.5 0 1 0-3.001.001A1.5 1.5 0 0 0 9.5 8Z"></path> </svg> - `Website` - `Use your GitHub Pages Website`
|
||||
|
||||
Edit a file under `Code` - `book` - A file of your choice - `Edit in place`, in the example below `book/intro.md` is edited:
|
||||
```{figure} figures/use_github_pages_website.png
|
||||
:name: github_pages_as_website
|
||||
```
|
||||
|
||||

|
||||
4. Wait a few minutes for the website to be deployed, if you're curious, have a look at the progress under <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play UnderlineNav-octicon d-none d-sm-inline"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path></svg>`Actions` - `All workflows`:
|
||||
|
||||
Make your edit and `Commit changes` to `main` branch:
|
||||
|
||||

|
||||

|
||||
|
||||
Wait a few minutes for the website to be deployed, if you're curious, have a look at the progress under `Actions` - `All wokflows`:
|
||||
|
||||

|
||||
|
||||
When the workflow has finished, visit your build book at `https://<username>.github.io/<repository_name>` (case sensitive). For our example it is: [https://dummystudent-Tom.github.io/My_own_book](https://dummystudent-Tom.github.io/My_own_book) :
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
It is possible to have multiple versions of a book published at once, by creating another Git branch (e.g. `draft` or `dev`).
|
||||
For each branch, the respective book is published at `https://<username>.github.io/<bookname>/<branchname>`.
|
||||
Technical note: for convenience, just `.../<bookname>/` redirects to `.../<bookname>/book/`, which is itself an alias (a symlink) for
|
||||
`.../<bookname>/main/`.
|
||||
```{figure} figures/action.png
|
||||
:name: action
|
||||
```
|
||||
5. When the workflow has finished, visit your build book at `https://<username>.github.io/<repository_name>` (case sensitive). For our example it is [https://dummydocent.github.io/test_book_from_template/](https://dummydocent.github.io/test_book_from_template/) for the shown repository.
|
||||
|
||||
To learn more about how we do this, please see the [GitHub Actions documentation](https://docs.github.com/en/actions) and our deployment pipeline configuration file `.github/workflows/deploy-book-ghpages.yml` [here](https://github.com/TeachBooks/template/blob/main/.github/workflows/deploy-book-ghpages.yml).
|
||||
|
||||
````
|
||||
|
||||
````{tab-item} GitLab template
|
||||
Will follow
|
||||
````
|
||||
`````
|
||||
|
||||
Now that you have your book, you can continue editing your book as described in the other chapters in this book
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# Workflows
|
||||
|
||||
- what does the publish branch do?
|
||||
- what is a pipeline
|
||||
|
||||
This coming page suggests a workflow how to collaborate using Git! Every team might have a different workflows but this workflow is shown as an example and is used in the MUDE course in CEG and by the TeachBooks team.<br>
|
||||
|
||||
There are two web-based platforms that host Git repositories: GitLab and GitHub. You might have read about GitHub Desktop that we are using to manage local repositories. GitLab and GitHub have similar features and are both widely used by the open source community. The main difference that is relevant for TeachBooks is that GitHub allows to host websites online without a server whereas GitLab needs a server. TU Delft has their own server which is why we use `tudelft.gitlab.nl`.
|
||||
|
||||
Now that you understand how to collaborate in git it is time to get started on your own book. The end of this chapter provides a [tutorial](githubtemplate.md) on how to fork our template book. By forking you are essentially creating an independent copy of the template repository in your own GitLab or GitHub account.
|
||||