├── .devcontainer └── devcontainer.json ├── .gitignore ├── JavaScript ├── index.html ├── index.js └── style.css ├── LICENSE.md ├── README.md ├── _quarto.yml ├── cover.png ├── docker ├── Dockerfile ├── build_docker.sh └── install_dependencies.sh ├── docs ├── images │ ├── script_tag_hello_world.gif │ ├── vscode_container.gif │ ├── vscode_html_template.gif │ └── vscode_live_server.gif ├── index.html ├── references.html ├── settings.html └── site_libs │ ├── bootstrap │ ├── bootstrap-icons.css │ ├── bootstrap-icons.woff │ ├── bootstrap.min.css │ └── bootstrap.min.js │ ├── clipboard │ └── clipboard.min.js │ ├── quarto-html │ ├── anchor.min.js │ ├── popper.min.js │ ├── quarto-syntax-highlighting.css │ ├── quarto.js │ ├── tippy.css │ └── tippy.umd.min.js │ ├── quarto-nav │ ├── headroom.min.js │ └── quarto-nav.js │ └── quarto-search │ ├── autocomplete.umd.js │ ├── fuse.min.js │ └── quarto-search.js ├── images ├── script_tag_hello_world.gif ├── script_tag_hello_world.mov ├── vscode_container.gif ├── vscode_container.mov ├── vscode_html_template.gif ├── vscode_html_template.mov ├── vscode_live_server.gif └── vscode_live_server.mov ├── index.log ├── index.qmd ├── index.tex ├── references.bib ├── references.qmd ├── settings.qmd ├── summary.qmd └── tutorials.Rproj /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tutorials", 3 | "image": "docker.io/rkrispin/tutorial:dev.0.0.0.9000", 4 | "customizations": { 5 | "vscode": { 6 | "settings": { 7 | "python.defaultInterpreterPath": "/opt/conda/envs/tutorial/bin/python" 8 | }, 9 | "extensions": [ 10 | "quarto.quarto", 11 | "ms-azuretools.vscode-docker", 12 | "ms-toolsai.jupyter", 13 | "bierner.markdown-mermaid", 14 | "ms-python.python", 15 | "rdebugger.r-debugger", 16 | "ms-vscode-remote.remote-containers", 17 | "yzhang.markdown-all-in-one", 18 | "reditorsupport.r", 19 | "redhat.vscode-yaml", 20 | "REditorSupport.r", 21 | "REditorSupport.r-lsp", 22 | "RDebugger.r-debugger", 23 | "purocean.drawio-preview", 24 | "aykutsarac.jsoncrack-vscode", 25 | "ritwickdey.liveserver" 26 | ] 27 | } 28 | }, 29 | "remoteEnv": { 30 | "DISABLE_AUTH": "true" 31 | }, 32 | "postCreateCommand": "radian" 33 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.quarto/ 2 | .Rproj.user 3 | -------------------------------------------------------------------------------- /JavaScript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Introduction to JS 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /JavaScript/index.js: -------------------------------------------------------------------------------- 1 | window.alert("Hello World!") -------------------------------------------------------------------------------- /JavaScript/style.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic); 2 | @import url(https://fonts.googleapis.com/css?family=Roboto+Condensed); 3 | @import url(https://fonts.googleapis.com/css?family=Roboto+Mono); 4 | 5 | body { 6 | font-family: 'Lato', Arial, sans-serif; 7 | font-size: 26px; 8 | } 9 | h1, h2, h3, h4 { 10 | font-family: 'Roboto Condensed', 'Arial Narrow OS', Arial, sans-serif; 11 | font-weight: normal; 12 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivs 4.0 United States License. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-nd/4.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Introduction to JavaScript 2 | 3 | This tutorial covers the basic functionality operations of the JavaScript (JS) language, covering the following topics: 4 | 5 | * Setting VScode environment 6 | * Basic workflow 7 | * Variables 8 | * Functions 9 | * Data structure 10 | 11 | ### Prerequisites 12 | 13 | Here are the assumptions I made when I created this tutorial: 14 | 15 | * No previous knowledge of JS 16 | * Have basic knowledge of another programming language (e.g., Python, R, Julia, etc.), and an understanding of the use of variables assignment and functions 17 | 18 | In addition, we will use some basic HTML and CSS throughout the tutorial, don’t worry if you are unfamiliar with those languages. 19 | 20 | 21 | ## License 22 | 23 | This book is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/) License. -------------------------------------------------------------------------------- /_quarto.yml: -------------------------------------------------------------------------------- 1 | project: 2 | type: book 3 | output-dir: docs 4 | 5 | book: 6 | title: "Introduction to JavaScript" 7 | author: "Rami Krispin" 8 | date: "01/01/2023" 9 | chapters: 10 | - index.qmd 11 | - settings.qmd 12 | - references.qmd 13 | 14 | bibliography: references.bib 15 | 16 | format: 17 | html: 18 | theme: cosmo 19 | pdf: 20 | documentclass: scrreprt 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/cover.png -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | # Setting environment variables 4 | ARG CONDA_ENV=atsaf 5 | ENV CONDA_ENV=$CONDA_ENV 6 | 7 | ARG PYTHON_VER=3.10 8 | ENV PYTHON_VER=$PYTHON_VER 9 | 10 | ARG QUARTO_VERSION=1.2.269 11 | ENV QUARTO_VERSION=$QUARTO_VERSION 12 | # R settings 13 | ENV R_VERSION_MAJOR=4 14 | ENV R_VERSION_MINOR=2 15 | ENV R_VERSION_PATCH=2 16 | ENV CONFIGURE_OPTIONS="--with-readline=no --with-x=no --with-cairo --with-jpeglib --enable-R-shlib --with-blas --with-lapack" 17 | ENV RENV_VERSION 0.9.3 18 | 19 | ENV LANG="en_US.UTF-8" 20 | ENV LC_COLLATE="en_US.UTF-8" 21 | ENV LC_CTYPE="en_US.UTF-8" 22 | ENV LC_MESSAGES="en_US.UTF-8" 23 | ENV LC_MONETARY="en_US.UTF-8" 24 | ENV LC_NUMERIC="en_US.UTF-8" 25 | ENV LC_TIME="en_US.UTF-8" 26 | ENV LC_ALL="en_US.UTF-8" 27 | 28 | ARG DEBIAN_FRONTEND=noninteractive 29 | ENV TZ=UTC 30 | # Installing dependencies 31 | RUN mkdir packages 32 | COPY install_dependencies.sh packages/ 33 | RUN bash packages/install_dependencies.sh $R_VERSION_MAJOR $R_VERSION_MINOR $R_VERSION_PATCH $QUARTO_VERSION $CONFIGURE_OPTIONS -------------------------------------------------------------------------------- /docker/build_docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Build the docker" 4 | 5 | docker build . --progress=plain \ 6 | --build-arg CONDA_ENV=tutorial \ 7 | --build-arg QUARTO_VERSION=1.2.269 \ 8 | --build-arg PYTHON_VER=3.10 \ 9 | -t rkrispin/tutorial:dev.0.0.0.9000 10 | 11 | if [[ $? = 0 ]] ; then 12 | echo "Pushing docker..." 13 | docker push rkrispin/tutorial:dev.0.0.0.9000 14 | else 15 | echo "Docker build failed" 16 | fi -------------------------------------------------------------------------------- /docker/install_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Envrionment variables 4 | R_VERSION_MAJOR=$1 5 | R_VERSION_MINOR=$2 6 | R_VERSION_PATCH=$3 7 | QUARTO_VERSION=$4 8 | CONFIGURE_OPTIONS=$5 9 | # Install dependencies 10 | apt-get update && apt-get install -y --no-install-recommends \ 11 | apt-utils\ 12 | gfortran \ 13 | git \ 14 | g++ \ 15 | libreadline-dev \ 16 | libx11-dev \ 17 | libxt-dev \ 18 | libpng-dev \ 19 | libjpeg-dev \ 20 | libcairo2-dev \ 21 | libcurl4-openssl-dev \ 22 | libssl-dev \ 23 | libxml2-dev \ 24 | libudunits2-dev \ 25 | libgdal-dev \ 26 | libbz2-dev \ 27 | libzstd-dev \ 28 | liblzma-dev \ 29 | libpcre2-dev \ 30 | locales \ 31 | openjdk-8-jdk \ 32 | screen \ 33 | texinfo \ 34 | texlive \ 35 | texlive-fonts-extra \ 36 | wget \ 37 | xvfb \ 38 | tzdata \ 39 | jq\ 40 | zlib1g \ 41 | g++-11 \ 42 | libz-dev \ 43 | freetype2-demos \ 44 | libtiff-dev \ 45 | make \ 46 | fontconfig \ 47 | libfribidi-dev \ 48 | libharfbuzz-dev \ 49 | libfontconfig1-dev \ 50 | vim \ 51 | curl \ 52 | nodejs \ 53 | npm \ 54 | sudo \ 55 | texlive-latex-extra \ 56 | build-essential \ 57 | gfortran \ 58 | libbz2-dev \ 59 | texlive-xetex \ 60 | lmodern \ 61 | && rm -rf /var/lib/apt/lists/* 62 | 63 | # Installing R 64 | wget https://cran.rstudio.com/src/base/R-${R_VERSION_MAJOR}/R-${R_VERSION_MAJOR}.${R_VERSION_MINOR}.${R_VERSION_PATCH}.tar.gz && \ 65 | tar zxvf R-${R_VERSION_MAJOR}.${R_VERSION_MINOR}.${R_VERSION_PATCH}.tar.gz && \ 66 | rm R-${R_VERSION_MAJOR}.${R_VERSION_MINOR}.${R_VERSION_PATCH}.tar.gz 67 | 68 | cd /R-${R_VERSION_MAJOR}.${R_VERSION_MINOR}.${R_VERSION_PATCH} 69 | 70 | ./configure ${CONFIGURE_OPTIONS} && \ 71 | make && \ 72 | make install 73 | 74 | # Installing Quarto 75 | TEMP_QUARTO="$(mktemp)" && 76 | wget -O "$TEMP_QUARTO" https://github.com/quarto-dev/quarto-cli/releases/download/v$QUARTO_VERSION/quarto-${QUARTO_VERSION}-linux-amd64.deb && 77 | sudo dpkg -i "$TEMP_QUARTO" 78 | rm -f "$TEMP_QUARTO" 79 | 80 | 81 | 82 | 83 | # Install miniconda 84 | sudo apt update && apt-get install -y --no-install-recommends \ 85 | software-properties-common \ 86 | && sudo add-apt-repository -y ppa:deadsnakes/ppa \ 87 | && sudo apt update 88 | 89 | wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh \ 90 | && /bin/bash ~/miniconda.sh -b -p /opt/conda \ 91 | && export PATH=/opt/conda/bin:$PATH \ 92 | && conda init bash \ 93 | && conda install conda-build 94 | 95 | # Set environment 96 | . /root/.bashrc \ 97 | && conda create -y --name $CONDA_ENV python=$PYTHON_VER 98 | 99 | echo "conda activate $CONDA_ENV" >> ~/.bashrc 100 | -------------------------------------------------------------------------------- /docs/images/script_tag_hello_world.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/docs/images/script_tag_hello_world.gif -------------------------------------------------------------------------------- /docs/images/vscode_container.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/docs/images/vscode_container.gif -------------------------------------------------------------------------------- /docs/images/vscode_html_template.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/docs/images/vscode_html_template.gif -------------------------------------------------------------------------------- /docs/images/vscode_live_server.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/docs/images/vscode_live_server.gif -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Introduction to JavaScript 13 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
71 |
72 | 80 |
81 | 82 |
83 | 84 | 115 | 116 | 128 | 129 |
130 | 131 |
132 |
133 |

Introduction to JavaScript

134 |
135 | 136 | 137 | 138 |
139 | 140 |
141 |
Author
142 |
143 |

Rami Krispin

144 |
145 |
146 | 147 |
148 |
Published
149 |
150 |

January 1, 2023

151 |
152 |
153 | 154 | 155 |
156 | 157 | 158 |
159 | 160 |
161 |

Preface

162 |

WIP…pre spelling check

163 |

This tutorial covers the basic functionality operations of the JavaScript (JS) language, covering the following topics:

164 |
    165 |
  • Setting VScode environment
  • 166 |
  • Basic workflow
  • 167 |
  • Variables
  • 168 |
  • Functions
  • 169 |
  • Data structure
  • 170 |
171 |
172 |

Prerequisites

173 |

Here are the assumptions I made when I created this tutorial:

174 |
    175 |
  • No previous knowledge of JS
  • 176 |
  • Have basic knowledge of another programming language (e.g., Python, R, Julia, etc.), and an understanding of the use of variables assignment and functions
  • 177 |
178 |

In addition, we will use some basic HTML and CSS throughout the tutorial, don’t worry if you are unfamiliar with those languages.

179 | 180 | 181 |
182 |
183 | 184 |
185 | 318 | 327 |
328 | 329 | 330 | 331 | -------------------------------------------------------------------------------- /docs/references.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Introduction to JavaScript - References 11 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
88 |
89 | 97 |
98 | 99 |
100 | 101 | 132 | 133 | 136 | 137 |
138 | 139 |
140 |
141 |

References

142 |
143 | 144 | 145 | 146 |
147 | 148 | 149 | 150 | 151 |
152 | 153 | 154 |
155 | 156 |
157 | 158 |
159 | 160 | 161 | 162 |
163 | 296 | 305 |
306 | 307 | 308 | 309 | -------------------------------------------------------------------------------- /docs/site_libs/bootstrap/bootstrap-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/docs/site_libs/bootstrap/bootstrap-icons.woff -------------------------------------------------------------------------------- /docs/site_libs/clipboard/clipboard.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * clipboard.js v2.0.10 3 | * https://clipboardjs.com/ 4 | * 5 | * Licensed MIT © Zeno Rocha 6 | */ 7 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1.anchorjs-link,.anchorjs-link:focus{opacity:1}",u.sheet.cssRules.length),u.sheet.insertRule("[data-anchorjs-icon]::after{content:attr(data-anchorjs-icon)}",u.sheet.cssRules.length),u.sheet.insertRule('@font-face{font-family:anchorjs-icons;src:url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype")}',u.sheet.cssRules.length)),u=document.querySelectorAll("[id]"),t=[].map.call(u,function(A){return A.id}),i=0;i\]./()*\\\n\t\b\v\u00A0]/g,"-").replace(/-{2,}/g,"-").substring(0,this.options.truncate).replace(/^-+|-+$/gm,"").toLowerCase()},this.hasAnchorJSLink=function(A){var e=A.firstChild&&-1<(" "+A.firstChild.className+" ").indexOf(" anchorjs-link "),A=A.lastChild&&-1<(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ");return e||A||!1}}}); 9 | // @license-end -------------------------------------------------------------------------------- /docs/site_libs/quarto-html/popper.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @popperjs/core v2.11.4 - MIT License 3 | */ 4 | 5 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Popper={})}(this,(function(e){"use strict";function t(e){if(null==e)return window;if("[object Window]"!==e.toString()){var t=e.ownerDocument;return t&&t.defaultView||window}return e}function n(e){return e instanceof t(e).Element||e instanceof Element}function r(e){return e instanceof t(e).HTMLElement||e instanceof HTMLElement}function o(e){return"undefined"!=typeof ShadowRoot&&(e instanceof t(e).ShadowRoot||e instanceof ShadowRoot)}var i=Math.max,a=Math.min,s=Math.round;function f(e,t){void 0===t&&(t=!1);var n=e.getBoundingClientRect(),o=1,i=1;if(r(e)&&t){var a=e.offsetHeight,f=e.offsetWidth;f>0&&(o=s(n.width)/f||1),a>0&&(i=s(n.height)/a||1)}return{width:n.width/o,height:n.height/i,top:n.top/i,right:n.right/o,bottom:n.bottom/i,left:n.left/o,x:n.left/o,y:n.top/i}}function c(e){var n=t(e);return{scrollLeft:n.pageXOffset,scrollTop:n.pageYOffset}}function p(e){return e?(e.nodeName||"").toLowerCase():null}function u(e){return((n(e)?e.ownerDocument:e.document)||window.document).documentElement}function l(e){return f(u(e)).left+c(e).scrollLeft}function d(e){return t(e).getComputedStyle(e)}function h(e){var t=d(e),n=t.overflow,r=t.overflowX,o=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+r)}function m(e,n,o){void 0===o&&(o=!1);var i,a,d=r(n),m=r(n)&&function(e){var t=e.getBoundingClientRect(),n=s(t.width)/e.offsetWidth||1,r=s(t.height)/e.offsetHeight||1;return 1!==n||1!==r}(n),v=u(n),g=f(e,m),y={scrollLeft:0,scrollTop:0},b={x:0,y:0};return(d||!d&&!o)&&(("body"!==p(n)||h(v))&&(y=(i=n)!==t(i)&&r(i)?{scrollLeft:(a=i).scrollLeft,scrollTop:a.scrollTop}:c(i)),r(n)?((b=f(n,!0)).x+=n.clientLeft,b.y+=n.clientTop):v&&(b.x=l(v))),{x:g.left+y.scrollLeft-b.x,y:g.top+y.scrollTop-b.y,width:g.width,height:g.height}}function v(e){var t=f(e),n=e.offsetWidth,r=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:r}}function g(e){return"html"===p(e)?e:e.assignedSlot||e.parentNode||(o(e)?e.host:null)||u(e)}function y(e){return["html","body","#document"].indexOf(p(e))>=0?e.ownerDocument.body:r(e)&&h(e)?e:y(g(e))}function b(e,n){var r;void 0===n&&(n=[]);var o=y(e),i=o===(null==(r=e.ownerDocument)?void 0:r.body),a=t(o),s=i?[a].concat(a.visualViewport||[],h(o)?o:[]):o,f=n.concat(s);return i?f:f.concat(b(g(s)))}function x(e){return["table","td","th"].indexOf(p(e))>=0}function w(e){return r(e)&&"fixed"!==d(e).position?e.offsetParent:null}function O(e){for(var n=t(e),i=w(e);i&&x(i)&&"static"===d(i).position;)i=w(i);return i&&("html"===p(i)||"body"===p(i)&&"static"===d(i).position)?n:i||function(e){var t=-1!==navigator.userAgent.toLowerCase().indexOf("firefox");if(-1!==navigator.userAgent.indexOf("Trident")&&r(e)&&"fixed"===d(e).position)return null;var n=g(e);for(o(n)&&(n=n.host);r(n)&&["html","body"].indexOf(p(n))<0;){var i=d(n);if("none"!==i.transform||"none"!==i.perspective||"paint"===i.contain||-1!==["transform","perspective"].indexOf(i.willChange)||t&&"filter"===i.willChange||t&&i.filter&&"none"!==i.filter)return n;n=n.parentNode}return null}(e)||n}var j="top",E="bottom",D="right",A="left",L="auto",P=[j,E,D,A],M="start",k="end",W="viewport",B="popper",H=P.reduce((function(e,t){return e.concat([t+"-"+M,t+"-"+k])}),[]),T=[].concat(P,[L]).reduce((function(e,t){return e.concat([t,t+"-"+M,t+"-"+k])}),[]),R=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"];function S(e){var t=new Map,n=new Set,r=[];function o(e){n.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!n.has(e)){var r=t.get(e);r&&o(r)}})),r.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||o(e)})),r}function C(e){return e.split("-")[0]}function q(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&o(n)){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function V(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function N(e,r){return r===W?V(function(e){var n=t(e),r=u(e),o=n.visualViewport,i=r.clientWidth,a=r.clientHeight,s=0,f=0;return o&&(i=o.width,a=o.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(s=o.offsetLeft,f=o.offsetTop)),{width:i,height:a,x:s+l(e),y:f}}(e)):n(r)?function(e){var t=f(e);return t.top=t.top+e.clientTop,t.left=t.left+e.clientLeft,t.bottom=t.top+e.clientHeight,t.right=t.left+e.clientWidth,t.width=e.clientWidth,t.height=e.clientHeight,t.x=t.left,t.y=t.top,t}(r):V(function(e){var t,n=u(e),r=c(e),o=null==(t=e.ownerDocument)?void 0:t.body,a=i(n.scrollWidth,n.clientWidth,o?o.scrollWidth:0,o?o.clientWidth:0),s=i(n.scrollHeight,n.clientHeight,o?o.scrollHeight:0,o?o.clientHeight:0),f=-r.scrollLeft+l(e),p=-r.scrollTop;return"rtl"===d(o||n).direction&&(f+=i(n.clientWidth,o?o.clientWidth:0)-a),{width:a,height:s,x:f,y:p}}(u(e)))}function I(e,t,o){var s="clippingParents"===t?function(e){var t=b(g(e)),o=["absolute","fixed"].indexOf(d(e).position)>=0&&r(e)?O(e):e;return n(o)?t.filter((function(e){return n(e)&&q(e,o)&&"body"!==p(e)})):[]}(e):[].concat(t),f=[].concat(s,[o]),c=f[0],u=f.reduce((function(t,n){var r=N(e,n);return t.top=i(r.top,t.top),t.right=a(r.right,t.right),t.bottom=a(r.bottom,t.bottom),t.left=i(r.left,t.left),t}),N(e,c));return u.width=u.right-u.left,u.height=u.bottom-u.top,u.x=u.left,u.y=u.top,u}function _(e){return e.split("-")[1]}function F(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function U(e){var t,n=e.reference,r=e.element,o=e.placement,i=o?C(o):null,a=o?_(o):null,s=n.x+n.width/2-r.width/2,f=n.y+n.height/2-r.height/2;switch(i){case j:t={x:s,y:n.y-r.height};break;case E:t={x:s,y:n.y+n.height};break;case D:t={x:n.x+n.width,y:f};break;case A:t={x:n.x-r.width,y:f};break;default:t={x:n.x,y:n.y}}var c=i?F(i):null;if(null!=c){var p="y"===c?"height":"width";switch(a){case M:t[c]=t[c]-(n[p]/2-r[p]/2);break;case k:t[c]=t[c]+(n[p]/2-r[p]/2)}}return t}function z(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function X(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function Y(e,t){void 0===t&&(t={});var r=t,o=r.placement,i=void 0===o?e.placement:o,a=r.boundary,s=void 0===a?"clippingParents":a,c=r.rootBoundary,p=void 0===c?W:c,l=r.elementContext,d=void 0===l?B:l,h=r.altBoundary,m=void 0!==h&&h,v=r.padding,g=void 0===v?0:v,y=z("number"!=typeof g?g:X(g,P)),b=d===B?"reference":B,x=e.rects.popper,w=e.elements[m?b:d],O=I(n(w)?w:w.contextElement||u(e.elements.popper),s,p),A=f(e.elements.reference),L=U({reference:A,element:x,strategy:"absolute",placement:i}),M=V(Object.assign({},x,L)),k=d===B?M:A,H={top:O.top-k.top+y.top,bottom:k.bottom-O.bottom+y.bottom,left:O.left-k.left+y.left,right:k.right-O.right+y.right},T=e.modifiersData.offset;if(d===B&&T){var R=T[i];Object.keys(H).forEach((function(e){var t=[D,E].indexOf(e)>=0?1:-1,n=[j,E].indexOf(e)>=0?"y":"x";H[e]+=R[n]*t}))}return H}var G={placement:"bottom",modifiers:[],strategy:"absolute"};function J(){for(var e=arguments.length,t=new Array(e),n=0;n=0?-1:1,i="function"==typeof n?n(Object.assign({},t,{placement:e})):n,a=i[0],s=i[1];return a=a||0,s=(s||0)*o,[A,D].indexOf(r)>=0?{x:s,y:a}:{x:a,y:s}}(n,t.rects,i),e}),{}),s=a[t.placement],f=s.x,c=s.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=f,t.modifiersData.popperOffsets.y+=c),t.modifiersData[r]=a}},ie={left:"right",right:"left",bottom:"top",top:"bottom"};function ae(e){return e.replace(/left|right|bottom|top/g,(function(e){return ie[e]}))}var se={start:"end",end:"start"};function fe(e){return e.replace(/start|end/g,(function(e){return se[e]}))}function ce(e,t){void 0===t&&(t={});var n=t,r=n.placement,o=n.boundary,i=n.rootBoundary,a=n.padding,s=n.flipVariations,f=n.allowedAutoPlacements,c=void 0===f?T:f,p=_(r),u=p?s?H:H.filter((function(e){return _(e)===p})):P,l=u.filter((function(e){return c.indexOf(e)>=0}));0===l.length&&(l=u);var d=l.reduce((function(t,n){return t[n]=Y(e,{placement:n,boundary:o,rootBoundary:i,padding:a})[C(n)],t}),{});return Object.keys(d).sort((function(e,t){return d[e]-d[t]}))}var pe={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var o=n.mainAxis,i=void 0===o||o,a=n.altAxis,s=void 0===a||a,f=n.fallbackPlacements,c=n.padding,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.flipVariations,h=void 0===d||d,m=n.allowedAutoPlacements,v=t.options.placement,g=C(v),y=f||(g===v||!h?[ae(v)]:function(e){if(C(e)===L)return[];var t=ae(e);return[fe(e),t,fe(t)]}(v)),b=[v].concat(y).reduce((function(e,n){return e.concat(C(n)===L?ce(t,{placement:n,boundary:p,rootBoundary:u,padding:c,flipVariations:h,allowedAutoPlacements:m}):n)}),[]),x=t.rects.reference,w=t.rects.popper,O=new Map,P=!0,k=b[0],W=0;W=0,S=R?"width":"height",q=Y(t,{placement:B,boundary:p,rootBoundary:u,altBoundary:l,padding:c}),V=R?T?D:A:T?E:j;x[S]>w[S]&&(V=ae(V));var N=ae(V),I=[];if(i&&I.push(q[H]<=0),s&&I.push(q[V]<=0,q[N]<=0),I.every((function(e){return e}))){k=B,P=!1;break}O.set(B,I)}if(P)for(var F=function(e){var t=b.find((function(t){var n=O.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return k=t,"break"},U=h?3:1;U>0;U--){if("break"===F(U))break}t.placement!==k&&(t.modifiersData[r]._skip=!0,t.placement=k,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function ue(e,t,n){return i(e,a(t,n))}var le={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.mainAxis,s=void 0===o||o,f=n.altAxis,c=void 0!==f&&f,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.padding,h=n.tether,m=void 0===h||h,g=n.tetherOffset,y=void 0===g?0:g,b=Y(t,{boundary:p,rootBoundary:u,padding:d,altBoundary:l}),x=C(t.placement),w=_(t.placement),L=!w,P=F(x),k="x"===P?"y":"x",W=t.modifiersData.popperOffsets,B=t.rects.reference,H=t.rects.popper,T="function"==typeof y?y(Object.assign({},t.rects,{placement:t.placement})):y,R="number"==typeof T?{mainAxis:T,altAxis:T}:Object.assign({mainAxis:0,altAxis:0},T),S=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,q={x:0,y:0};if(W){if(s){var V,N="y"===P?j:A,I="y"===P?E:D,U="y"===P?"height":"width",z=W[P],X=z+b[N],G=z-b[I],J=m?-H[U]/2:0,K=w===M?B[U]:H[U],Q=w===M?-H[U]:-B[U],Z=t.elements.arrow,$=m&&Z?v(Z):{width:0,height:0},ee=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},te=ee[N],ne=ee[I],re=ue(0,B[U],$[U]),oe=L?B[U]/2-J-re-te-R.mainAxis:K-re-te-R.mainAxis,ie=L?-B[U]/2+J+re+ne+R.mainAxis:Q+re+ne+R.mainAxis,ae=t.elements.arrow&&O(t.elements.arrow),se=ae?"y"===P?ae.clientTop||0:ae.clientLeft||0:0,fe=null!=(V=null==S?void 0:S[P])?V:0,ce=z+ie-fe,pe=ue(m?a(X,z+oe-fe-se):X,z,m?i(G,ce):G);W[P]=pe,q[P]=pe-z}if(c){var le,de="x"===P?j:A,he="x"===P?E:D,me=W[k],ve="y"===k?"height":"width",ge=me+b[de],ye=me-b[he],be=-1!==[j,A].indexOf(x),xe=null!=(le=null==S?void 0:S[k])?le:0,we=be?ge:me-B[ve]-H[ve]-xe+R.altAxis,Oe=be?me+B[ve]+H[ve]-xe-R.altAxis:ye,je=m&&be?function(e,t,n){var r=ue(e,t,n);return r>n?n:r}(we,me,Oe):ue(m?we:ge,me,m?Oe:ye);W[k]=je,q[k]=je-me}t.modifiersData[r]=q}},requiresIfExists:["offset"]};var de={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state,r=e.name,o=e.options,i=n.elements.arrow,a=n.modifiersData.popperOffsets,s=C(n.placement),f=F(s),c=[A,D].indexOf(s)>=0?"height":"width";if(i&&a){var p=function(e,t){return z("number"!=typeof(e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e)?e:X(e,P))}(o.padding,n),u=v(i),l="y"===f?j:A,d="y"===f?E:D,h=n.rects.reference[c]+n.rects.reference[f]-a[f]-n.rects.popper[c],m=a[f]-n.rects.reference[f],g=O(i),y=g?"y"===f?g.clientHeight||0:g.clientWidth||0:0,b=h/2-m/2,x=p[l],w=y-u[c]-p[d],L=y/2-u[c]/2+b,M=ue(x,L,w),k=f;n.modifiersData[r]=((t={})[k]=M,t.centerOffset=M-L,t)}},effect:function(e){var t=e.state,n=e.options.element,r=void 0===n?"[data-popper-arrow]":n;null!=r&&("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&q(t.elements.popper,r)&&(t.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function he(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function me(e){return[j,D,E,A].some((function(t){return e[t]>=0}))}var ve={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,n=e.name,r=t.rects.reference,o=t.rects.popper,i=t.modifiersData.preventOverflow,a=Y(t,{elementContext:"reference"}),s=Y(t,{altBoundary:!0}),f=he(a,r),c=he(s,o,i),p=me(f),u=me(c);t.modifiersData[n]={referenceClippingOffsets:f,popperEscapeOffsets:c,isReferenceHidden:p,hasPopperEscaped:u},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":p,"data-popper-escaped":u})}},ge=K({defaultModifiers:[Z,$,ne,re]}),ye=[Z,$,ne,re,oe,pe,le,de,ve],be=K({defaultModifiers:ye});e.applyStyles=re,e.arrow=de,e.computeStyles=ne,e.createPopper=be,e.createPopperLite=ge,e.defaultModifiers=ye,e.detectOverflow=Y,e.eventListeners=Z,e.flip=pe,e.hide=ve,e.offset=oe,e.popperGenerator=K,e.popperOffsets=$,e.preventOverflow=le,Object.defineProperty(e,"__esModule",{value:!0})})); 6 | 7 | -------------------------------------------------------------------------------- /docs/site_libs/quarto-html/quarto-syntax-highlighting.css: -------------------------------------------------------------------------------- 1 | /* quarto syntax highlight colors */ 2 | :root { 3 | --quarto-hl-ot-color: #003B4F; 4 | --quarto-hl-at-color: #657422; 5 | --quarto-hl-ss-color: #20794D; 6 | --quarto-hl-an-color: #5E5E5E; 7 | --quarto-hl-fu-color: #4758AB; 8 | --quarto-hl-st-color: #20794D; 9 | --quarto-hl-cf-color: #003B4F; 10 | --quarto-hl-op-color: #5E5E5E; 11 | --quarto-hl-er-color: #AD0000; 12 | --quarto-hl-bn-color: #AD0000; 13 | --quarto-hl-al-color: #AD0000; 14 | --quarto-hl-va-color: #111111; 15 | --quarto-hl-bu-color: inherit; 16 | --quarto-hl-ex-color: inherit; 17 | --quarto-hl-pp-color: #AD0000; 18 | --quarto-hl-in-color: #5E5E5E; 19 | --quarto-hl-vs-color: #20794D; 20 | --quarto-hl-wa-color: #5E5E5E; 21 | --quarto-hl-do-color: #5E5E5E; 22 | --quarto-hl-im-color: #00769E; 23 | --quarto-hl-ch-color: #20794D; 24 | --quarto-hl-dt-color: #AD0000; 25 | --quarto-hl-fl-color: #AD0000; 26 | --quarto-hl-co-color: #5E5E5E; 27 | --quarto-hl-cv-color: #5E5E5E; 28 | --quarto-hl-cn-color: #8f5902; 29 | --quarto-hl-sc-color: #5E5E5E; 30 | --quarto-hl-dv-color: #AD0000; 31 | --quarto-hl-kw-color: #003B4F; 32 | } 33 | 34 | /* other quarto variables */ 35 | :root { 36 | --quarto-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 37 | } 38 | 39 | pre > code.sourceCode > span { 40 | color: #003B4F; 41 | } 42 | 43 | code span { 44 | color: #003B4F; 45 | } 46 | 47 | code.sourceCode > span { 48 | color: #003B4F; 49 | } 50 | 51 | div.sourceCode, 52 | div.sourceCode pre.sourceCode { 53 | color: #003B4F; 54 | } 55 | 56 | code span.ot { 57 | color: #003B4F; 58 | } 59 | 60 | code span.at { 61 | color: #657422; 62 | } 63 | 64 | code span.ss { 65 | color: #20794D; 66 | } 67 | 68 | code span.an { 69 | color: #5E5E5E; 70 | } 71 | 72 | code span.fu { 73 | color: #4758AB; 74 | } 75 | 76 | code span.st { 77 | color: #20794D; 78 | } 79 | 80 | code span.cf { 81 | color: #003B4F; 82 | } 83 | 84 | code span.op { 85 | color: #5E5E5E; 86 | } 87 | 88 | code span.er { 89 | color: #AD0000; 90 | } 91 | 92 | code span.bn { 93 | color: #AD0000; 94 | } 95 | 96 | code span.al { 97 | color: #AD0000; 98 | } 99 | 100 | code span.va { 101 | color: #111111; 102 | } 103 | 104 | code span.pp { 105 | color: #AD0000; 106 | } 107 | 108 | code span.in { 109 | color: #5E5E5E; 110 | } 111 | 112 | code span.vs { 113 | color: #20794D; 114 | } 115 | 116 | code span.wa { 117 | color: #5E5E5E; 118 | font-style: italic; 119 | } 120 | 121 | code span.do { 122 | color: #5E5E5E; 123 | font-style: italic; 124 | } 125 | 126 | code span.im { 127 | color: #00769E; 128 | } 129 | 130 | code span.ch { 131 | color: #20794D; 132 | } 133 | 134 | code span.dt { 135 | color: #AD0000; 136 | } 137 | 138 | code span.fl { 139 | color: #AD0000; 140 | } 141 | 142 | code span.co { 143 | color: #5E5E5E; 144 | } 145 | 146 | code span.cv { 147 | color: #5E5E5E; 148 | font-style: italic; 149 | } 150 | 151 | code span.cn { 152 | color: #8f5902; 153 | } 154 | 155 | code span.sc { 156 | color: #5E5E5E; 157 | } 158 | 159 | code span.dv { 160 | color: #AD0000; 161 | } 162 | 163 | code span.kw { 164 | color: #003B4F; 165 | } 166 | 167 | .prevent-inlining { 168 | content: " { 17 | const sibling = el.previousElementSibling; 18 | if (sibling && sibling.tagName === "A") { 19 | return sibling.classList.contains("active"); 20 | } else { 21 | return false; 22 | } 23 | }; 24 | 25 | // fire slideEnter for bootstrap tab activations (for htmlwidget resize behavior) 26 | function fireSlideEnter(e) { 27 | const event = window.document.createEvent("Event"); 28 | event.initEvent("slideenter", true, true); 29 | window.document.dispatchEvent(event); 30 | } 31 | const tabs = window.document.querySelectorAll('a[data-bs-toggle="tab"]'); 32 | tabs.forEach((tab) => { 33 | tab.addEventListener("shown.bs.tab", fireSlideEnter); 34 | }); 35 | 36 | // fire slideEnter for tabby tab activations (for htmlwidget resize behavior) 37 | document.addEventListener("tabby", fireSlideEnter, false); 38 | 39 | // Track scrolling and mark TOC links as active 40 | // get table of contents and sidebar (bail if we don't have at least one) 41 | const tocLinks = tocEl 42 | ? [...tocEl.querySelectorAll("a[data-scroll-target]")] 43 | : []; 44 | const makeActive = (link) => tocLinks[link].classList.add("active"); 45 | const removeActive = (link) => tocLinks[link].classList.remove("active"); 46 | const removeAllActive = () => 47 | [...Array(tocLinks.length).keys()].forEach((link) => removeActive(link)); 48 | 49 | // activate the anchor for a section associated with this TOC entry 50 | tocLinks.forEach((link) => { 51 | link.addEventListener("click", () => { 52 | if (link.href.indexOf("#") !== -1) { 53 | const anchor = link.href.split("#")[1]; 54 | const heading = window.document.querySelector( 55 | `[data-anchor-id=${anchor}]` 56 | ); 57 | if (heading) { 58 | // Add the class 59 | heading.classList.add("reveal-anchorjs-link"); 60 | 61 | // function to show the anchor 62 | const handleMouseout = () => { 63 | heading.classList.remove("reveal-anchorjs-link"); 64 | heading.removeEventListener("mouseout", handleMouseout); 65 | }; 66 | 67 | // add a function to clear the anchor when the user mouses out of it 68 | heading.addEventListener("mouseout", handleMouseout); 69 | } 70 | } 71 | }); 72 | }); 73 | 74 | const sections = tocLinks.map((link) => { 75 | const target = link.getAttribute("data-scroll-target"); 76 | if (target.startsWith("#")) { 77 | return window.document.getElementById(decodeURI(`${target.slice(1)}`)); 78 | } else { 79 | return window.document.querySelector(decodeURI(`${target}`)); 80 | } 81 | }); 82 | 83 | const sectionMargin = 200; 84 | let currentActive = 0; 85 | // track whether we've initialized state the first time 86 | let init = false; 87 | 88 | const updateActiveLink = () => { 89 | // The index from bottom to top (e.g. reversed list) 90 | let sectionIndex = -1; 91 | if ( 92 | window.innerHeight + window.pageYOffset >= 93 | window.document.body.offsetHeight 94 | ) { 95 | sectionIndex = 0; 96 | } else { 97 | sectionIndex = [...sections].reverse().findIndex((section) => { 98 | if (section) { 99 | return window.pageYOffset >= section.offsetTop - sectionMargin; 100 | } else { 101 | return false; 102 | } 103 | }); 104 | } 105 | if (sectionIndex > -1) { 106 | const current = sections.length - sectionIndex - 1; 107 | if (current !== currentActive) { 108 | removeAllActive(); 109 | currentActive = current; 110 | makeActive(current); 111 | if (init) { 112 | window.dispatchEvent(sectionChanged); 113 | } 114 | init = true; 115 | } 116 | } 117 | }; 118 | 119 | const inHiddenRegion = (top, bottom, hiddenRegions) => { 120 | for (const region of hiddenRegions) { 121 | if (top <= region.bottom && bottom >= region.top) { 122 | return true; 123 | } 124 | } 125 | return false; 126 | }; 127 | 128 | const categorySelector = "header.quarto-title-block .quarto-category"; 129 | const activateCategories = (href) => { 130 | // Find any categories 131 | // Surround them with a link pointing back to: 132 | // #category=Authoring 133 | try { 134 | const categoryEls = window.document.querySelectorAll(categorySelector); 135 | for (const categoryEl of categoryEls) { 136 | const categoryText = categoryEl.textContent; 137 | if (categoryText) { 138 | const link = `${href}#category=${encodeURIComponent(categoryText)}`; 139 | const linkEl = window.document.createElement("a"); 140 | linkEl.setAttribute("href", link); 141 | for (const child of categoryEl.childNodes) { 142 | linkEl.append(child); 143 | } 144 | categoryEl.appendChild(linkEl); 145 | } 146 | } 147 | } catch { 148 | // Ignore errors 149 | } 150 | }; 151 | function hasTitleCategories() { 152 | return window.document.querySelector(categorySelector) !== null; 153 | } 154 | 155 | function offsetRelativeUrl(url) { 156 | const offset = getMeta("quarto:offset"); 157 | return offset ? offset + url : url; 158 | } 159 | 160 | function offsetAbsoluteUrl(url) { 161 | const offset = getMeta("quarto:offset"); 162 | const baseUrl = new URL(offset, window.location); 163 | 164 | const projRelativeUrl = url.replace(baseUrl, ""); 165 | if (projRelativeUrl.startsWith("/")) { 166 | return projRelativeUrl; 167 | } else { 168 | return "/" + projRelativeUrl; 169 | } 170 | } 171 | 172 | // read a meta tag value 173 | function getMeta(metaName) { 174 | const metas = window.document.getElementsByTagName("meta"); 175 | for (let i = 0; i < metas.length; i++) { 176 | if (metas[i].getAttribute("name") === metaName) { 177 | return metas[i].getAttribute("content"); 178 | } 179 | } 180 | return ""; 181 | } 182 | 183 | async function findAndActivateCategories() { 184 | const currentPagePath = offsetAbsoluteUrl(window.location.href); 185 | const response = await fetch(offsetRelativeUrl("listings.json")); 186 | if (response.status == 200) { 187 | return response.json().then(function (listingPaths) { 188 | const listingHrefs = []; 189 | for (const listingPath of listingPaths) { 190 | const pathWithoutLeadingSlash = listingPath.listing.substring(1); 191 | for (const item of listingPath.items) { 192 | if ( 193 | item === currentPagePath || 194 | item === currentPagePath + "index.html" 195 | ) { 196 | // Resolve this path against the offset to be sure 197 | // we already are using the correct path to the listing 198 | // (this adjusts the listing urls to be rooted against 199 | // whatever root the page is actually running against) 200 | const relative = offsetRelativeUrl(pathWithoutLeadingSlash); 201 | const baseUrl = window.location; 202 | const resolvedPath = new URL(relative, baseUrl); 203 | listingHrefs.push(resolvedPath.pathname); 204 | break; 205 | } 206 | } 207 | } 208 | 209 | // Look up the tree for a nearby linting and use that if we find one 210 | const nearestListing = findNearestParentListing( 211 | offsetAbsoluteUrl(window.location.pathname), 212 | listingHrefs 213 | ); 214 | if (nearestListing) { 215 | activateCategories(nearestListing); 216 | } else { 217 | // See if the referrer is a listing page for this item 218 | const referredRelativePath = offsetAbsoluteUrl(document.referrer); 219 | const referrerListing = listingHrefs.find((listingHref) => { 220 | const isListingReferrer = 221 | listingHref === referredRelativePath || 222 | listingHref === referredRelativePath + "index.html"; 223 | return isListingReferrer; 224 | }); 225 | 226 | if (referrerListing) { 227 | // Try to use the referrer if possible 228 | activateCategories(referrerListing); 229 | } else if (listingHrefs.length > 0) { 230 | // Otherwise, just fall back to the first listing 231 | activateCategories(listingHrefs[0]); 232 | } 233 | } 234 | }); 235 | } 236 | } 237 | if (hasTitleCategories()) { 238 | findAndActivateCategories(); 239 | } 240 | 241 | const findNearestParentListing = (href, listingHrefs) => { 242 | if (!href || !listingHrefs) { 243 | return undefined; 244 | } 245 | // Look up the tree for a nearby linting and use that if we find one 246 | const relativeParts = href.substring(1).split("/"); 247 | while (relativeParts.length > 0) { 248 | const path = relativeParts.join("/"); 249 | for (const listingHref of listingHrefs) { 250 | if (listingHref.startsWith(path)) { 251 | return listingHref; 252 | } 253 | } 254 | relativeParts.pop(); 255 | } 256 | 257 | return undefined; 258 | }; 259 | 260 | const manageSidebarVisiblity = (el, placeholderDescriptor) => { 261 | let isVisible = true; 262 | 263 | return (hiddenRegions) => { 264 | if (el === null) { 265 | return; 266 | } 267 | 268 | // Find the last element of the TOC 269 | const lastChildEl = el.lastElementChild; 270 | 271 | if (lastChildEl) { 272 | // Find the top and bottom o the element that is being managed 273 | const elTop = el.offsetTop; 274 | const elBottom = 275 | elTop + lastChildEl.offsetTop + lastChildEl.offsetHeight; 276 | 277 | // Converts the sidebar to a menu 278 | const convertToMenu = () => { 279 | for (const child of el.children) { 280 | child.style.opacity = 0; 281 | child.style.overflow = "hidden"; 282 | } 283 | 284 | const toggleContainer = window.document.createElement("div"); 285 | toggleContainer.style.width = "100%"; 286 | toggleContainer.classList.add("zindex-over-content"); 287 | toggleContainer.classList.add("quarto-sidebar-toggle"); 288 | toggleContainer.classList.add("headroom-target"); // Marks this to be managed by headeroom 289 | toggleContainer.id = placeholderDescriptor.id; 290 | toggleContainer.style.position = "fixed"; 291 | 292 | const toggleIcon = window.document.createElement("i"); 293 | toggleIcon.classList.add("quarto-sidebar-toggle-icon"); 294 | toggleIcon.classList.add("bi"); 295 | toggleIcon.classList.add("bi-caret-down-fill"); 296 | 297 | const toggleTitle = window.document.createElement("div"); 298 | const titleEl = window.document.body.querySelector( 299 | placeholderDescriptor.titleSelector 300 | ); 301 | if (titleEl) { 302 | toggleTitle.append(titleEl.innerText, toggleIcon); 303 | } 304 | toggleTitle.classList.add("zindex-over-content"); 305 | toggleTitle.classList.add("quarto-sidebar-toggle-title"); 306 | toggleContainer.append(toggleTitle); 307 | 308 | const toggleContents = window.document.createElement("div"); 309 | toggleContents.classList = el.classList; 310 | toggleContents.classList.add("zindex-over-content"); 311 | toggleContents.classList.add("quarto-sidebar-toggle-contents"); 312 | for (const child of el.children) { 313 | if (child.id === "toc-title") { 314 | continue; 315 | } 316 | 317 | const clone = child.cloneNode(true); 318 | clone.style.opacity = 1; 319 | clone.style.display = null; 320 | toggleContents.append(clone); 321 | } 322 | toggleContents.style.height = "0px"; 323 | toggleContainer.append(toggleContents); 324 | el.parentElement.prepend(toggleContainer); 325 | 326 | // Process clicks 327 | let tocShowing = false; 328 | // Allow the caller to control whether this is dismissed 329 | // when it is clicked (e.g. sidebar navigation supports 330 | // opening and closing the nav tree, so don't dismiss on click) 331 | const clickEl = placeholderDescriptor.dismissOnClick 332 | ? toggleContainer 333 | : toggleTitle; 334 | 335 | const closeToggle = () => { 336 | if (tocShowing) { 337 | toggleContainer.classList.remove("expanded"); 338 | toggleContents.style.height = "0px"; 339 | tocShowing = false; 340 | } 341 | }; 342 | 343 | const positionToggle = () => { 344 | // position the element (top left of parent, same width as parent) 345 | const elRect = el.getBoundingClientRect(); 346 | toggleContainer.style.left = `${elRect.left}px`; 347 | toggleContainer.style.top = `${elRect.top}px`; 348 | toggleContainer.style.width = `${elRect.width}px`; 349 | }; 350 | 351 | // Get rid of any expanded toggle if the user scrolls 352 | window.document.addEventListener( 353 | "scroll", 354 | throttle(() => { 355 | closeToggle(); 356 | }, 50) 357 | ); 358 | 359 | // Handle positioning of the toggle 360 | window.addEventListener( 361 | "resize", 362 | throttle(() => { 363 | positionToggle(); 364 | }, 50) 365 | ); 366 | positionToggle(); 367 | 368 | // Process the click 369 | clickEl.onclick = () => { 370 | if (!tocShowing) { 371 | toggleContainer.classList.add("expanded"); 372 | toggleContents.style.height = null; 373 | tocShowing = true; 374 | } else { 375 | closeToggle(); 376 | } 377 | }; 378 | }; 379 | 380 | // Converts a sidebar from a menu back to a sidebar 381 | const convertToSidebar = () => { 382 | for (const child of el.children) { 383 | child.style.opacity = 1; 384 | child.style.overflow = null; 385 | } 386 | 387 | const placeholderEl = window.document.getElementById( 388 | placeholderDescriptor.id 389 | ); 390 | if (placeholderEl) { 391 | placeholderEl.remove(); 392 | } 393 | 394 | el.classList.remove("rollup"); 395 | }; 396 | 397 | if (isReaderMode()) { 398 | convertToMenu(); 399 | isVisible = false; 400 | } else { 401 | if (!isVisible) { 402 | // If the element is current not visible reveal if there are 403 | // no conflicts with overlay regions 404 | if (!inHiddenRegion(elTop, elBottom, hiddenRegions)) { 405 | convertToSidebar(); 406 | isVisible = true; 407 | } 408 | } else { 409 | // If the element is visible, hide it if it conflicts with overlay regions 410 | // and insert a placeholder toggle (or if we're in reader mode) 411 | if (inHiddenRegion(elTop, elBottom, hiddenRegions)) { 412 | convertToMenu(); 413 | isVisible = false; 414 | } 415 | } 416 | } 417 | } 418 | }; 419 | }; 420 | 421 | // Find any conflicting margin elements and add margins to the 422 | // top to prevent overlap 423 | const marginChildren = window.document.querySelectorAll( 424 | ".column-margin.column-container > * " 425 | ); 426 | 427 | nexttick(() => { 428 | let lastBottom = 0; 429 | for (const marginChild of marginChildren) { 430 | const top = marginChild.getBoundingClientRect().top + window.scrollY; 431 | if (top < lastBottom) { 432 | const margin = lastBottom - top; 433 | marginChild.style.marginTop = `${margin}px`; 434 | } 435 | const styles = window.getComputedStyle(marginChild); 436 | const marginTop = parseFloat(styles["marginTop"]); 437 | 438 | lastBottom = top + marginChild.getBoundingClientRect().height + marginTop; 439 | } 440 | }); 441 | 442 | // Manage the visibility of the toc and the sidebar 443 | const marginScrollVisibility = manageSidebarVisiblity(marginSidebarEl, { 444 | id: "quarto-toc-toggle", 445 | titleSelector: "#toc-title", 446 | dismissOnClick: true, 447 | }); 448 | const sidebarScrollVisiblity = manageSidebarVisiblity(sidebarEl, { 449 | id: "quarto-sidebarnav-toggle", 450 | titleSelector: ".title", 451 | dismissOnClick: false, 452 | }); 453 | let tocLeftScrollVisibility; 454 | if (leftTocEl) { 455 | tocLeftScrollVisibility = manageSidebarVisiblity(leftTocEl, { 456 | id: "quarto-lefttoc-toggle", 457 | titleSelector: "#toc-title", 458 | dismissOnClick: true, 459 | }); 460 | } 461 | 462 | // Find the first element that uses formatting in special columns 463 | const conflictingEls = window.document.body.querySelectorAll( 464 | '[class^="column-"], [class*=" column-"], aside, [class*="margin-caption"], [class*=" margin-caption"], [class*="margin-ref"], [class*=" margin-ref"]' 465 | ); 466 | 467 | // Filter all the possibly conflicting elements into ones 468 | // the do conflict on the left or ride side 469 | const arrConflictingEls = Array.from(conflictingEls); 470 | const leftSideConflictEls = arrConflictingEls.filter((el) => { 471 | if (el.tagName === "ASIDE") { 472 | return false; 473 | } 474 | return Array.from(el.classList).find((className) => { 475 | return ( 476 | className !== "column-body" && 477 | className.startsWith("column-") && 478 | !className.endsWith("right") && 479 | !className.endsWith("container") && 480 | className !== "column-margin" 481 | ); 482 | }); 483 | }); 484 | const rightSideConflictEls = arrConflictingEls.filter((el) => { 485 | if (el.tagName === "ASIDE") { 486 | return true; 487 | } 488 | 489 | const hasMarginCaption = Array.from(el.classList).find((className) => { 490 | return className == "margin-caption"; 491 | }); 492 | if (hasMarginCaption) { 493 | return true; 494 | } 495 | 496 | return Array.from(el.classList).find((className) => { 497 | return ( 498 | className !== "column-body" && 499 | !className.endsWith("container") && 500 | className.startsWith("column-") && 501 | !className.endsWith("left") 502 | ); 503 | }); 504 | }); 505 | 506 | const kOverlapPaddingSize = 10; 507 | function toRegions(els) { 508 | return els.map((el) => { 509 | const top = 510 | el.getBoundingClientRect().top + 511 | document.documentElement.scrollTop - 512 | kOverlapPaddingSize; 513 | return { 514 | top, 515 | bottom: top + el.scrollHeight + 2 * kOverlapPaddingSize, 516 | }; 517 | }); 518 | } 519 | 520 | const hideOverlappedSidebars = () => { 521 | marginScrollVisibility(toRegions(rightSideConflictEls)); 522 | sidebarScrollVisiblity(toRegions(leftSideConflictEls)); 523 | if (tocLeftScrollVisibility) { 524 | tocLeftScrollVisibility(toRegions(leftSideConflictEls)); 525 | } 526 | }; 527 | 528 | window.quartoToggleReader = () => { 529 | // Applies a slow class (or removes it) 530 | // to update the transition speed 531 | const slowTransition = (slow) => { 532 | const manageTransition = (id, slow) => { 533 | const el = document.getElementById(id); 534 | if (el) { 535 | if (slow) { 536 | el.classList.add("slow"); 537 | } else { 538 | el.classList.remove("slow"); 539 | } 540 | } 541 | }; 542 | 543 | manageTransition("TOC", slow); 544 | manageTransition("quarto-sidebar", slow); 545 | }; 546 | 547 | const readerMode = !isReaderMode(); 548 | setReaderModeValue(readerMode); 549 | 550 | // If we're entering reader mode, slow the transition 551 | if (readerMode) { 552 | slowTransition(readerMode); 553 | } 554 | highlightReaderToggle(readerMode); 555 | hideOverlappedSidebars(); 556 | 557 | // If we're exiting reader mode, restore the non-slow transition 558 | if (!readerMode) { 559 | slowTransition(!readerMode); 560 | } 561 | }; 562 | 563 | const highlightReaderToggle = (readerMode) => { 564 | const els = document.querySelectorAll(".quarto-reader-toggle"); 565 | if (els) { 566 | els.forEach((el) => { 567 | if (readerMode) { 568 | el.classList.add("reader"); 569 | } else { 570 | el.classList.remove("reader"); 571 | } 572 | }); 573 | } 574 | }; 575 | 576 | const setReaderModeValue = (val) => { 577 | if (window.location.protocol !== "file:") { 578 | window.localStorage.setItem("quarto-reader-mode", val); 579 | } else { 580 | localReaderMode = val; 581 | } 582 | }; 583 | 584 | const isReaderMode = () => { 585 | if (window.location.protocol !== "file:") { 586 | return window.localStorage.getItem("quarto-reader-mode") === "true"; 587 | } else { 588 | return localReaderMode; 589 | } 590 | }; 591 | let localReaderMode = null; 592 | 593 | // Walk the TOC and collapse/expand nodes 594 | // Nodes are expanded if: 595 | // - they are top level 596 | // - they have children that are 'active' links 597 | // - they are directly below an link that is 'active' 598 | const walk = (el, depth) => { 599 | // Tick depth when we enter a UL 600 | if (el.tagName === "UL") { 601 | depth = depth + 1; 602 | } 603 | 604 | // It this is active link 605 | let isActiveNode = false; 606 | if (el.tagName === "A" && el.classList.contains("active")) { 607 | isActiveNode = true; 608 | } 609 | 610 | // See if there is an active child to this element 611 | let hasActiveChild = false; 612 | for (child of el.children) { 613 | hasActiveChild = walk(child, depth) || hasActiveChild; 614 | } 615 | 616 | // Process the collapse state if this is an UL 617 | if (el.tagName === "UL") { 618 | if (depth === 1 || hasActiveChild || prevSiblingIsActiveLink(el)) { 619 | el.classList.remove("collapse"); 620 | } else { 621 | el.classList.add("collapse"); 622 | } 623 | 624 | // untick depth when we leave a UL 625 | depth = depth - 1; 626 | } 627 | return hasActiveChild || isActiveNode; 628 | }; 629 | 630 | // walk the TOC and expand / collapse any items that should be shown 631 | 632 | if (tocEl) { 633 | walk(tocEl, 0); 634 | updateActiveLink(); 635 | } 636 | 637 | // Throttle the scroll event and walk peridiocally 638 | window.document.addEventListener( 639 | "scroll", 640 | throttle(() => { 641 | if (tocEl) { 642 | updateActiveLink(); 643 | walk(tocEl, 0); 644 | } 645 | if (!isReaderMode()) { 646 | hideOverlappedSidebars(); 647 | } 648 | }, 5) 649 | ); 650 | window.addEventListener( 651 | "resize", 652 | throttle(() => { 653 | if (!isReaderMode()) { 654 | hideOverlappedSidebars(); 655 | } 656 | }, 10) 657 | ); 658 | hideOverlappedSidebars(); 659 | highlightReaderToggle(isReaderMode()); 660 | }); 661 | 662 | // grouped tabsets 663 | window.addEventListener("pageshow", (_event) => { 664 | function getTabSettings() { 665 | const data = localStorage.getItem("quarto-persistent-tabsets-data"); 666 | if (!data) { 667 | localStorage.setItem("quarto-persistent-tabsets-data", "{}"); 668 | return {}; 669 | } 670 | if (data) { 671 | return JSON.parse(data); 672 | } 673 | } 674 | 675 | function setTabSettings(data) { 676 | localStorage.setItem( 677 | "quarto-persistent-tabsets-data", 678 | JSON.stringify(data) 679 | ); 680 | } 681 | 682 | function setTabState(groupName, groupValue) { 683 | const data = getTabSettings(); 684 | data[groupName] = groupValue; 685 | setTabSettings(data); 686 | } 687 | 688 | function toggleTab(tab, active) { 689 | const tabPanelId = tab.getAttribute("aria-controls"); 690 | const tabPanel = document.getElementById(tabPanelId); 691 | if (active) { 692 | tab.classList.add("active"); 693 | tabPanel.classList.add("active"); 694 | } else { 695 | tab.classList.remove("active"); 696 | tabPanel.classList.remove("active"); 697 | } 698 | } 699 | 700 | function toggleAll(selectedGroup, selectorsToSync) { 701 | for (const [thisGroup, tabs] of Object.entries(selectorsToSync)) { 702 | const active = selectedGroup === thisGroup; 703 | for (const tab of tabs) { 704 | toggleTab(tab, active); 705 | } 706 | } 707 | } 708 | 709 | function findSelectorsToSyncByLanguage() { 710 | const result = {}; 711 | const tabs = Array.from( 712 | document.querySelectorAll(`div[data-group] a[id^='tabset-']`) 713 | ); 714 | for (const item of tabs) { 715 | const div = item.parentElement.parentElement.parentElement; 716 | const group = div.getAttribute("data-group"); 717 | if (!result[group]) { 718 | result[group] = {}; 719 | } 720 | const selectorsToSync = result[group]; 721 | const value = item.innerHTML; 722 | if (!selectorsToSync[value]) { 723 | selectorsToSync[value] = []; 724 | } 725 | selectorsToSync[value].push(item); 726 | } 727 | return result; 728 | } 729 | 730 | function setupSelectorSync() { 731 | const selectorsToSync = findSelectorsToSyncByLanguage(); 732 | Object.entries(selectorsToSync).forEach(([group, tabSetsByValue]) => { 733 | Object.entries(tabSetsByValue).forEach(([value, items]) => { 734 | items.forEach((item) => { 735 | item.addEventListener("click", (_event) => { 736 | setTabState(group, value); 737 | toggleAll(value, selectorsToSync[group]); 738 | }); 739 | }); 740 | }); 741 | }); 742 | return selectorsToSync; 743 | } 744 | 745 | const selectorsToSync = setupSelectorSync(); 746 | for (const [group, selectedName] of Object.entries(getTabSettings())) { 747 | const selectors = selectorsToSync[group]; 748 | // it's possible that stale state gives us empty selections, so we explicitly check here. 749 | if (selectors) { 750 | toggleAll(selectedName, selectors); 751 | } 752 | } 753 | }); 754 | 755 | function throttle(func, wait) { 756 | let waiting = false; 757 | return function () { 758 | if (!waiting) { 759 | func.apply(this, arguments); 760 | waiting = true; 761 | setTimeout(function () { 762 | waiting = false; 763 | }, wait); 764 | } 765 | }; 766 | } 767 | 768 | function nexttick(func) { 769 | return setTimeout(func, 0); 770 | } 771 | -------------------------------------------------------------------------------- /docs/site_libs/quarto-html/tippy.css: -------------------------------------------------------------------------------- 1 | .tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1} -------------------------------------------------------------------------------- /docs/site_libs/quarto-html/tippy.umd.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@popperjs/core")):"function"==typeof define&&define.amd?define(["@popperjs/core"],t):(e=e||self).tippy=t(e.Popper)}(this,(function(e){"use strict";var t={passive:!0,capture:!0},n=function(){return document.body};function r(e,t,n){if(Array.isArray(e)){var r=e[t];return null==r?Array.isArray(n)?n[t]:n:r}return e}function o(e,t){var n={}.toString.call(e);return 0===n.indexOf("[object")&&n.indexOf(t+"]")>-1}function i(e,t){return"function"==typeof e?e.apply(void 0,t):e}function a(e,t){return 0===t?e:function(r){clearTimeout(n),n=setTimeout((function(){e(r)}),t)};var n}function s(e,t){var n=Object.assign({},e);return t.forEach((function(e){delete n[e]})),n}function u(e){return[].concat(e)}function c(e,t){-1===e.indexOf(t)&&e.push(t)}function p(e){return e.split("-")[0]}function f(e){return[].slice.call(e)}function l(e){return Object.keys(e).reduce((function(t,n){return void 0!==e[n]&&(t[n]=e[n]),t}),{})}function d(){return document.createElement("div")}function v(e){return["Element","Fragment"].some((function(t){return o(e,t)}))}function m(e){return o(e,"MouseEvent")}function g(e){return!(!e||!e._tippy||e._tippy.reference!==e)}function h(e){return v(e)?[e]:function(e){return o(e,"NodeList")}(e)?f(e):Array.isArray(e)?e:f(document.querySelectorAll(e))}function b(e,t){e.forEach((function(e){e&&(e.style.transitionDuration=t+"ms")}))}function y(e,t){e.forEach((function(e){e&&e.setAttribute("data-state",t)}))}function w(e){var t,n=u(e)[0];return null!=n&&null!=(t=n.ownerDocument)&&t.body?n.ownerDocument:document}function E(e,t,n){var r=t+"EventListener";["transitionend","webkitTransitionEnd"].forEach((function(t){e[r](t,n)}))}function O(e,t){for(var n=t;n;){var r;if(e.contains(n))return!0;n=null==n.getRootNode||null==(r=n.getRootNode())?void 0:r.host}return!1}var x={isTouch:!1},C=0;function T(){x.isTouch||(x.isTouch=!0,window.performance&&document.addEventListener("mousemove",A))}function A(){var e=performance.now();e-C<20&&(x.isTouch=!1,document.removeEventListener("mousemove",A)),C=e}function L(){var e=document.activeElement;if(g(e)){var t=e._tippy;e.blur&&!t.state.isVisible&&e.blur()}}var D=!!("undefined"!=typeof window&&"undefined"!=typeof document)&&!!window.msCrypto,R=Object.assign({appendTo:n,aria:{content:"auto",expanded:"auto"},delay:0,duration:[300,250],getReferenceClientRect:null,hideOnClick:!0,ignoreAttributes:!1,interactive:!1,interactiveBorder:2,interactiveDebounce:0,moveTransition:"",offset:[0,10],onAfterUpdate:function(){},onBeforeUpdate:function(){},onCreate:function(){},onDestroy:function(){},onHidden:function(){},onHide:function(){},onMount:function(){},onShow:function(){},onShown:function(){},onTrigger:function(){},onUntrigger:function(){},onClickOutside:function(){},placement:"top",plugins:[],popperOptions:{},render:null,showOnCreate:!1,touch:!0,trigger:"mouseenter focus",triggerTarget:null},{animateFill:!1,followCursor:!1,inlinePositioning:!1,sticky:!1},{allowHTML:!1,animation:"fade",arrow:!0,content:"",inertia:!1,maxWidth:350,role:"tooltip",theme:"",zIndex:9999}),k=Object.keys(R);function P(e){var t=(e.plugins||[]).reduce((function(t,n){var r,o=n.name,i=n.defaultValue;o&&(t[o]=void 0!==e[o]?e[o]:null!=(r=R[o])?r:i);return t}),{});return Object.assign({},e,t)}function j(e,t){var n=Object.assign({},t,{content:i(t.content,[e])},t.ignoreAttributes?{}:function(e,t){return(t?Object.keys(P(Object.assign({},R,{plugins:t}))):k).reduce((function(t,n){var r=(e.getAttribute("data-tippy-"+n)||"").trim();if(!r)return t;if("content"===n)t[n]=r;else try{t[n]=JSON.parse(r)}catch(e){t[n]=r}return t}),{})}(e,t.plugins));return n.aria=Object.assign({},R.aria,n.aria),n.aria={expanded:"auto"===n.aria.expanded?t.interactive:n.aria.expanded,content:"auto"===n.aria.content?t.interactive?null:"describedby":n.aria.content},n}function M(e,t){e.innerHTML=t}function V(e){var t=d();return!0===e?t.className="tippy-arrow":(t.className="tippy-svg-arrow",v(e)?t.appendChild(e):M(t,e)),t}function I(e,t){v(t.content)?(M(e,""),e.appendChild(t.content)):"function"!=typeof t.content&&(t.allowHTML?M(e,t.content):e.textContent=t.content)}function S(e){var t=e.firstElementChild,n=f(t.children);return{box:t,content:n.find((function(e){return e.classList.contains("tippy-content")})),arrow:n.find((function(e){return e.classList.contains("tippy-arrow")||e.classList.contains("tippy-svg-arrow")})),backdrop:n.find((function(e){return e.classList.contains("tippy-backdrop")}))}}function N(e){var t=d(),n=d();n.className="tippy-box",n.setAttribute("data-state","hidden"),n.setAttribute("tabindex","-1");var r=d();function o(n,r){var o=S(t),i=o.box,a=o.content,s=o.arrow;r.theme?i.setAttribute("data-theme",r.theme):i.removeAttribute("data-theme"),"string"==typeof r.animation?i.setAttribute("data-animation",r.animation):i.removeAttribute("data-animation"),r.inertia?i.setAttribute("data-inertia",""):i.removeAttribute("data-inertia"),i.style.maxWidth="number"==typeof r.maxWidth?r.maxWidth+"px":r.maxWidth,r.role?i.setAttribute("role",r.role):i.removeAttribute("role"),n.content===r.content&&n.allowHTML===r.allowHTML||I(a,e.props),r.arrow?s?n.arrow!==r.arrow&&(i.removeChild(s),i.appendChild(V(r.arrow))):i.appendChild(V(r.arrow)):s&&i.removeChild(s)}return r.className="tippy-content",r.setAttribute("data-state","hidden"),I(r,e.props),t.appendChild(n),n.appendChild(r),o(e.props,e.props),{popper:t,onUpdate:o}}N.$$tippy=!0;var B=1,H=[],U=[];function _(o,s){var v,g,h,C,T,A,L,k,M=j(o,Object.assign({},R,P(l(s)))),V=!1,I=!1,N=!1,_=!1,F=[],W=a(we,M.interactiveDebounce),X=B++,Y=(k=M.plugins).filter((function(e,t){return k.indexOf(e)===t})),$={id:X,reference:o,popper:d(),popperInstance:null,props:M,state:{isEnabled:!0,isVisible:!1,isDestroyed:!1,isMounted:!1,isShown:!1},plugins:Y,clearDelayTimeouts:function(){clearTimeout(v),clearTimeout(g),cancelAnimationFrame(h)},setProps:function(e){if($.state.isDestroyed)return;ae("onBeforeUpdate",[$,e]),be();var t=$.props,n=j(o,Object.assign({},t,l(e),{ignoreAttributes:!0}));$.props=n,he(),t.interactiveDebounce!==n.interactiveDebounce&&(ce(),W=a(we,n.interactiveDebounce));t.triggerTarget&&!n.triggerTarget?u(t.triggerTarget).forEach((function(e){e.removeAttribute("aria-expanded")})):n.triggerTarget&&o.removeAttribute("aria-expanded");ue(),ie(),J&&J(t,n);$.popperInstance&&(Ce(),Ae().forEach((function(e){requestAnimationFrame(e._tippy.popperInstance.forceUpdate)})));ae("onAfterUpdate",[$,e])},setContent:function(e){$.setProps({content:e})},show:function(){var e=$.state.isVisible,t=$.state.isDestroyed,o=!$.state.isEnabled,a=x.isTouch&&!$.props.touch,s=r($.props.duration,0,R.duration);if(e||t||o||a)return;if(te().hasAttribute("disabled"))return;if(ae("onShow",[$],!1),!1===$.props.onShow($))return;$.state.isVisible=!0,ee()&&(z.style.visibility="visible");ie(),de(),$.state.isMounted||(z.style.transition="none");if(ee()){var u=re(),p=u.box,f=u.content;b([p,f],0)}A=function(){var e;if($.state.isVisible&&!_){if(_=!0,z.offsetHeight,z.style.transition=$.props.moveTransition,ee()&&$.props.animation){var t=re(),n=t.box,r=t.content;b([n,r],s),y([n,r],"visible")}se(),ue(),c(U,$),null==(e=$.popperInstance)||e.forceUpdate(),ae("onMount",[$]),$.props.animation&&ee()&&function(e,t){me(e,t)}(s,(function(){$.state.isShown=!0,ae("onShown",[$])}))}},function(){var e,t=$.props.appendTo,r=te();e=$.props.interactive&&t===n||"parent"===t?r.parentNode:i(t,[r]);e.contains(z)||e.appendChild(z);$.state.isMounted=!0,Ce()}()},hide:function(){var e=!$.state.isVisible,t=$.state.isDestroyed,n=!$.state.isEnabled,o=r($.props.duration,1,R.duration);if(e||t||n)return;if(ae("onHide",[$],!1),!1===$.props.onHide($))return;$.state.isVisible=!1,$.state.isShown=!1,_=!1,V=!1,ee()&&(z.style.visibility="hidden");if(ce(),ve(),ie(!0),ee()){var i=re(),a=i.box,s=i.content;$.props.animation&&(b([a,s],o),y([a,s],"hidden"))}se(),ue(),$.props.animation?ee()&&function(e,t){me(e,(function(){!$.state.isVisible&&z.parentNode&&z.parentNode.contains(z)&&t()}))}(o,$.unmount):$.unmount()},hideWithInteractivity:function(e){ne().addEventListener("mousemove",W),c(H,W),W(e)},enable:function(){$.state.isEnabled=!0},disable:function(){$.hide(),$.state.isEnabled=!1},unmount:function(){$.state.isVisible&&$.hide();if(!$.state.isMounted)return;Te(),Ae().forEach((function(e){e._tippy.unmount()})),z.parentNode&&z.parentNode.removeChild(z);U=U.filter((function(e){return e!==$})),$.state.isMounted=!1,ae("onHidden",[$])},destroy:function(){if($.state.isDestroyed)return;$.clearDelayTimeouts(),$.unmount(),be(),delete o._tippy,$.state.isDestroyed=!0,ae("onDestroy",[$])}};if(!M.render)return $;var q=M.render($),z=q.popper,J=q.onUpdate;z.setAttribute("data-tippy-root",""),z.id="tippy-"+$.id,$.popper=z,o._tippy=$,z._tippy=$;var G=Y.map((function(e){return e.fn($)})),K=o.hasAttribute("aria-expanded");return he(),ue(),ie(),ae("onCreate",[$]),M.showOnCreate&&Le(),z.addEventListener("mouseenter",(function(){$.props.interactive&&$.state.isVisible&&$.clearDelayTimeouts()})),z.addEventListener("mouseleave",(function(){$.props.interactive&&$.props.trigger.indexOf("mouseenter")>=0&&ne().addEventListener("mousemove",W)})),$;function Q(){var e=$.props.touch;return Array.isArray(e)?e:[e,0]}function Z(){return"hold"===Q()[0]}function ee(){var e;return!(null==(e=$.props.render)||!e.$$tippy)}function te(){return L||o}function ne(){var e=te().parentNode;return e?w(e):document}function re(){return S(z)}function oe(e){return $.state.isMounted&&!$.state.isVisible||x.isTouch||C&&"focus"===C.type?0:r($.props.delay,e?0:1,R.delay)}function ie(e){void 0===e&&(e=!1),z.style.pointerEvents=$.props.interactive&&!e?"":"none",z.style.zIndex=""+$.props.zIndex}function ae(e,t,n){var r;(void 0===n&&(n=!0),G.forEach((function(n){n[e]&&n[e].apply(n,t)})),n)&&(r=$.props)[e].apply(r,t)}function se(){var e=$.props.aria;if(e.content){var t="aria-"+e.content,n=z.id;u($.props.triggerTarget||o).forEach((function(e){var r=e.getAttribute(t);if($.state.isVisible)e.setAttribute(t,r?r+" "+n:n);else{var o=r&&r.replace(n,"").trim();o?e.setAttribute(t,o):e.removeAttribute(t)}}))}}function ue(){!K&&$.props.aria.expanded&&u($.props.triggerTarget||o).forEach((function(e){$.props.interactive?e.setAttribute("aria-expanded",$.state.isVisible&&e===te()?"true":"false"):e.removeAttribute("aria-expanded")}))}function ce(){ne().removeEventListener("mousemove",W),H=H.filter((function(e){return e!==W}))}function pe(e){if(!x.isTouch||!N&&"mousedown"!==e.type){var t=e.composedPath&&e.composedPath()[0]||e.target;if(!$.props.interactive||!O(z,t)){if(u($.props.triggerTarget||o).some((function(e){return O(e,t)}))){if(x.isTouch)return;if($.state.isVisible&&$.props.trigger.indexOf("click")>=0)return}else ae("onClickOutside",[$,e]);!0===$.props.hideOnClick&&($.clearDelayTimeouts(),$.hide(),I=!0,setTimeout((function(){I=!1})),$.state.isMounted||ve())}}}function fe(){N=!0}function le(){N=!1}function de(){var e=ne();e.addEventListener("mousedown",pe,!0),e.addEventListener("touchend",pe,t),e.addEventListener("touchstart",le,t),e.addEventListener("touchmove",fe,t)}function ve(){var e=ne();e.removeEventListener("mousedown",pe,!0),e.removeEventListener("touchend",pe,t),e.removeEventListener("touchstart",le,t),e.removeEventListener("touchmove",fe,t)}function me(e,t){var n=re().box;function r(e){e.target===n&&(E(n,"remove",r),t())}if(0===e)return t();E(n,"remove",T),E(n,"add",r),T=r}function ge(e,t,n){void 0===n&&(n=!1),u($.props.triggerTarget||o).forEach((function(r){r.addEventListener(e,t,n),F.push({node:r,eventType:e,handler:t,options:n})}))}function he(){var e;Z()&&(ge("touchstart",ye,{passive:!0}),ge("touchend",Ee,{passive:!0})),(e=$.props.trigger,e.split(/\s+/).filter(Boolean)).forEach((function(e){if("manual"!==e)switch(ge(e,ye),e){case"mouseenter":ge("mouseleave",Ee);break;case"focus":ge(D?"focusout":"blur",Oe);break;case"focusin":ge("focusout",Oe)}}))}function be(){F.forEach((function(e){var t=e.node,n=e.eventType,r=e.handler,o=e.options;t.removeEventListener(n,r,o)})),F=[]}function ye(e){var t,n=!1;if($.state.isEnabled&&!xe(e)&&!I){var r="focus"===(null==(t=C)?void 0:t.type);C=e,L=e.currentTarget,ue(),!$.state.isVisible&&m(e)&&H.forEach((function(t){return t(e)})),"click"===e.type&&($.props.trigger.indexOf("mouseenter")<0||V)&&!1!==$.props.hideOnClick&&$.state.isVisible?n=!0:Le(e),"click"===e.type&&(V=!n),n&&!r&&De(e)}}function we(e){var t=e.target,n=te().contains(t)||z.contains(t);"mousemove"===e.type&&n||function(e,t){var n=t.clientX,r=t.clientY;return e.every((function(e){var t=e.popperRect,o=e.popperState,i=e.props.interactiveBorder,a=p(o.placement),s=o.modifiersData.offset;if(!s)return!0;var u="bottom"===a?s.top.y:0,c="top"===a?s.bottom.y:0,f="right"===a?s.left.x:0,l="left"===a?s.right.x:0,d=t.top-r+u>i,v=r-t.bottom-c>i,m=t.left-n+f>i,g=n-t.right-l>i;return d||v||m||g}))}(Ae().concat(z).map((function(e){var t,n=null==(t=e._tippy.popperInstance)?void 0:t.state;return n?{popperRect:e.getBoundingClientRect(),popperState:n,props:M}:null})).filter(Boolean),e)&&(ce(),De(e))}function Ee(e){xe(e)||$.props.trigger.indexOf("click")>=0&&V||($.props.interactive?$.hideWithInteractivity(e):De(e))}function Oe(e){$.props.trigger.indexOf("focusin")<0&&e.target!==te()||$.props.interactive&&e.relatedTarget&&z.contains(e.relatedTarget)||De(e)}function xe(e){return!!x.isTouch&&Z()!==e.type.indexOf("touch")>=0}function Ce(){Te();var t=$.props,n=t.popperOptions,r=t.placement,i=t.offset,a=t.getReferenceClientRect,s=t.moveTransition,u=ee()?S(z).arrow:null,c=a?{getBoundingClientRect:a,contextElement:a.contextElement||te()}:o,p=[{name:"offset",options:{offset:i}},{name:"preventOverflow",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:"flip",options:{padding:5}},{name:"computeStyles",options:{adaptive:!s}},{name:"$$tippy",enabled:!0,phase:"beforeWrite",requires:["computeStyles"],fn:function(e){var t=e.state;if(ee()){var n=re().box;["placement","reference-hidden","escaped"].forEach((function(e){"placement"===e?n.setAttribute("data-placement",t.placement):t.attributes.popper["data-popper-"+e]?n.setAttribute("data-"+e,""):n.removeAttribute("data-"+e)})),t.attributes.popper={}}}}];ee()&&u&&p.push({name:"arrow",options:{element:u,padding:3}}),p.push.apply(p,(null==n?void 0:n.modifiers)||[]),$.popperInstance=e.createPopper(c,z,Object.assign({},n,{placement:r,onFirstUpdate:A,modifiers:p}))}function Te(){$.popperInstance&&($.popperInstance.destroy(),$.popperInstance=null)}function Ae(){return f(z.querySelectorAll("[data-tippy-root]"))}function Le(e){$.clearDelayTimeouts(),e&&ae("onTrigger",[$,e]),de();var t=oe(!0),n=Q(),r=n[0],o=n[1];x.isTouch&&"hold"===r&&o&&(t=o),t?v=setTimeout((function(){$.show()}),t):$.show()}function De(e){if($.clearDelayTimeouts(),ae("onUntrigger",[$,e]),$.state.isVisible){if(!($.props.trigger.indexOf("mouseenter")>=0&&$.props.trigger.indexOf("click")>=0&&["mouseleave","mousemove"].indexOf(e.type)>=0&&V)){var t=oe(!1);t?g=setTimeout((function(){$.state.isVisible&&$.hide()}),t):h=requestAnimationFrame((function(){$.hide()}))}}else ve()}}function F(e,n){void 0===n&&(n={});var r=R.plugins.concat(n.plugins||[]);document.addEventListener("touchstart",T,t),window.addEventListener("blur",L);var o=Object.assign({},n,{plugins:r}),i=h(e).reduce((function(e,t){var n=t&&_(t,o);return n&&e.push(n),e}),[]);return v(e)?i[0]:i}F.defaultProps=R,F.setDefaultProps=function(e){Object.keys(e).forEach((function(t){R[t]=e[t]}))},F.currentInput=x;var W=Object.assign({},e.applyStyles,{effect:function(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow)}}),X={mouseover:"mouseenter",focusin:"focus",click:"click"};var Y={name:"animateFill",defaultValue:!1,fn:function(e){var t;if(null==(t=e.props.render)||!t.$$tippy)return{};var n=S(e.popper),r=n.box,o=n.content,i=e.props.animateFill?function(){var e=d();return e.className="tippy-backdrop",y([e],"hidden"),e}():null;return{onCreate:function(){i&&(r.insertBefore(i,r.firstElementChild),r.setAttribute("data-animatefill",""),r.style.overflow="hidden",e.setProps({arrow:!1,animation:"shift-away"}))},onMount:function(){if(i){var e=r.style.transitionDuration,t=Number(e.replace("ms",""));o.style.transitionDelay=Math.round(t/10)+"ms",i.style.transitionDuration=e,y([i],"visible")}},onShow:function(){i&&(i.style.transitionDuration="0ms")},onHide:function(){i&&y([i],"hidden")}}}};var $={clientX:0,clientY:0},q=[];function z(e){var t=e.clientX,n=e.clientY;$={clientX:t,clientY:n}}var J={name:"followCursor",defaultValue:!1,fn:function(e){var t=e.reference,n=w(e.props.triggerTarget||t),r=!1,o=!1,i=!0,a=e.props;function s(){return"initial"===e.props.followCursor&&e.state.isVisible}function u(){n.addEventListener("mousemove",f)}function c(){n.removeEventListener("mousemove",f)}function p(){r=!0,e.setProps({getReferenceClientRect:null}),r=!1}function f(n){var r=!n.target||t.contains(n.target),o=e.props.followCursor,i=n.clientX,a=n.clientY,s=t.getBoundingClientRect(),u=i-s.left,c=a-s.top;!r&&e.props.interactive||e.setProps({getReferenceClientRect:function(){var e=t.getBoundingClientRect(),n=i,r=a;"initial"===o&&(n=e.left+u,r=e.top+c);var s="horizontal"===o?e.top:r,p="vertical"===o?e.right:n,f="horizontal"===o?e.bottom:r,l="vertical"===o?e.left:n;return{width:p-l,height:f-s,top:s,right:p,bottom:f,left:l}}})}function l(){e.props.followCursor&&(q.push({instance:e,doc:n}),function(e){e.addEventListener("mousemove",z)}(n))}function d(){0===(q=q.filter((function(t){return t.instance!==e}))).filter((function(e){return e.doc===n})).length&&function(e){e.removeEventListener("mousemove",z)}(n)}return{onCreate:l,onDestroy:d,onBeforeUpdate:function(){a=e.props},onAfterUpdate:function(t,n){var i=n.followCursor;r||void 0!==i&&a.followCursor!==i&&(d(),i?(l(),!e.state.isMounted||o||s()||u()):(c(),p()))},onMount:function(){e.props.followCursor&&!o&&(i&&(f($),i=!1),s()||u())},onTrigger:function(e,t){m(t)&&($={clientX:t.clientX,clientY:t.clientY}),o="focus"===t.type},onHidden:function(){e.props.followCursor&&(p(),c(),i=!0)}}}};var G={name:"inlinePositioning",defaultValue:!1,fn:function(e){var t,n=e.reference;var r=-1,o=!1,i=[],a={name:"tippyInlinePositioning",enabled:!0,phase:"afterWrite",fn:function(o){var a=o.state;e.props.inlinePositioning&&(-1!==i.indexOf(a.placement)&&(i=[]),t!==a.placement&&-1===i.indexOf(a.placement)&&(i.push(a.placement),e.setProps({getReferenceClientRect:function(){return function(e){return function(e,t,n,r){if(n.length<2||null===e)return t;if(2===n.length&&r>=0&&n[0].left>n[1].right)return n[r]||t;switch(e){case"top":case"bottom":var o=n[0],i=n[n.length-1],a="top"===e,s=o.top,u=i.bottom,c=a?o.left:i.left,p=a?o.right:i.right;return{top:s,bottom:u,left:c,right:p,width:p-c,height:u-s};case"left":case"right":var f=Math.min.apply(Math,n.map((function(e){return e.left}))),l=Math.max.apply(Math,n.map((function(e){return e.right}))),d=n.filter((function(t){return"left"===e?t.left===f:t.right===l})),v=d[0].top,m=d[d.length-1].bottom;return{top:v,bottom:m,left:f,right:l,width:l-f,height:m-v};default:return t}}(p(e),n.getBoundingClientRect(),f(n.getClientRects()),r)}(a.placement)}})),t=a.placement)}};function s(){var t;o||(t=function(e,t){var n;return{popperOptions:Object.assign({},e.popperOptions,{modifiers:[].concat(((null==(n=e.popperOptions)?void 0:n.modifiers)||[]).filter((function(e){return e.name!==t.name})),[t])})}}(e.props,a),o=!0,e.setProps(t),o=!1)}return{onCreate:s,onAfterUpdate:s,onTrigger:function(t,n){if(m(n)){var o=f(e.reference.getClientRects()),i=o.find((function(e){return e.left-2<=n.clientX&&e.right+2>=n.clientX&&e.top-2<=n.clientY&&e.bottom+2>=n.clientY})),a=o.indexOf(i);r=a>-1?a:r}},onHidden:function(){r=-1}}}};var K={name:"sticky",defaultValue:!1,fn:function(e){var t=e.reference,n=e.popper;function r(t){return!0===e.props.sticky||e.props.sticky===t}var o=null,i=null;function a(){var s=r("reference")?(e.popperInstance?e.popperInstance.state.elements.reference:t).getBoundingClientRect():null,u=r("popper")?n.getBoundingClientRect():null;(s&&Q(o,s)||u&&Q(i,u))&&e.popperInstance&&e.popperInstance.update(),o=s,i=u,e.state.isMounted&&requestAnimationFrame(a)}return{onMount:function(){e.props.sticky&&a()}}}};function Q(e,t){return!e||!t||(e.top!==t.top||e.right!==t.right||e.bottom!==t.bottom||e.left!==t.left)}return F.setDefaultProps({plugins:[Y,J,G,K],render:N}),F.createSingleton=function(e,t){var n;void 0===t&&(t={});var r,o=e,i=[],a=[],c=t.overrides,p=[],f=!1;function l(){a=o.map((function(e){return u(e.props.triggerTarget||e.reference)})).reduce((function(e,t){return e.concat(t)}),[])}function v(){i=o.map((function(e){return e.reference}))}function m(e){o.forEach((function(t){e?t.enable():t.disable()}))}function g(e){return o.map((function(t){var n=t.setProps;return t.setProps=function(o){n(o),t.reference===r&&e.setProps(o)},function(){t.setProps=n}}))}function h(e,t){var n=a.indexOf(t);if(t!==r){r=t;var s=(c||[]).concat("content").reduce((function(e,t){return e[t]=o[n].props[t],e}),{});e.setProps(Object.assign({},s,{getReferenceClientRect:"function"==typeof s.getReferenceClientRect?s.getReferenceClientRect:function(){var e;return null==(e=i[n])?void 0:e.getBoundingClientRect()}}))}}m(!1),v(),l();var b={fn:function(){return{onDestroy:function(){m(!0)},onHidden:function(){r=null},onClickOutside:function(e){e.props.showOnCreate&&!f&&(f=!0,r=null)},onShow:function(e){e.props.showOnCreate&&!f&&(f=!0,h(e,i[0]))},onTrigger:function(e,t){h(e,t.currentTarget)}}}},y=F(d(),Object.assign({},s(t,["overrides"]),{plugins:[b].concat(t.plugins||[]),triggerTarget:a,popperOptions:Object.assign({},t.popperOptions,{modifiers:[].concat((null==(n=t.popperOptions)?void 0:n.modifiers)||[],[W])})})),w=y.show;y.show=function(e){if(w(),!r&&null==e)return h(y,i[0]);if(!r||null!=e){if("number"==typeof e)return i[e]&&h(y,i[e]);if(o.indexOf(e)>=0){var t=e.reference;return h(y,t)}return i.indexOf(e)>=0?h(y,e):void 0}},y.showNext=function(){var e=i[0];if(!r)return y.show(0);var t=i.indexOf(r);y.show(i[t+1]||e)},y.showPrevious=function(){var e=i[i.length-1];if(!r)return y.show(e);var t=i.indexOf(r),n=i[t-1]||e;y.show(n)};var E=y.setProps;return y.setProps=function(e){c=e.overrides||c,E(e)},y.setInstances=function(e){m(!0),p.forEach((function(e){return e()})),o=e,m(!1),v(),l(),p=g(y),y.setProps({triggerTarget:a})},p=g(y),y},F.delegate=function(e,n){var r=[],o=[],i=!1,a=n.target,c=s(n,["target"]),p=Object.assign({},c,{trigger:"manual",touch:!1}),f=Object.assign({touch:R.touch},c,{showOnCreate:!0}),l=F(e,p);function d(e){if(e.target&&!i){var t=e.target.closest(a);if(t){var r=t.getAttribute("data-tippy-trigger")||n.trigger||R.trigger;if(!t._tippy&&!("touchstart"===e.type&&"boolean"==typeof f.touch||"touchstart"!==e.type&&r.indexOf(X[e.type])<0)){var s=F(t,f);s&&(o=o.concat(s))}}}}function v(e,t,n,o){void 0===o&&(o=!1),e.addEventListener(t,n,o),r.push({node:e,eventType:t,handler:n,options:o})}return u(l).forEach((function(e){var n=e.destroy,a=e.enable,s=e.disable;e.destroy=function(e){void 0===e&&(e=!0),e&&o.forEach((function(e){e.destroy()})),o=[],r.forEach((function(e){var t=e.node,n=e.eventType,r=e.handler,o=e.options;t.removeEventListener(n,r,o)})),r=[],n()},e.enable=function(){a(),o.forEach((function(e){return e.enable()})),i=!1},e.disable=function(){s(),o.forEach((function(e){return e.disable()})),i=!0},function(e){var n=e.reference;v(n,"touchstart",d,t),v(n,"mouseover",d),v(n,"focusin",d),v(n,"click",d)}(e)})),l},F.hideAll=function(e){var t=void 0===e?{}:e,n=t.exclude,r=t.duration;U.forEach((function(e){var t=!1;if(n&&(t=g(n)?e.reference===n:e.popper===n.popper),!t){var o=e.props.duration;e.setProps({duration:r}),e.hide(),e.state.isDestroyed||e.setProps({duration:o})}}))},F.roundArrow='',F})); 2 | 3 | -------------------------------------------------------------------------------- /docs/site_libs/quarto-nav/headroom.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * headroom.js v0.12.0 - Give your page some headroom. Hide your header until you need it 3 | * Copyright (c) 2020 Nick Williams - http://wicky.nillia.ms/headroom.js 4 | * License: MIT 5 | */ 6 | 7 | !function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(t=t||self).Headroom=n()}(this,function(){"use strict";function t(){return"undefined"!=typeof window}function d(t){return function(t){return t&&t.document&&function(t){return 9===t.nodeType}(t.document)}(t)?function(t){var n=t.document,o=n.body,s=n.documentElement;return{scrollHeight:function(){return Math.max(o.scrollHeight,s.scrollHeight,o.offsetHeight,s.offsetHeight,o.clientHeight,s.clientHeight)},height:function(){return t.innerHeight||s.clientHeight||o.clientHeight},scrollY:function(){return void 0!==t.pageYOffset?t.pageYOffset:(s||o.parentNode||o).scrollTop}}}(t):function(t){return{scrollHeight:function(){return Math.max(t.scrollHeight,t.offsetHeight,t.clientHeight)},height:function(){return Math.max(t.offsetHeight,t.clientHeight)},scrollY:function(){return t.scrollTop}}}(t)}function n(t,s,e){var n,o=function(){var n=!1;try{var t={get passive(){n=!0}};window.addEventListener("test",t,t),window.removeEventListener("test",t,t)}catch(t){n=!1}return n}(),i=!1,r=d(t),l=r.scrollY(),a={};function c(){var t=Math.round(r.scrollY()),n=r.height(),o=r.scrollHeight();a.scrollY=t,a.lastScrollY=l,a.direction=ls.tolerance[a.direction],e(a),l=t,i=!1}function h(){i||(i=!0,n=requestAnimationFrame(c))}var u=!!o&&{passive:!0,capture:!1};return t.addEventListener("scroll",h,u),c(),{destroy:function(){cancelAnimationFrame(n),t.removeEventListener("scroll",h,u)}}}function o(t){return t===Object(t)?t:{down:t,up:t}}function s(t,n){n=n||{},Object.assign(this,s.options,n),this.classes=Object.assign({},s.options.classes,n.classes),this.elem=t,this.tolerance=o(this.tolerance),this.offset=o(this.offset),this.initialised=!1,this.frozen=!1}return s.prototype={constructor:s,init:function(){return s.cutsTheMustard&&!this.initialised&&(this.addClass("initial"),this.initialised=!0,setTimeout(function(t){t.scrollTracker=n(t.scroller,{offset:t.offset,tolerance:t.tolerance},t.update.bind(t))},100,this)),this},destroy:function(){this.initialised=!1,Object.keys(this.classes).forEach(this.removeClass,this),this.scrollTracker.destroy()},unpin:function(){!this.hasClass("pinned")&&this.hasClass("unpinned")||(this.addClass("unpinned"),this.removeClass("pinned"),this.onUnpin&&this.onUnpin.call(this))},pin:function(){this.hasClass("unpinned")&&(this.addClass("pinned"),this.removeClass("unpinned"),this.onPin&&this.onPin.call(this))},freeze:function(){this.frozen=!0,this.addClass("frozen")},unfreeze:function(){this.frozen=!1,this.removeClass("frozen")},top:function(){this.hasClass("top")||(this.addClass("top"),this.removeClass("notTop"),this.onTop&&this.onTop.call(this))},notTop:function(){this.hasClass("notTop")||(this.addClass("notTop"),this.removeClass("top"),this.onNotTop&&this.onNotTop.call(this))},bottom:function(){this.hasClass("bottom")||(this.addClass("bottom"),this.removeClass("notBottom"),this.onBottom&&this.onBottom.call(this))},notBottom:function(){this.hasClass("notBottom")||(this.addClass("notBottom"),this.removeClass("bottom"),this.onNotBottom&&this.onNotBottom.call(this))},shouldUnpin:function(t){return"down"===t.direction&&!t.top&&t.toleranceExceeded},shouldPin:function(t){return"up"===t.direction&&t.toleranceExceeded||t.top},addClass:function(t){this.elem.classList.add.apply(this.elem.classList,this.classes[t].split(" "))},removeClass:function(t){this.elem.classList.remove.apply(this.elem.classList,this.classes[t].split(" "))},hasClass:function(t){return this.classes[t].split(" ").every(function(t){return this.classList.contains(t)},this.elem)},update:function(t){t.isOutOfBounds||!0!==this.frozen&&(t.top?this.top():this.notTop(),t.bottom?this.bottom():this.notBottom(),this.shouldUnpin(t)?this.unpin():this.shouldPin(t)&&this.pin())}},s.options={tolerance:{up:0,down:0},offset:0,scroller:t()?window:null,classes:{frozen:"headroom--frozen",pinned:"headroom--pinned",unpinned:"headroom--unpinned",top:"headroom--top",notTop:"headroom--not-top",bottom:"headroom--bottom",notBottom:"headroom--not-bottom",initial:"headroom"}},s.cutsTheMustard=!!(t()&&function(){}.bind&&"classList"in document.documentElement&&Object.assign&&Object.keys&&requestAnimationFrame),s}); 8 | -------------------------------------------------------------------------------- /docs/site_libs/quarto-nav/quarto-nav.js: -------------------------------------------------------------------------------- 1 | const headroomChanged = new CustomEvent("quarto-hrChanged", { 2 | detail: {}, 3 | bubbles: true, 4 | cancelable: false, 5 | composed: false, 6 | }); 7 | 8 | window.document.addEventListener("DOMContentLoaded", function () { 9 | let init = false; 10 | 11 | function throttle(func, wait) { 12 | var timeout; 13 | return function () { 14 | const context = this; 15 | const args = arguments; 16 | const later = function () { 17 | clearTimeout(timeout); 18 | timeout = null; 19 | func.apply(context, args); 20 | }; 21 | 22 | if (!timeout) { 23 | timeout = setTimeout(later, wait); 24 | } 25 | }; 26 | } 27 | 28 | function headerOffset() { 29 | // Set an offset if there is are fixed top navbar 30 | const headerEl = window.document.querySelector("header.fixed-top"); 31 | if (headerEl) { 32 | return headerEl.clientHeight; 33 | } else { 34 | return 0; 35 | } 36 | } 37 | 38 | function footerOffset() { 39 | const footerEl = window.document.querySelector("footer.footer"); 40 | if (footerEl) { 41 | return footerEl.clientHeight; 42 | } else { 43 | return 0; 44 | } 45 | } 46 | 47 | function updateDocumentOffsetWithoutAnimation() { 48 | updateDocumentOffset(false); 49 | } 50 | 51 | function updateDocumentOffset(animated) { 52 | // set body offset 53 | const topOffset = headerOffset(); 54 | const bodyOffset = topOffset + footerOffset(); 55 | const bodyEl = window.document.body; 56 | bodyEl.setAttribute("data-bs-offset", topOffset); 57 | bodyEl.style.paddingTop = topOffset + "px"; 58 | 59 | // deal with sidebar offsets 60 | const sidebars = window.document.querySelectorAll( 61 | ".sidebar, .headroom-target" 62 | ); 63 | sidebars.forEach((sidebar) => { 64 | if (!animated) { 65 | sidebar.classList.add("notransition"); 66 | // Remove the no transition class after the animation has time to complete 67 | setTimeout(function () { 68 | sidebar.classList.remove("notransition"); 69 | }, 201); 70 | } 71 | 72 | if (window.Headroom && sidebar.classList.contains("sidebar-unpinned")) { 73 | sidebar.style.top = "0"; 74 | sidebar.style.maxHeight = "100vh"; 75 | } else { 76 | sidebar.style.top = topOffset + "px"; 77 | sidebar.style.maxHeight = "calc(100vh - " + topOffset + "px)"; 78 | } 79 | }); 80 | 81 | // allow space for footer 82 | const mainContainer = window.document.querySelector(".quarto-container"); 83 | if (mainContainer) { 84 | mainContainer.style.minHeight = "calc(100vh - " + bodyOffset + "px)"; 85 | } 86 | 87 | // link offset 88 | let linkStyle = window.document.querySelector("#quarto-target-style"); 89 | if (!linkStyle) { 90 | linkStyle = window.document.createElement("style"); 91 | linkStyle.setAttribute("id", "quarto-target-style"); 92 | window.document.head.appendChild(linkStyle); 93 | } 94 | while (linkStyle.firstChild) { 95 | linkStyle.removeChild(linkStyle.firstChild); 96 | } 97 | if (topOffset > 0) { 98 | linkStyle.appendChild( 99 | window.document.createTextNode(` 100 | section:target::before { 101 | content: ""; 102 | display: block; 103 | height: ${topOffset}px; 104 | margin: -${topOffset}px 0 0; 105 | }`) 106 | ); 107 | } 108 | if (init) { 109 | window.dispatchEvent(headroomChanged); 110 | } 111 | init = true; 112 | } 113 | 114 | // initialize headroom 115 | var header = window.document.querySelector("#quarto-header"); 116 | if (header && window.Headroom) { 117 | const headroom = new window.Headroom(header, { 118 | tolerance: 5, 119 | onPin: function () { 120 | const sidebars = window.document.querySelectorAll( 121 | ".sidebar, .headroom-target" 122 | ); 123 | sidebars.forEach((sidebar) => { 124 | sidebar.classList.remove("sidebar-unpinned"); 125 | }); 126 | updateDocumentOffset(); 127 | }, 128 | onUnpin: function () { 129 | const sidebars = window.document.querySelectorAll( 130 | ".sidebar, .headroom-target" 131 | ); 132 | sidebars.forEach((sidebar) => { 133 | sidebar.classList.add("sidebar-unpinned"); 134 | }); 135 | updateDocumentOffset(); 136 | }, 137 | }); 138 | headroom.init(); 139 | 140 | let frozen = false; 141 | window.quartoToggleHeadroom = function () { 142 | if (frozen) { 143 | headroom.unfreeze(); 144 | frozen = false; 145 | } else { 146 | headroom.freeze(); 147 | frozen = true; 148 | } 149 | }; 150 | } 151 | 152 | // Observe size changed for the header 153 | const headerEl = window.document.querySelector("header.fixed-top"); 154 | if (headerEl && window.ResizeObserver) { 155 | const observer = new window.ResizeObserver( 156 | updateDocumentOffsetWithoutAnimation 157 | ); 158 | observer.observe(headerEl, { 159 | attributes: true, 160 | childList: true, 161 | characterData: true, 162 | }); 163 | } else { 164 | window.addEventListener( 165 | "resize", 166 | throttle(updateDocumentOffsetWithoutAnimation, 50) 167 | ); 168 | } 169 | setTimeout(updateDocumentOffsetWithoutAnimation, 250); 170 | 171 | // fixup index.html links if we aren't on the filesystem 172 | if (window.location.protocol !== "file:") { 173 | const links = window.document.querySelectorAll("a"); 174 | for (let i = 0; i < links.length; i++) { 175 | links[i].href = links[i].href.replace(/\/index\.html/, "/"); 176 | } 177 | 178 | // Fixup any sharing links that require urls 179 | // Append url to any sharing urls 180 | const sharingLinks = window.document.querySelectorAll( 181 | "a.sidebar-tools-main-item" 182 | ); 183 | for (let i = 0; i < sharingLinks.length; i++) { 184 | const sharingLink = sharingLinks[i]; 185 | const href = sharingLink.getAttribute("href"); 186 | if (href) { 187 | sharingLink.setAttribute( 188 | "href", 189 | href.replace("|url|", window.location.href) 190 | ); 191 | } 192 | } 193 | 194 | // Scroll the active navigation item into view, if necessary 195 | const navSidebar = window.document.querySelector("nav#quarto-sidebar"); 196 | if (navSidebar) { 197 | // Find the active item 198 | const activeItem = navSidebar.querySelector("li.sidebar-item a.active"); 199 | if (activeItem) { 200 | // Wait for the scroll height and height to resolve by observing size changes on the 201 | // nav element that is scrollable 202 | const resizeObserver = new ResizeObserver((_entries) => { 203 | // The bottom of the element 204 | const elBottom = activeItem.offsetTop; 205 | const viewBottom = navSidebar.scrollTop + navSidebar.clientHeight; 206 | 207 | // The element height and scroll height are the same, then we are still loading 208 | if (viewBottom !== navSidebar.scrollHeight) { 209 | // Determine if the item isn't visible and scroll to it 210 | if (elBottom >= viewBottom) { 211 | navSidebar.scrollTop = elBottom; 212 | } 213 | 214 | // stop observing now since we've completed the scroll 215 | resizeObserver.unobserve(navSidebar); 216 | } 217 | }); 218 | resizeObserver.observe(navSidebar); 219 | } 220 | } 221 | } 222 | }); 223 | -------------------------------------------------------------------------------- /docs/site_libs/quarto-search/fuse.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Fuse.js v6.5.3 - Lightweight fuzzy-search (http://fusejs.io) 3 | * 4 | * Copyright (c) 2021 Kiro Risk (http://kiro.me) 5 | * All Rights Reserved. Apache Software License 2.0 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | */ 9 | var e,t;e=this,t=function(){"use strict";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function t(t){for(var n=1;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:1,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:3,n=new Map,r=Math.pow(10,t);return{get:function(t){var i=t.match(C).length;if(n.has(i))return n.get(i);var o=1/Math.pow(i,.5*e),c=parseFloat(Math.round(o*r)/r);return n.set(i,c),c},clear:function(){n.clear()}}}var $=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.getFn,i=void 0===n?I.getFn:n,o=t.fieldNormWeight,c=void 0===o?I.fieldNormWeight:o;r(this,e),this.norm=E(c,3),this.getFn=i,this.isCreated=!1,this.setIndexRecords()}return o(e,[{key:"setSources",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.docs=e}},{key:"setIndexRecords",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.records=e}},{key:"setKeys",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.keys=t,this._keysMap={},t.forEach((function(t,n){e._keysMap[t.id]=n}))}},{key:"create",value:function(){var e=this;!this.isCreated&&this.docs.length&&(this.isCreated=!0,g(this.docs[0])?this.docs.forEach((function(t,n){e._addString(t,n)})):this.docs.forEach((function(t,n){e._addObject(t,n)})),this.norm.clear())}},{key:"add",value:function(e){var t=this.size();g(e)?this._addString(e,t):this._addObject(e,t)}},{key:"removeAt",value:function(e){this.records.splice(e,1);for(var t=e,n=this.size();t2&&void 0!==arguments[2]?arguments[2]:{},r=n.getFn,i=void 0===r?I.getFn:r,o=n.fieldNormWeight,c=void 0===o?I.fieldNormWeight:o,a=new $({getFn:i,fieldNormWeight:c});return a.setKeys(e.map(_)),a.setSources(t),a.create(),a}function F(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.errors,r=void 0===n?0:n,i=t.currentLocation,o=void 0===i?0:i,c=t.expectedLocation,a=void 0===c?0:c,s=t.distance,u=void 0===s?I.distance:s,h=t.ignoreLocation,f=void 0===h?I.ignoreLocation:h,l=r/e.length;if(f)return l;var d=Math.abs(a-o);return u?l+d/u:d?1:l}function N(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:I.minMatchCharLength,n=[],r=-1,i=-1,o=0,c=e.length;o=t&&n.push([r,i]),r=-1)}return e[o-1]&&o-r>=t&&n.push([r,o-1]),n}var P=32;function W(e){for(var t={},n=0,r=e.length;n1&&void 0!==arguments[1]?arguments[1]:{},o=i.location,c=void 0===o?I.location:o,a=i.threshold,s=void 0===a?I.threshold:a,u=i.distance,h=void 0===u?I.distance:u,f=i.includeMatches,l=void 0===f?I.includeMatches:f,d=i.findAllMatches,v=void 0===d?I.findAllMatches:d,g=i.minMatchCharLength,y=void 0===g?I.minMatchCharLength:g,p=i.isCaseSensitive,m=void 0===p?I.isCaseSensitive:p,k=i.ignoreLocation,M=void 0===k?I.ignoreLocation:k;if(r(this,e),this.options={location:c,threshold:s,distance:h,includeMatches:l,findAllMatches:v,minMatchCharLength:y,isCaseSensitive:m,ignoreLocation:M},this.pattern=m?t:t.toLowerCase(),this.chunks=[],this.pattern.length){var b=function(e,t){n.chunks.push({pattern:e,alphabet:W(e),startIndex:t})},x=this.pattern.length;if(x>P){for(var w=0,L=x%P,S=x-L;w3&&void 0!==arguments[3]?arguments[3]:{},i=r.location,o=void 0===i?I.location:i,c=r.distance,a=void 0===c?I.distance:c,s=r.threshold,u=void 0===s?I.threshold:s,h=r.findAllMatches,f=void 0===h?I.findAllMatches:h,l=r.minMatchCharLength,d=void 0===l?I.minMatchCharLength:l,v=r.includeMatches,g=void 0===v?I.includeMatches:v,y=r.ignoreLocation,p=void 0===y?I.ignoreLocation:y;if(t.length>P)throw new Error(w(P));for(var m,k=t.length,M=e.length,b=Math.max(0,Math.min(o,M)),x=u,L=b,S=d>1||g,_=S?Array(M):[];(m=e.indexOf(t,L))>-1;){var O=F(t,{currentLocation:m,expectedLocation:b,distance:a,ignoreLocation:p});if(x=Math.min(O,x),L=m+k,S)for(var j=0;j=z;q-=1){var B=q-1,J=n[e.charAt(B)];if(S&&(_[B]=+!!J),K[q]=(K[q+1]<<1|1)&J,R&&(K[q]|=(A[q+1]|A[q])<<1|1|A[q+1]),K[q]&$&&(C=F(t,{errors:R,currentLocation:B,expectedLocation:b,distance:a,ignoreLocation:p}))<=x){if(x=C,(L=B)<=b)break;z=Math.max(1,2*b-L)}}if(F(t,{errors:R+1,currentLocation:b,expectedLocation:b,distance:a,ignoreLocation:p})>x)break;A=K}var U={isMatch:L>=0,score:Math.max(.001,C)};if(S){var V=N(_,d);V.length?g&&(U.indices=V):U.isMatch=!1}return U}(e,n,i,{location:c+o,distance:a,threshold:s,findAllMatches:u,minMatchCharLength:h,includeMatches:r,ignoreLocation:f}),p=y.isMatch,m=y.score,k=y.indices;p&&(g=!0),v+=m,p&&k&&(d=[].concat(l(d),l(k)))}));var y={isMatch:g,score:g?v/this.chunks.length:1};return g&&r&&(y.indices=d),y}}]),e}(),z=function(){function e(t){r(this,e),this.pattern=t}return o(e,[{key:"search",value:function(){}}],[{key:"isMultiMatch",value:function(e){return D(e,this.multiRegex)}},{key:"isSingleMatch",value:function(e){return D(e,this.singleRegex)}}]),e}();function D(e,t){var n=e.match(t);return n?n[1]:null}var K=function(e){a(n,e);var t=f(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}],[{key:"type",get:function(){return"exact"}},{key:"multiRegex",get:function(){return/^="(.*)"$/}},{key:"singleRegex",get:function(){return/^=(.*)$/}}]),n}(z),q=function(e){a(n,e);var t=f(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=-1===e.indexOf(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-exact"}},{key:"multiRegex",get:function(){return/^!"(.*)"$/}},{key:"singleRegex",get:function(){return/^!(.*)$/}}]),n}(z),B=function(e){a(n,e);var t=f(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}],[{key:"type",get:function(){return"prefix-exact"}},{key:"multiRegex",get:function(){return/^\^"(.*)"$/}},{key:"singleRegex",get:function(){return/^\^(.*)$/}}]),n}(z),J=function(e){a(n,e);var t=f(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-prefix-exact"}},{key:"multiRegex",get:function(){return/^!\^"(.*)"$/}},{key:"singleRegex",get:function(){return/^!\^(.*)$/}}]),n}(z),U=function(e){a(n,e);var t=f(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}}],[{key:"type",get:function(){return"suffix-exact"}},{key:"multiRegex",get:function(){return/^"(.*)"\$$/}},{key:"singleRegex",get:function(){return/^(.*)\$$/}}]),n}(z),V=function(e){a(n,e);var t=f(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){var t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-suffix-exact"}},{key:"multiRegex",get:function(){return/^!"(.*)"\$$/}},{key:"singleRegex",get:function(){return/^!(.*)\$$/}}]),n}(z),G=function(e){a(n,e);var t=f(n);function n(e){var i,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},c=o.location,a=void 0===c?I.location:c,s=o.threshold,u=void 0===s?I.threshold:s,h=o.distance,f=void 0===h?I.distance:h,l=o.includeMatches,d=void 0===l?I.includeMatches:l,v=o.findAllMatches,g=void 0===v?I.findAllMatches:v,y=o.minMatchCharLength,p=void 0===y?I.minMatchCharLength:y,m=o.isCaseSensitive,k=void 0===m?I.isCaseSensitive:m,M=o.ignoreLocation,b=void 0===M?I.ignoreLocation:M;return r(this,n),(i=t.call(this,e))._bitapSearch=new T(e,{location:a,threshold:u,distance:f,includeMatches:d,findAllMatches:g,minMatchCharLength:p,isCaseSensitive:k,ignoreLocation:b}),i}return o(n,[{key:"search",value:function(e){return this._bitapSearch.searchIn(e)}}],[{key:"type",get:function(){return"fuzzy"}},{key:"multiRegex",get:function(){return/^"(.*)"$/}},{key:"singleRegex",get:function(){return/^(.*)$/}}]),n}(z),H=function(e){a(n,e);var t=f(n);function n(e){return r(this,n),t.call(this,e)}return o(n,[{key:"search",value:function(e){for(var t,n=0,r=[],i=this.pattern.length;(t=e.indexOf(this.pattern,n))>-1;)n=t+i,r.push([t,n-1]);var o=!!r.length;return{isMatch:o,score:o?0:1,indices:r}}}],[{key:"type",get:function(){return"include"}},{key:"multiRegex",get:function(){return/^'"(.*)"$/}},{key:"singleRegex",get:function(){return/^'(.*)$/}}]),n}(z),Q=[K,H,B,J,V,U,q,G],X=Q.length,Y=/ +(?=([^\"]*\"[^\"]*\")*[^\"]*$)/;function Z(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.split("|").map((function(e){for(var n=e.trim().split(Y).filter((function(e){return e&&!!e.trim()})),r=[],i=0,o=n.length;i1&&void 0!==arguments[1]?arguments[1]:{},i=n.isCaseSensitive,o=void 0===i?I.isCaseSensitive:i,c=n.includeMatches,a=void 0===c?I.includeMatches:c,s=n.minMatchCharLength,u=void 0===s?I.minMatchCharLength:s,h=n.ignoreLocation,f=void 0===h?I.ignoreLocation:h,l=n.findAllMatches,d=void 0===l?I.findAllMatches:l,v=n.location,g=void 0===v?I.location:v,y=n.threshold,p=void 0===y?I.threshold:y,m=n.distance,k=void 0===m?I.distance:m;r(this,e),this.query=null,this.options={isCaseSensitive:o,includeMatches:a,minMatchCharLength:u,findAllMatches:d,ignoreLocation:f,location:g,threshold:p,distance:k},this.pattern=o?t:t.toLowerCase(),this.query=Z(this.pattern,this.options)}return o(e,[{key:"searchIn",value:function(e){var t=this.query;if(!t)return{isMatch:!1,score:1};var n=this.options,r=n.includeMatches;e=n.isCaseSensitive?e:e.toLowerCase();for(var i=0,o=[],c=0,a=0,s=t.length;a-1&&(n.refIndex=e.idx),t.matches.push(n)}}))}function ve(e,t){t.score=e.score}function ge(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.includeMatches,i=void 0===r?I.includeMatches:r,o=n.includeScore,c=void 0===o?I.includeScore:o,a=[];return i&&a.push(de),c&&a.push(ve),e.map((function(e){var n=e.idx,r={item:t[n],refIndex:n};return a.length&&a.forEach((function(t){t(e,r)})),r}))}var ye=function(){function e(n){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2?arguments[2]:void 0;r(this,e),this.options=t(t({},I),i),this.options.useExtendedSearch,this._keyStore=new S(this.options.keys),this.setCollection(n,o)}return o(e,[{key:"setCollection",value:function(e,t){if(this._docs=e,t&&!(t instanceof $))throw new Error("Incorrect 'index' type");this._myIndex=t||R(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}},{key:"add",value:function(e){k(e)&&(this._docs.push(e),this._myIndex.add(e))}},{key:"remove",value:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){return!1},t=[],n=0,r=this._docs.length;n1&&void 0!==arguments[1]?arguments[1]:{},n=t.limit,r=void 0===n?-1:n,i=this.options,o=i.includeMatches,c=i.includeScore,a=i.shouldSort,s=i.sortFn,u=i.ignoreFieldNorm,h=g(e)?g(this._docs[0])?this._searchStringList(e):this._searchObjectList(e):this._searchLogical(e);return le(h,{ignoreFieldNorm:u}),a&&h.sort(s),y(r)&&r>-1&&(h=h.slice(0,r)),ge(h,this._docs,{includeMatches:o,includeScore:c})}},{key:"_searchStringList",value:function(e){var t=re(e,this.options),n=this._myIndex.records,r=[];return n.forEach((function(e){var n=e.v,i=e.i,o=e.n;if(k(n)){var c=t.searchIn(n),a=c.isMatch,s=c.score,u=c.indices;a&&r.push({item:n,idx:i,matches:[{score:s,value:n,norm:o,indices:u}]})}})),r}},{key:"_searchLogical",value:function(e){var t=this,n=function(e,t){var n=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).auto,r=void 0===n||n,i=function e(n){var i=Object.keys(n),o=ue(n);if(!o&&i.length>1&&!se(n))return e(fe(n));if(he(n)){var c=o?n[ce]:i[0],a=o?n[ae]:n[c];if(!g(a))throw new Error(x(c));var s={keyId:j(c),pattern:a};return r&&(s.searcher=re(a,t)),s}var u={children:[],operator:i[0]};return i.forEach((function(t){var r=n[t];v(r)&&r.forEach((function(t){u.children.push(e(t))}))})),u};return se(e)||(e=fe(e)),i(e)}(e,this.options),r=function e(n,r,i){if(!n.children){var o=n.keyId,c=n.searcher,a=t._findMatches({key:t._keyStore.get(o),value:t._myIndex.getValueForItemAtKeyId(r,o),searcher:c});return a&&a.length?[{idx:i,item:r,matches:a}]:[]}for(var s=[],u=0,h=n.children.length;u1&&void 0!==arguments[1]?arguments[1]:{},n=t.getFn,r=void 0===n?I.getFn:n,i=t.fieldNormWeight,o=void 0===i?I.fieldNormWeight:i,c=e.keys,a=e.records,s=new $({getFn:r,fieldNormWeight:o});return s.setKeys(c),s.setIndexRecords(a),s},ye.config=I,function(){ne.push.apply(ne,arguments)}(te),ye},"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Fuse=t(); -------------------------------------------------------------------------------- /images/script_tag_hello_world.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/images/script_tag_hello_world.gif -------------------------------------------------------------------------------- /images/script_tag_hello_world.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/images/script_tag_hello_world.mov -------------------------------------------------------------------------------- /images/vscode_container.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/images/vscode_container.gif -------------------------------------------------------------------------------- /images/vscode_container.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/images/vscode_container.mov -------------------------------------------------------------------------------- /images/vscode_html_template.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/images/vscode_html_template.gif -------------------------------------------------------------------------------- /images/vscode_html_template.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/images/vscode_html_template.mov -------------------------------------------------------------------------------- /images/vscode_live_server.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/images/vscode_live_server.gif -------------------------------------------------------------------------------- /images/vscode_live_server.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RamiKrispin/Introduction-to-JavaScript/157ec36f807c35498d3398a14b5df2962b99b2f0/images/vscode_live_server.mov -------------------------------------------------------------------------------- /index.log: -------------------------------------------------------------------------------- 1 | This is XeTeX, Version 3.141592653-2.6-0.999993 (TeX Live 2022/dev/Debian) (preloaded format=xelatex 2022.11.28) 31 DEC 2022 16:38 2 | entering extended mode 3 | restricted \write18 enabled. 4 | %&-line parsing enabled. 5 | **index.tex 6 | (./index.tex 7 | LaTeX2e <2021-11-15> patch level 1 8 | L3 programming layer <2022-01-21> (/usr/share/texlive/texmf-dist/tex/latex/koma 9 | -script/scrreprt.cls 10 | Document Class: scrreprt 2021/11/13 v3.35 KOMA-Script document class (report) 11 | (/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrkbase.sty 12 | Package: scrkbase 2021/11/13 v3.35 KOMA-Script package (KOMA-Script-dependent b 13 | asics and keyval usage) 14 | (/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrbase.sty 15 | Package: scrbase 2021/11/13 v3.35 KOMA-Script package (KOMA-Script-independent 16 | basics and keyval usage) 17 | (/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrlfile.sty 18 | Package: scrlfile 2021/11/13 v3.35 KOMA-Script package (file load hooks) 19 | (/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrlfile-hook.sty 20 | Package: scrlfile-hook 2021/11/13 v3.35 KOMA-Script package (using LaTeX hooks) 21 | 22 | (/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrlogo.sty 23 | Package: scrlogo 2021/11/13 v3.35 KOMA-Script package (logo) 24 | ))) (/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty 25 | Package: keyval 2014/10/28 v1.15 key=value parser (DPC) 26 | \KV@toks@=\toks16 27 | ) 28 | Applying: [2021/05/01] Usage of raw or classic option list on input line 252. 29 | Already applied: [0000/00/00] Usage of raw or classic option list on input line 30 | 368. 31 | )) (/usr/share/texlive/texmf-dist/tex/latex/koma-script/tocbasic.sty 32 | Package: tocbasic 2021/11/13 v3.35 KOMA-Script package (handling toc-files) 33 | \scr@dte@tocline@numberwidth=\skip47 34 | \scr@dte@tocline@numbox=\box50 35 | ) 36 | Package tocbasic Info: babel extension for `toc' omitted 37 | (tocbasic) because of missing \bbl@set@language on input line 137. 38 | Class scrreprt Info: File `scrsize11pt.clo' used instead of 39 | (scrreprt) file `scrsize11.clo' to setup font sizes on input line 248 40 | 7. 41 | (/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrsize11pt.clo 42 | File: scrsize11pt.clo 2021/11/13 v3.35 KOMA-Script font size class option (11pt 43 | ) 44 | ) (/usr/share/texlive/texmf-dist/tex/latex/koma-script/typearea.sty 45 | Package: typearea 2021/11/13 v3.35 KOMA-Script package (type area) 46 | \ta@bcor=\skip48 47 | \ta@div=\count181 48 | Package typearea Info: You've used standard option `letterpaper'. 49 | (typearea) This is correct! 50 | (typearea) Internally I'm using `paper=letter'. 51 | (typearea) If you'd like to set the option with \KOMAoptions, 52 | (typearea) you'd have to use `paper=letter' there 53 | (typearea) instead of `letterpaper', too. 54 | \ta@hblk=\skip49 55 | \ta@vblk=\skip50 56 | \ta@temp=\skip51 57 | \footheight=\skip52 58 | Package typearea Info: These are the values describing the layout: 59 | (typearea) DIV = 11 60 | (typearea) BCOR = 0.0pt 61 | (typearea) \paperwidth = 614.295pt 62 | (typearea) \textwidth = 446.76004pt 63 | (typearea) DIV departure = -14% 64 | (typearea) \evensidemargin = 11.49748pt 65 | (typearea) \oddsidemargin = 11.49748pt 66 | (typearea) \paperheight = 794.96999pt 67 | (typearea) \textheight = 582.20026pt 68 | (typearea) \topmargin = -37.40001pt 69 | (typearea) \headheight = 17.0pt 70 | (typearea) \headsep = 20.40001pt 71 | (typearea) \topskip = 11.0pt 72 | (typearea) \footskip = 47.6pt 73 | (typearea) \baselineskip = 13.6pt 74 | (typearea) on input line 1743. 75 | ) 76 | \c@part=\count182 77 | \c@chapter=\count183 78 | \c@section=\count184 79 | \c@subsection=\count185 80 | \c@subsubsection=\count186 81 | \c@paragraph=\count187 82 | \c@subparagraph=\count188 83 | \scr@dte@chapter@maxnumwidth=\skip53 84 | Class scrreprt Info: using compatibility default `afterindent=bysign' 85 | (scrreprt) for `\chapter on input line 5717. 86 | \scr@dte@section@maxnumwidth=\skip54 87 | Class scrreprt Info: using compatibility default `runin=bysign' 88 | (scrreprt) for `\section on input line 5728. 89 | Class scrreprt Info: using compatibility default `afterindent=bysign' 90 | (scrreprt) for `\section on input line 5728. 91 | \scr@dte@part@maxnumwidth=\skip55 92 | Class scrreprt Info: using compatibility default `afterindent=true' 93 | (scrreprt) for `\part on input line 5737. 94 | \scr@dte@subsection@maxnumwidth=\skip56 95 | Class scrreprt Info: using compatibility default `runin=bysign' 96 | (scrreprt) for `\subsection on input line 5747. 97 | Class scrreprt Info: using compatibility default `afterindent=bysign' 98 | (scrreprt) for `\subsection on input line 5747. 99 | \scr@dte@subsubsection@maxnumwidth=\skip57 100 | Class scrreprt Info: using compatibility default `runin=bysign' 101 | (scrreprt) for `\subsubsection on input line 5757. 102 | Class scrreprt Info: using compatibility default `afterindent=bysign' 103 | (scrreprt) for `\subsubsection on input line 5757. 104 | \scr@dte@paragraph@maxnumwidth=\skip58 105 | Class scrreprt Info: using compatibility default `runin=bysign' 106 | (scrreprt) for `\paragraph on input line 5768. 107 | Class scrreprt Info: using compatibility default `afterindent=bysign' 108 | (scrreprt) for `\paragraph on input line 5768. 109 | \scr@dte@subparagraph@maxnumwidth=\skip59 110 | Class scrreprt Info: using compatibility default `runin=bysign' 111 | (scrreprt) for `\subparagraph on input line 5778. 112 | Class scrreprt Info: using compatibility default `afterindent=bysign' 113 | (scrreprt) for `\subparagraph on input line 5778. 114 | \abovecaptionskip=\skip60 115 | \belowcaptionskip=\skip61 116 | \c@pti@nb@sid@b@x=\box51 117 | Package tocbasic Info: babel extension for `lof' omitted 118 | (tocbasic) because of missing \bbl@set@language on input line 6958. 119 | 120 | \scr@dte@figure@maxnumwidth=\skip62 121 | \c@figure=\count189 122 | Package tocbasic Info: babel extension for `lot' omitted 123 | (tocbasic) because of missing \bbl@set@language on input line 6974. 124 | 125 | \scr@dte@table@maxnumwidth=\skip63 126 | \c@table=\count190 127 | Class scrreprt Info: Redefining `\numberline' on input line 7142. 128 | \bibindent=\dimen138 129 | ) (/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty 130 | Package: amsmath 2021/10/15 v2.17l AMS math features 131 | \@mathmargin=\skip64 132 | For additional information on amsmath, use the `?' option. 133 | (/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty 134 | Package: amstext 2021/08/26 v2.01 AMS text 135 | (/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty 136 | File: amsgen.sty 1999/11/30 v2.0 generic functions 137 | \@emptytoks=\toks17 138 | \ex@=\dimen139 139 | )) (/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty 140 | Package: amsbsy 1999/11/29 v1.2d Bold Symbols 141 | \pmbraise@=\dimen140 142 | ) (/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty 143 | Package: amsopn 2021/08/26 v2.02 operator names 144 | ) 145 | \inf@bad=\count191 146 | LaTeX Info: Redefining \frac on input line 234. 147 | \uproot@=\count192 148 | \leftroot@=\count193 149 | LaTeX Info: Redefining \overline on input line 399. 150 | \classnum@=\count194 151 | \DOTSCASE@=\count195 152 | LaTeX Info: Redefining \ldots on input line 496. 153 | LaTeX Info: Redefining \dots on input line 499. 154 | LaTeX Info: Redefining \cdots on input line 620. 155 | \Mathstrutbox@=\box52 156 | \strutbox@=\box53 157 | \big@size=\dimen141 158 | LaTeX Font Info: Redeclaring font encoding OML on input line 743. 159 | LaTeX Font Info: Redeclaring font encoding OMS on input line 744. 160 | \macc@depth=\count196 161 | \c@MaxMatrixCols=\count197 162 | \dotsspace@=\muskip16 163 | \c@parentequation=\count198 164 | \dspbrk@lvl=\count199 165 | \tag@help=\toks18 166 | \row@=\count266 167 | \column@=\count267 168 | \maxfields@=\count268 169 | \andhelp@=\toks19 170 | \eqnshift@=\dimen142 171 | \alignsep@=\dimen143 172 | \tagshift@=\dimen144 173 | \tagwidth@=\dimen145 174 | \totwidth@=\dimen146 175 | \lineht@=\dimen147 176 | \@envbody=\toks20 177 | \multlinegap=\skip65 178 | \multlinetaggap=\skip66 179 | \mathdisplay@stack=\toks21 180 | LaTeX Info: Redefining \[ on input line 2938. 181 | LaTeX Info: Redefining \] on input line 2939. 182 | ) (/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty 183 | Package: amssymb 2013/01/14 v3.01 AMS font symbols 184 | (/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty 185 | Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support 186 | \symAMSa=\mathgroup4 187 | \symAMSb=\mathgroup5 188 | LaTeX Font Info: Redeclaring math symbol \hbar on input line 98. 189 | LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' 190 | (Font) U/euf/m/n --> U/euf/b/n on input line 106. 191 | )) 192 | 193 | ! LaTeX Error: File `lmodern.sty' not found. 194 | 195 | Type X to quit or to proceed, 196 | or enter new name. (Default extension: sty) 197 | 198 | Enter file name: 199 | ! Emergency stop. 200 | 201 | 202 | l.13 \usepackage 203 | {iftex}^^M 204 | Here is how much of TeX's memory you used: 205 | 4414 strings out of 478214 206 | 90426 string characters out of 5855575 207 | 517240 words of memory out of 5000000 208 | 25040 multiletter control sequences out of 15000+600000 209 | 469267 words of font info for 29 fonts, out of 8000000 for 9000 210 | 14 hyphenation exceptions out of 8191 211 | 108i,1n,106p,10600b,270s stack positions out of 5000i,500n,10000p,200000b,80000s 212 | 213 | No pages of output. 214 | -------------------------------------------------------------------------------- /index.qmd: -------------------------------------------------------------------------------- 1 | # Preface {.unnumbered} 2 | 3 | WIP...pre spelling check 4 | 5 | This tutorial covers the basic functionality operations of the JavaScript (JS) language, covering the following topics: 6 | 7 | * Setting VScode environment 8 | * Basic workflow 9 | * Variables 10 | * Functions 11 | * Data structure 12 | 13 | ## Prerequisites 14 | 15 | Here are the assumptions I made when I created this tutorial: 16 | 17 | * No previous knowledge of JS 18 | * Have basic knowledge of another programming language (e.g., Python, R, Julia, etc.), and an understanding of the use of variables assignment and functions 19 | 20 | In addition, we will use some basic HTML and CSS throughout the tutorial, don’t worry if you are unfamiliar with those languages. 21 | 22 | 23 | -------------------------------------------------------------------------------- /index.tex: -------------------------------------------------------------------------------- 1 | % Options for packages loaded elsewhere 2 | \PassOptionsToPackage{unicode}{hyperref} 3 | \PassOptionsToPackage{hyphens}{url} 4 | \PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor} 5 | % 6 | \documentclass[ 7 | letterpaper, 8 | DIV=11, 9 | numbers=noendperiod]{scrreprt} 10 | 11 | \usepackage{amsmath,amssymb} 12 | \usepackage{lmodern} 13 | \usepackage{iftex} 14 | \ifPDFTeX 15 | \usepackage[T1]{fontenc} 16 | \usepackage[utf8]{inputenc} 17 | \usepackage{textcomp} % provide euro and other symbols 18 | \else % if luatex or xetex 19 | \usepackage{unicode-math} 20 | \defaultfontfeatures{Scale=MatchLowercase} 21 | \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1} 22 | \fi 23 | % Use upquote if available, for straight quotes in verbatim environments 24 | \IfFileExists{upquote.sty}{\usepackage{upquote}}{} 25 | \IfFileExists{microtype.sty}{% use microtype if available 26 | \usepackage[]{microtype} 27 | \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts 28 | }{} 29 | \makeatletter 30 | \@ifundefined{KOMAClassName}{% if non-KOMA class 31 | \IfFileExists{parskip.sty}{% 32 | \usepackage{parskip} 33 | }{% else 34 | \setlength{\parindent}{0pt} 35 | \setlength{\parskip}{6pt plus 2pt minus 1pt}} 36 | }{% if KOMA class 37 | \KOMAoptions{parskip=half}} 38 | \makeatother 39 | \usepackage{xcolor} 40 | \setlength{\emergencystretch}{3em} % prevent overfull lines 41 | \setcounter{secnumdepth}{5} 42 | % Make \paragraph and \subparagraph free-standing 43 | \ifx\paragraph\undefined\else 44 | \let\oldparagraph\paragraph 45 | \renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}} 46 | \fi 47 | \ifx\subparagraph\undefined\else 48 | \let\oldsubparagraph\subparagraph 49 | \renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}} 50 | \fi 51 | 52 | \usepackage{color} 53 | \usepackage{fancyvrb} 54 | \newcommand{\VerbBar}{|} 55 | \newcommand{\VERB}{\Verb[commandchars=\\\{\}]} 56 | \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} 57 | % Add ',fontsize=\small' for more characters per line 58 | \usepackage{framed} 59 | \definecolor{shadecolor}{RGB}{241,243,245} 60 | \newenvironment{Shaded}{\begin{snugshade}}{\end{snugshade}} 61 | \newcommand{\AlertTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} 62 | \newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}} 63 | \newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.40,0.45,0.13}{#1}} 64 | \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} 65 | \newcommand{\BuiltInTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} 66 | \newcommand{\CharTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}} 67 | \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}} 68 | \newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}} 69 | \newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{#1}} 70 | \newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} 71 | \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} 72 | \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} 73 | \newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}} 74 | \newcommand{\ErrorTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} 75 | \newcommand{\ExtensionTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} 76 | \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} 77 | \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.28,0.35,0.67}{#1}} 78 | \newcommand{\ImportTok}[1]{\textcolor[rgb]{0.00,0.46,0.62}{#1}} 79 | \newcommand{\InformationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}} 80 | \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} 81 | \newcommand{\NormalTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} 82 | \newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}} 83 | \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} 84 | \newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} 85 | \newcommand{\RegionMarkerTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} 86 | \newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}} 87 | \newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}} 88 | \newcommand{\StringTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}} 89 | \newcommand{\VariableTok}[1]{\textcolor[rgb]{0.07,0.07,0.07}{#1}} 90 | \newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}} 91 | \newcommand{\WarningTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}} 92 | 93 | \providecommand{\tightlist}{% 94 | \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}\usepackage{longtable,booktabs,array} 95 | \usepackage{calc} % for calculating minipage widths 96 | % Correct order of tables after \paragraph or \subparagraph 97 | \usepackage{etoolbox} 98 | \makeatletter 99 | \patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{} 100 | \makeatother 101 | % Allow footnotes in longtable head/foot 102 | \IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}} 103 | \makesavenoteenv{longtable} 104 | \usepackage{graphicx} 105 | \makeatletter 106 | \def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi} 107 | \def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi} 108 | \makeatother 109 | % Scale images if necessary, so that they will not overflow the page 110 | % margins by default, and it is still possible to overwrite the defaults 111 | % using explicit options in \includegraphics[width, height, ...]{} 112 | \setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio} 113 | % Set default figure placement to htbp 114 | \makeatletter 115 | \def\fps@figure{htbp} 116 | \makeatother 117 | \newlength{\cslhangindent} 118 | \setlength{\cslhangindent}{1.5em} 119 | \newlength{\csllabelwidth} 120 | \setlength{\csllabelwidth}{3em} 121 | \newlength{\cslentryspacingunit} % times entry-spacing 122 | \setlength{\cslentryspacingunit}{\parskip} 123 | \newenvironment{CSLReferences}[2] % #1 hanging-ident, #2 entry spacing 124 | {% don't indent paragraphs 125 | \setlength{\parindent}{0pt} 126 | % turn on hanging indent if param 1 is 1 127 | \ifodd #1 128 | \let\oldpar\par 129 | \def\par{\hangindent=\cslhangindent\oldpar} 130 | \fi 131 | % set entry spacing 132 | \setlength{\parskip}{#2\cslentryspacingunit} 133 | }% 134 | {} 135 | \usepackage{calc} 136 | \newcommand{\CSLBlock}[1]{#1\hfill\break} 137 | \newcommand{\CSLLeftMargin}[1]{\parbox[t]{\csllabelwidth}{#1}} 138 | \newcommand{\CSLRightInline}[1]{\parbox[t]{\linewidth - \csllabelwidth}{#1}\break} 139 | \newcommand{\CSLIndent}[1]{\hspace{\cslhangindent}#1} 140 | 141 | \KOMAoption{captions}{tableheading} 142 | \makeatletter 143 | \makeatother 144 | \makeatletter 145 | \@ifpackageloaded{bookmark}{}{\usepackage{bookmark}} 146 | \makeatother 147 | \makeatletter 148 | \@ifpackageloaded{caption}{}{\usepackage{caption}} 149 | \AtBeginDocument{% 150 | \ifdefined\contentsname 151 | \renewcommand*\contentsname{Table of contents} 152 | \else 153 | \newcommand\contentsname{Table of contents} 154 | \fi 155 | \ifdefined\listfigurename 156 | \renewcommand*\listfigurename{List of Figures} 157 | \else 158 | \newcommand\listfigurename{List of Figures} 159 | \fi 160 | \ifdefined\listtablename 161 | \renewcommand*\listtablename{List of Tables} 162 | \else 163 | \newcommand\listtablename{List of Tables} 164 | \fi 165 | \ifdefined\figurename 166 | \renewcommand*\figurename{Figure} 167 | \else 168 | \newcommand\figurename{Figure} 169 | \fi 170 | \ifdefined\tablename 171 | \renewcommand*\tablename{Table} 172 | \else 173 | \newcommand\tablename{Table} 174 | \fi 175 | } 176 | \@ifpackageloaded{float}{}{\usepackage{float}} 177 | \floatstyle{ruled} 178 | \@ifundefined{c@chapter}{\newfloat{codelisting}{h}{lop}}{\newfloat{codelisting}{h}{lop}[chapter]} 179 | \floatname{codelisting}{Listing} 180 | \newcommand*\listoflistings{\listof{codelisting}{List of Listings}} 181 | \makeatother 182 | \makeatletter 183 | \@ifpackageloaded{caption}{}{\usepackage{caption}} 184 | \@ifpackageloaded{subcaption}{}{\usepackage{subcaption}} 185 | \makeatother 186 | \makeatletter 187 | \@ifpackageloaded{tcolorbox}{}{\usepackage[many]{tcolorbox}} 188 | \makeatother 189 | \makeatletter 190 | \@ifundefined{shadecolor}{\definecolor{shadecolor}{rgb}{.97, .97, .97}} 191 | \makeatother 192 | \makeatletter 193 | \makeatother 194 | \ifLuaTeX 195 | \usepackage{selnolig} % disable illegal ligatures 196 | \fi 197 | \IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}} 198 | \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available 199 | \urlstyle{same} % disable monospaced font for URLs 200 | \hypersetup{ 201 | pdftitle={Introduction to JavaScript}, 202 | pdfauthor={Rami Krispin}, 203 | colorlinks=true, 204 | linkcolor={blue}, 205 | filecolor={Maroon}, 206 | citecolor={Blue}, 207 | urlcolor={Blue}, 208 | pdfcreator={LaTeX via pandoc}} 209 | 210 | \title{Introduction to JavaScript} 211 | \author{Rami Krispin} 212 | \date{1/1/23} 213 | 214 | \begin{document} 215 | \maketitle 216 | \ifdefined\Shaded\renewenvironment{Shaded}{\begin{tcolorbox}[breakable, borderline west={3pt}{0pt}{shadecolor}, frame hidden, sharp corners, enhanced, boxrule=0pt, interior hidden]}{\end{tcolorbox}}\fi 217 | 218 | \renewcommand*\contentsname{Table of contents} 219 | { 220 | \hypersetup{linkcolor=} 221 | \setcounter{tocdepth}{2} 222 | \tableofcontents 223 | } 224 | \bookmarksetup{startatroot} 225 | 226 | \hypertarget{preface}{% 227 | \chapter*{Preface}\label{preface}} 228 | \addcontentsline{toc}{chapter}{Preface} 229 | 230 | \markboth{Preface}{Preface} 231 | 232 | WIP\ldots pre spelling check 233 | 234 | This tutorial covers the basic functionality operations of the 235 | JavaScript (JS) language, covering the following topics: 236 | 237 | \begin{itemize} 238 | \tightlist 239 | \item 240 | Setting VScode environment 241 | \item 242 | Basic workflow 243 | \item 244 | Variables 245 | \item 246 | Functions 247 | \item 248 | Data structure 249 | \end{itemize} 250 | 251 | \hypertarget{prerequisites}{% 252 | \section*{Prerequisites}\label{prerequisites}} 253 | \addcontentsline{toc}{section}{Prerequisites} 254 | 255 | \markright{Prerequisites} 256 | 257 | Here are the assumptions I made when I created this tutorial: 258 | 259 | \begin{itemize} 260 | \tightlist 261 | \item 262 | No previous knowledge of JS 263 | \item 264 | Have basic knowledge of another programming language (e.g., Python, R, 265 | Julia, etc.), and an understanding of the use of variables assignment 266 | and functions 267 | \end{itemize} 268 | 269 | In addition, we will use some basic HTML and CSS throughout the 270 | tutorial, don't worry if you are unfamiliar with those languages. 271 | 272 | \bookmarksetup{startatroot} 273 | 274 | \hypertarget{settings}{% 275 | \chapter{Settings}\label{settings}} 276 | 277 | WIP\ldots pre spelling check 278 | 279 | Before getting started, let's set the development environment. There are 280 | many ways to develop and execute JavaScript. For this tutorial, I use 281 | VScode, which has great integrations with JavaScript, HTML, and CSS and 282 | seamless integration with Docker. In addition, it has great integration 283 | with Quarto, which was used to create this document. If you want to 284 | follow the same settings, check the instructions below. 285 | 286 | \hypertarget{vscode-settings-for-javascript}{% 287 | \subsection{VScode Settings for 288 | JavaScript}\label{vscode-settings-for-javascript}} 289 | 290 | If you don't have VScode installed, you can download and install it 291 | directly from the \href{https://code.visualstudio.com/}{VScode website}. 292 | I also use the following extensions: 293 | 294 | \begin{itemize} 295 | \tightlist 296 | \item 297 | \href{https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer}{Live 298 | Server} extension, which enables you to launch a local development 299 | server with a live reload feature for static \& dynamic pages 300 | \item 301 | \href{https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers}{Dev 302 | Containers} extension, supporting development on VScode with Docker 303 | containers 304 | \end{itemize} 305 | 306 | \hypertarget{setting-docker-environment}{% 307 | \subsection{Setting Docker 308 | Environment}\label{setting-docker-environment}} 309 | 310 | One of the main reasons I love using VScode is the seamless integration 311 | with Docker. It enables you to develop in your local folder while 312 | executing the code inside the image. Here is what you need to set your 313 | VScode to run inside a Docker image: 314 | 315 | \begin{itemize} 316 | \tightlist 317 | \item 318 | Docker Desktop (or equivalent) install on your machine (download and 319 | install it from 320 | \href{https://www.docker.com/products/docker-desktop/}{here}) 321 | \item 322 | Docker 323 | \href{https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker}{extension} 324 | for VScode 325 | \item 326 | Set the supporting image, 327 | \href{https://github.com/RamiKrispin/Tutorials/tree/main/docker}{here} 328 | are the Docker settings I am using for this tutorial 329 | \item 330 | Create the devcontainer.json file with your container settings (image 331 | name, environment variables, extension names, etc.), 332 | \href{https://github.com/RamiKrispin/Tutorials/blob/main/.devcontainer/devcontainer.json}{here} 333 | is my \texttt{devcontainer.json} file setting 334 | \item 335 | Open the folder inside the container (see the screenshot below) 336 | \end{itemize} 337 | 338 | You can read more about setting and using Docker with VScode on 339 | \href{https://code.visualstudio.com/docs/containers/overview}{VScode's 340 | documentation}. 341 | 342 | If you want to leverage the tutorial Docker settings, you can clone the 343 | repository and follow the next steps: 344 | 345 | \begin{itemize} 346 | \tightlist 347 | \item 348 | Open the tutorial repository's folder on VScode 349 | \item 350 | Open the \texttt{Command\ Palette} (⇧⌘P in Mac, Ctrl+Shift+P in 351 | Windows) or use the \texttt{Open\ Remote\ Window} button (on the 352 | bottom left side, see the screen recording above) and type 353 | \texttt{Open\ Folder\ in\ Container}. 354 | \end{itemize} 355 | 356 | \textbf{Note:} It might take few minutes on the first time opening the 357 | container, as it pull the docker image from 358 | \href{https://hub.docker.com/repository/docker/rkrispin/tutorial}{Docker 359 | Hub}. 360 | 361 | \hypertarget{workflow}{% 362 | \section{Workflow}\label{workflow}} 363 | 364 | JavaScript (also known as JS), is one of the most popular programming 365 | languages for web development. It is typically used to create web page 366 | applications, mobile apps, games, and great data visualization tools 367 | (D3, Observable Plot, Leaflet, Charts, etc.). You can run JavaScript on 368 | your web browser (e.g., Chrome, Safari, Firefox, etc.): 369 | 370 | \textbf{Screen record here}* 371 | 372 | While you can use your web browser as a consul for ad-hoc code tests, 373 | the development of JS applications is done inside a script using a code 374 | editor such VScode, notepad, etc. It is common to have JS code embedded 375 | inside HTML script (or call JS script from HTML script). 376 | 377 | \hypertarget{file-structure}{% 378 | \subsection{File structure}\label{file-structure}} 379 | 380 | In this tutorial, we will adopt the basic framework for running JS code 381 | on the browser by setting a web page with an HTML file 382 | (\texttt{index.html}) and leveraging it to call a JS file 383 | (\texttt{index.js}) with our JS code. In addition, we will use a CSS 384 | file (\texttt{style.css}) to set the web page style. I will set those 385 | files under the 386 | \href{https://github.com/RamiKrispin/Tutorials/tree/main/JavaScript}{JavaScript 387 | folder}: 388 | 389 | \begin{Shaded} 390 | \begin{Highlighting}[] 391 | \NormalTok{.} 392 | \NormalTok{├── index.html} 393 | \NormalTok{├── index.js} 394 | \NormalTok{└── style.ccs} 395 | \end{Highlighting} 396 | \end{Shaded} 397 | 398 | \textbf{Note:} For convenience, I placed the three files in the same 399 | folder. However, if you wish to arrange it differently, you can easily 400 | reference the \texttt{index.js} and \texttt{style.css} file paths from 401 | the \texttt{index.html} file. 402 | 403 | Don't worry if you are not familiar with HTML or CSS. We will use the 404 | basic templates to set those files. Let's start by creating three empty 405 | files using the file names above. To set the HTML file, we will use the 406 | VScode HTML code snippet template by typing the \texttt{!} symbol and 407 | press enter: 408 | 409 | In a nutshell, the HTML language is based on code chunks nested by tags. 410 | The tags define the code's functionality. Here is the most common tag 411 | structure: 412 | 413 | \begin{Shaded} 414 | \begin{Highlighting}[] 415 | \KeywordTok{\textless{}tag\_name\textgreater{}}\NormalTok{ arguments and expressions }\KeywordTok{\textless{}/tag\_name\textgreater{}} 416 | \end{Highlighting} 417 | \end{Shaded} 418 | 419 | In this HTML structure, the element is nested by the tag name. In both 420 | cases, the tag is enclosed within \texttt{\textless{}\ \textgreater{}} 421 | brackets, where the closing tag is marked with \texttt{/} symbol before 422 | the tag. For example, we will use the title tag to define the web page 423 | title: 424 | 425 | \begin{Shaded} 426 | \begin{Highlighting}[] 427 | \KeywordTok{\textless{}title\textgreater{}}\NormalTok{My Title}\KeywordTok{\textless{}/title\textgreater{}} 428 | \end{Highlighting} 429 | \end{Shaded} 430 | 431 | The second type of tag typically defines an attribute with a single tag 432 | enclosed with \textless\textgreater{} brackets. For example, the 433 | \href{https://www.w3schools.com/tags/tag_meta.asp}{meta} tag defines the 434 | HTML page metadata: 435 | 436 | \begin{Shaded} 437 | \begin{Highlighting}[] 438 | \KeywordTok{\textless{}meta} \ErrorTok{charset}\OtherTok{=}\StringTok{"UTF{-}8"}\KeywordTok{\textgreater{}} 439 | \end{Highlighting} 440 | \end{Shaded} 441 | 442 | In this case, the \texttt{charset} argument defines the character 443 | encoding method as \texttt{UTF-8}. 444 | 445 | The HTML file we created contains the following two main elements: 446 | 447 | \begin{itemize} 448 | \tightlist 449 | \item 450 | \texttt{head} - Use to define the page metadata and attributes 451 | \item 452 | \texttt{body} - Use to set the page content 453 | \end{itemize} 454 | 455 | An excellent resource to read about the 456 | \href{https://www.w3schools.com/tags/tag_head.asp}{head} and 457 | \href{https://www.w3schools.com/tags/tag_body.asp}{body} tags, or any 458 | other tags, is the 459 | \href{https://www.w3schools.com/html/default.asp}{w3schools website}. 460 | 461 | \textbf{index.html}: 462 | 463 | \begin{Shaded} 464 | \begin{Highlighting}[] 465 | \DataTypeTok{\textless{}!DOCTYPE }\NormalTok{html}\DataTypeTok{\textgreater{}} 466 | \KeywordTok{\textless{}html} \ErrorTok{lang}\OtherTok{=}\StringTok{"en"}\KeywordTok{\textgreater{}} 467 | \KeywordTok{\textless{}head\textgreater{}} 468 | \KeywordTok{\textless{}meta} \ErrorTok{charset}\OtherTok{=}\StringTok{"UTF{-}8"}\KeywordTok{\textgreater{}} 469 | \KeywordTok{\textless{}meta} \ErrorTok{http{-}equiv}\OtherTok{=}\StringTok{"X{-}UA{-}Compatible"} \ErrorTok{content}\OtherTok{=}\StringTok{"IE=edge"}\KeywordTok{\textgreater{}} 470 | \KeywordTok{\textless{}meta} \ErrorTok{name}\OtherTok{=}\StringTok{"viewport"} \ErrorTok{content}\OtherTok{=}\StringTok{"width=device{-}width, initial{-}scale=1.0"}\KeywordTok{\textgreater{}} 471 | \KeywordTok{\textless{}title\textgreater{}}\NormalTok{Document}\KeywordTok{\textless{}/title\textgreater{}} 472 | \KeywordTok{\textless{}/head\textgreater{}} 473 | \KeywordTok{\textless{}body\textgreater{}} 474 | \KeywordTok{\textless{}/body\textgreater{}} 475 | \KeywordTok{\textless{}/html\textgreater{}} 476 | \end{Highlighting} 477 | \end{Shaded} 478 | 479 | Here are a few things we are going to modify and add to this file: 480 | 481 | \begin{itemize} 482 | \tightlist 483 | \item 484 | The \texttt{\textless{}title\textgreater{}} tag under the 485 | \texttt{\textless{}head\textgreater{}} defines the web browser's tab 486 | title. Let's modify it from \emph{Document} to \emph{Introduction to 487 | JS} 488 | \item 489 | Set the page CSS by linking the \texttt{style.css} file to the page 490 | \texttt{\textless{}head\textgreater{}} element using the 491 | \href{https://www.w3schools.com/tags/tag_link.asp}{link} tag 492 | \end{itemize} 493 | 494 | \textbf{index.html}: 495 | 496 | \begin{Shaded} 497 | \begin{Highlighting}[] 498 | \DataTypeTok{\textless{}!DOCTYPE }\NormalTok{html}\DataTypeTok{\textgreater{}} 499 | \KeywordTok{\textless{}html} \ErrorTok{lang}\OtherTok{=}\StringTok{"en"}\KeywordTok{\textgreater{}} 500 | \KeywordTok{\textless{}head\textgreater{}} 501 | \KeywordTok{\textless{}meta} \ErrorTok{charset}\OtherTok{=}\StringTok{"UTF{-}8"}\KeywordTok{\textgreater{}} 502 | \KeywordTok{\textless{}meta} \ErrorTok{http{-}equiv}\OtherTok{=}\StringTok{"X{-}UA{-}Compatible"} \ErrorTok{content}\OtherTok{=}\StringTok{"IE=edge"}\KeywordTok{\textgreater{}} 503 | \KeywordTok{\textless{}meta} \ErrorTok{name}\OtherTok{=}\StringTok{"viewport"} \ErrorTok{content}\OtherTok{=}\StringTok{"width=device{-}width, initial{-}scale=1.0"}\KeywordTok{\textgreater{}} 504 | \KeywordTok{\textless{}title\textgreater{}}\NormalTok{Introduction to JS}\KeywordTok{\textless{}/title\textgreater{}} 505 | \KeywordTok{\textless{}link} \ErrorTok{rel}\OtherTok{=}\StringTok{"stylesheet"} \ErrorTok{href} \OtherTok{=} \StringTok{"style.css"}\KeywordTok{\textgreater{}} 506 | \KeywordTok{\textless{}/head\textgreater{}} 507 | \KeywordTok{\textless{}body\textgreater{}} 508 | \KeywordTok{\textless{}/body\textgreater{}} 509 | \KeywordTok{\textless{}/html\textgreater{}} 510 | \end{Highlighting} 511 | \end{Shaded} 512 | 513 | Here is a simple CSS setting we will use to define the HTML page font 514 | and headers size: 515 | 516 | \textbf{style.css} 517 | 518 | \begin{Shaded} 519 | \begin{Highlighting}[] 520 | \ImportTok{@import} \FunctionTok{url(}\StringTok{https://fonts.googleapis.com/css?family=Lato:400,700,400italic}\FunctionTok{)}\OperatorTok{;} 521 | \ImportTok{@import} \FunctionTok{url(}\StringTok{https://fonts.googleapis.com/css?family=Roboto+Condensed}\FunctionTok{)}\OperatorTok{;} 522 | \ImportTok{@import} \FunctionTok{url(}\StringTok{https://fonts.googleapis.com/css?family=Roboto+Mono}\FunctionTok{)}\OperatorTok{;} 523 | 524 | \NormalTok{body \{ } 525 | \KeywordTok{font{-}family}\NormalTok{: }\StringTok{\textquotesingle{}Lato\textquotesingle{}}\OperatorTok{,}\NormalTok{ Arial}\OperatorTok{,} \DecValTok{sans{-}serif}\OperatorTok{;} 526 | \KeywordTok{font{-}size}\NormalTok{: }\DecValTok{26}\DataTypeTok{px}\OperatorTok{;} 527 | \NormalTok{\}} 528 | \NormalTok{h1}\OperatorTok{,}\NormalTok{ h2}\OperatorTok{,}\NormalTok{ h3}\OperatorTok{,}\NormalTok{ h4 \{} 529 | \KeywordTok{font{-}family}\NormalTok{: }\StringTok{\textquotesingle{}Roboto Condensed\textquotesingle{}}\OperatorTok{,} \StringTok{\textquotesingle{}Arial Narrow OS\textquotesingle{}}\OperatorTok{,}\NormalTok{ Arial}\OperatorTok{,} \DecValTok{sans{-}serif}\OperatorTok{;} 530 | \KeywordTok{font{-}weight}\NormalTok{: }\DecValTok{normal}\OperatorTok{;} 531 | \NormalTok{\}} 532 | \end{Highlighting} 533 | \end{Shaded} 534 | 535 | \hypertarget{live-server}{% 536 | \subsection{Live Server}\label{live-server}} 537 | 538 | Last but not least, let's see how the VScode's 539 | \href{https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer}{live 540 | server} extension is working and how to leverage it in our workflow. 541 | This extension will enable us to instantaneously review the changes we 542 | apply to the index.html file on the web browser as we update and save 543 | the code. If you have wide screen, I recommand to open side-by-side 544 | VScode and your default browser and see, while coding, the changes in 545 | the browser. To launch the live server on VScode, go to the EXPLORER tab 546 | left side and right-click on the index.html file. That should pop up a 547 | window with options, select \emph{Open with Live Server} option: 548 | 549 | \hypertarget{executing-javascript-code}{% 550 | \section{Executing JavaScript code}\label{executing-javascript-code}} 551 | 552 | Throughout this tutorial, we will use the \texttt{index.html} file to 553 | run JS code on the HTML page using the 554 | \href{https://www.w3schools.com/tags/tag_script.asp}{script} tag. As the 555 | name implies, the \texttt{script} tab enables us to embed JS code within 556 | an HTML file or call and execute an external JS script. For example, 557 | let's use the JS \texttt{window.alert} function to pop an alert window 558 | and print \texttt{Hello\ World!}: 559 | 560 | \begin{Shaded} 561 | \begin{Highlighting}[] 562 | \BuiltInTok{window}\OperatorTok{.}\FunctionTok{alert}\NormalTok{(}\StringTok{"Hello World!"}\NormalTok{)} 563 | \end{Highlighting} 564 | \end{Shaded} 565 | 566 | Here is how you would embed your JS code within the HTML file using the 567 | \texttt{script} tag: 568 | 569 | \begin{Shaded} 570 | \begin{Highlighting}[] 571 | \DataTypeTok{\textless{}!DOCTYPE }\NormalTok{html}\DataTypeTok{\textgreater{}} 572 | \KeywordTok{\textless{}html} \ErrorTok{lang}\OtherTok{=}\StringTok{"en"}\KeywordTok{\textgreater{}} 573 | \KeywordTok{\textless{}head\textgreater{}} 574 | \KeywordTok{\textless{}meta} \ErrorTok{charset}\OtherTok{=}\StringTok{"UTF{-}8"}\KeywordTok{\textgreater{}} 575 | \KeywordTok{\textless{}meta} \ErrorTok{http{-}equiv}\OtherTok{=}\StringTok{"X{-}UA{-}Compatible"} \ErrorTok{content}\OtherTok{=}\StringTok{"IE=edge"}\KeywordTok{\textgreater{}} 576 | \KeywordTok{\textless{}meta} \ErrorTok{name}\OtherTok{=}\StringTok{"viewport"} \ErrorTok{content}\OtherTok{=}\StringTok{"width=device{-}width, initial{-}scale=1.0"}\KeywordTok{\textgreater{}} 577 | \KeywordTok{\textless{}title\textgreater{}}\NormalTok{Introduction to JS}\KeywordTok{\textless{}/title\textgreater{}} 578 | \KeywordTok{\textless{}link} \ErrorTok{rel}\OtherTok{=}\StringTok{"stylesheet"} \ErrorTok{href} \OtherTok{=} \StringTok{"style.css"}\KeywordTok{\textgreater{}} 579 | \KeywordTok{\textless{}/head\textgreater{}} 580 | \KeywordTok{\textless{}body\textgreater{}} 581 | \KeywordTok{\textless{}script\textgreater{}}\BuiltInTok{window}\OperatorTok{.}\FunctionTok{alert}\NormalTok{(}\StringTok{"Hello World!"}\NormalTok{)}\KeywordTok{\textless{}/script\textgreater{}} 582 | \KeywordTok{\textless{}/body\textgreater{}} 583 | \KeywordTok{\textless{}/html\textgreater{}} 584 | \end{Highlighting} 585 | \end{Shaded} 586 | 587 | Alternatively, you can use the \texttt{script} tag to call and execute 588 | the JS script file. Let's copy our JS code to the \texttt{index.js} file 589 | and call it with the \texttt{src} argument of the \texttt{script} tag: 590 | 591 | \textbf{index.js} 592 | 593 | \begin{Shaded} 594 | \begin{Highlighting}[] 595 | \BuiltInTok{window}\OperatorTok{.}\FunctionTok{alert}\NormalTok{(}\StringTok{"Hello World!"}\NormalTok{)} 596 | \end{Highlighting} 597 | \end{Shaded} 598 | 599 | \textbf{index.html} 600 | 601 | \begin{Shaded} 602 | \begin{Highlighting}[] 603 | \DataTypeTok{\textless{}!DOCTYPE }\NormalTok{html}\DataTypeTok{\textgreater{}} 604 | \KeywordTok{\textless{}html} \ErrorTok{lang}\OtherTok{=}\StringTok{"en"}\KeywordTok{\textgreater{}} 605 | \KeywordTok{\textless{}head\textgreater{}} 606 | \KeywordTok{\textless{}meta} \ErrorTok{charset}\OtherTok{=}\StringTok{"UTF{-}8"}\KeywordTok{\textgreater{}} 607 | \KeywordTok{\textless{}meta} \ErrorTok{http{-}equiv}\OtherTok{=}\StringTok{"X{-}UA{-}Compatible"} \ErrorTok{content}\OtherTok{=}\StringTok{"IE=edge"}\KeywordTok{\textgreater{}} 608 | \KeywordTok{\textless{}meta} \ErrorTok{name}\OtherTok{=}\StringTok{"viewport"} \ErrorTok{content}\OtherTok{=}\StringTok{"width=device{-}width, initial{-}scale=1.0"}\KeywordTok{\textgreater{}} 609 | \KeywordTok{\textless{}title\textgreater{}}\NormalTok{Introduction to JS}\KeywordTok{\textless{}/title\textgreater{}} 610 | \KeywordTok{\textless{}link} \ErrorTok{rel}\OtherTok{=}\StringTok{"stylesheet"} \ErrorTok{href} \OtherTok{=} \StringTok{"style.css"}\KeywordTok{\textgreater{}} 611 | \KeywordTok{\textless{}/head\textgreater{}} 612 | \KeywordTok{\textless{}body\textgreater{}} 613 | \KeywordTok{\textless{}script} \ErrorTok{src} \OtherTok{=} \StringTok{"index.js"}\KeywordTok{\textgreater{}\textless{}/script\textgreater{}} 614 | \KeywordTok{\textless{}/body\textgreater{}} 615 | \KeywordTok{\textless{}/html\textgreater{}} 616 | \end{Highlighting} 617 | \end{Shaded} 618 | 619 | In both cases, here is the expected output: 620 | 621 | That's it! We are ready to write our first JS code! 622 | 623 | \bookmarksetup{startatroot} 624 | 625 | \hypertarget{references}{% 626 | \chapter*{References}\label{references}} 627 | \addcontentsline{toc}{chapter}{References} 628 | 629 | \markboth{References}{References} 630 | 631 | \hypertarget{refs}{} 632 | \begin{CSLReferences}{0}{0} 633 | \end{CSLReferences} 634 | 635 | 636 | 637 | \end{document} 638 | -------------------------------------------------------------------------------- /references.bib: -------------------------------------------------------------------------------- 1 | @article{knuth84, 2 | author = {Knuth, Donald E.}, 3 | title = {Literate Programming}, 4 | year = {1984}, 5 | issue_date = {May 1984}, 6 | publisher = {Oxford University Press, Inc.}, 7 | address = {USA}, 8 | volume = {27}, 9 | number = {2}, 10 | issn = {0010-4620}, 11 | url = {https://doi.org/10.1093/comjnl/27.2.97}, 12 | doi = {10.1093/comjnl/27.2.97}, 13 | journal = {Comput. J.}, 14 | month = may, 15 | pages = {97–111}, 16 | numpages = {15} 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /references.qmd: -------------------------------------------------------------------------------- 1 | # References {.unnumbered} 2 | 3 | ::: {#refs} 4 | ::: 5 | -------------------------------------------------------------------------------- /settings.qmd: -------------------------------------------------------------------------------- 1 | # Settings 2 | 3 | WIP...pre spelling check 4 | 5 | 6 | Before getting started, let's set the development environment. There are many ways to develop and execute JavaScript. For this tutorial, I use VScode, which has great integrations with JavaScript, HTML, and CSS and seamless integration with Docker. In addition, it has great integration with Quarto, which was used to create this document. If you want to follow the same settings, check the instructions below. 7 | 8 | ### VScode Settings for JavaScript 9 | 10 | If you don't have VScode installed, you can download and install it directly from the [VScode website](https://code.visualstudio.com/). I also use the following extensions: 11 | 12 | * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) extension, which enables you to launch a local development server with a live reload feature for static & dynamic pages 13 | * [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension, supporting development on VScode with Docker containers 14 | 15 | ### Setting Docker Environment 16 | 17 | One of the main reasons I love using VScode is the seamless integration with Docker. It enables you to develop in your local folder while executing the code inside the image. Here is what you need to set your VScode to run inside a Docker image: 18 | 19 | * Docker Desktop (or equivalent) install on your machine (download and install it from [here](https://www.docker.com/products/docker-desktop/)) 20 | * Docker [extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) for VScode 21 | * Set the supporting image, [here](https://github.com/RamiKrispin/Tutorials/tree/main/docker) are the Docker settings I am using for this tutorial 22 | * Create the devcontainer.json file with your container settings (image name, environment variables, extension names, etc.), [here](https://github.com/RamiKrispin/Tutorials/blob/main/.devcontainer/devcontainer.json) is my `devcontainer.json` file setting 23 | * Open the folder inside the container (see the screenshot below) 24 | 25 | Open Container 26 | 27 | You can read more about setting and using Docker with VScode on [VScode's documentation](https://code.visualstudio.com/docs/containers/overview). 28 | 29 | 30 | If you want to leverage the tutorial Docker settings, you can clone the repository and follow the next steps: 31 | 32 | * Open the tutorial repository's folder on VScode 33 | * Open the `Command Palette` (⇧⌘P in Mac, Ctrl+Shift+P in Windows) or use the `Open Remote Window` button (on the bottom left side, see the screen recording above) and type `Open Folder in Container`. 34 | 35 | **Note:** It might take few minutes on the first time opening the container, as it pull the docker image from [Docker Hub](https://hub.docker.com/repository/docker/rkrispin/tutorial). 36 | 37 | ## Workflow 38 | 39 | JavaScript (also known as JS), is one of the most popular programming languages for web development. It is typically used to create web page applications, mobile apps, games, and great data visualization tools (D3, Observable Plot, Leaflet, Charts, etc.). You can run JavaScript on your web browser (e.g., Chrome, Safari, Firefox, etc.): 40 | 41 | **Screen record here*** 42 | 43 | While you can use your web browser as a consul for ad-hoc code tests, the development of JS applications is done inside a script using a code editor such VScode, notepad, etc. It is common to have JS code embedded inside HTML script (or call JS script from HTML script). 44 | 45 | ### File structure 46 | 47 | In this tutorial, we will adopt the basic framework for running JS code on the browser by setting a web page with an HTML file (`index.html`) and leveraging it to call a JS file (`index.js`) with our JS code. In addition, we will use a CSS file (`style.css`) to set the web page style. I will set those files under the [JavaScript folder](https://github.com/RamiKrispin/Tutorials/tree/main/JavaScript): 48 | 49 | ``` shell 50 | . 51 | ├── index.html 52 | ├── index.js 53 | └── style.ccs 54 | ``` 55 | 56 | 57 | **Note:** For convenience, I placed the three files in the same folder. However, if you wish to arrange it differently, you can easily reference the `index.js` and `style.css` file paths from the `index.html` file. 58 | 59 | Don't worry if you are not familiar with HTML or CSS. We will use the basic templates to set those files. Let's start by creating three empty files using the file names above. To set the HTML file, we will use the VScode HTML code snippet template by typing the `!` symbol and press enter: 60 | 61 | Setting HTML template 62 | 63 | In a nutshell, the HTML language is based on code chunks nested by tags. The tags define the code's functionality. Here is the most common tag structure: 64 | 65 | ``` html 66 | arguments and expressions 67 | ``` 68 | 69 | In this HTML structure, the element is nested by the tag name. In both cases, the tag is enclosed within `< >` brackets, where the closing tag is marked with `/` symbol before the tag. For example, we will use the title tag to define the web page title: 70 | 71 | ``` html 72 | My Title 73 | ``` 74 | 75 | The second type of tag typically defines an attribute with a single tag enclosed with <> brackets. For example, the [meta](https://www.w3schools.com/tags/tag_meta.asp) tag defines the HTML page metadata: 76 | 77 | ``` html 78 | 79 | ``` 80 | 81 | In this case, the `charset` argument defines the character encoding method as `UTF-8`. 82 | 83 | 84 | The HTML file we created contains the following two main elements: 85 | 86 | * `head` - Use to define the page metadata and attributes 87 | * `body` - Use to set the page content 88 | 89 | An excellent resource to read about the [head](https://www.w3schools.com/tags/tag_head.asp) and [body](https://www.w3schools.com/tags/tag_body.asp) tags, or any other tags, is the [w3schools website](https://www.w3schools.com/html/default.asp). 90 | 91 | **index.html**: 92 | ``` html 93 | 94 | 95 | 96 | 97 | 98 | 99 | Document 100 | 101 | 102 | 103 | 104 | ``` 105 | 106 | Here are a few things we are going to modify and add to this file: 107 | 108 | * The `` tag under the `<head>` defines the web browser's tab title. Let's modify it from *Document* to *Introduction to JS* 109 | * Set the page CSS by linking the `style.css` file to the page `<head>` element using the [link](https://www.w3schools.com/tags/tag_link.asp) tag 110 | 111 | **index.html**: 112 | ``` html 113 | <!DOCTYPE html> 114 | <html lang="en"> 115 | <head> 116 | <meta charset="UTF-8"> 117 | <meta http-equiv="X-UA-Compatible" content="IE=edge"> 118 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> 119 | <title>Introduction to JS 120 | 121 | 122 | 123 | 124 | 125 | ``` 126 | 127 | Here is a simple CSS setting we will use to define the HTML page font and headers size: 128 | 129 | **style.css** 130 | ``` CSS 131 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic); 132 | @import url(https://fonts.googleapis.com/css?family=Roboto+Condensed); 133 | @import url(https://fonts.googleapis.com/css?family=Roboto+Mono); 134 | 135 | body { 136 | font-family: 'Lato', Arial, sans-serif; 137 | font-size: 26px; 138 | } 139 | h1, h2, h3, h4 { 140 | font-family: 'Roboto Condensed', 'Arial Narrow OS', Arial, sans-serif; 141 | font-weight: normal; 142 | } 143 | ``` 144 | 145 | ### Live Server 146 | 147 | Last but not least, let's see how the VScode's [live server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) extension is working and how to leverage it in our workflow. This extension will enable us to instantaneously review the changes we apply to the index.html file on the web browser as we update and save the code. If you have wide screen, I recommand to open side-by-side VScode and your default browser and see, while coding, the changes in the browser. To launch the live server on VScode, go to the EXPLORER tab left side and right-click on the index.html file. That should pop up a window with options, select *Open with Live Server* option: 148 | 149 | Live Server 150 | 151 | ## Executing JavaScript code 152 | 153 | Throughout this tutorial, we will use the `index.html` file to run JS code on the HTML page using the [script](https://www.w3schools.com/tags/tag_script.asp) tag. As the name implies, the `script` tab enables us to embed JS code within an HTML file or call and execute an external JS script. For example, let's use the JS `window.alert` function to pop an alert window and print `Hello World!`: 154 | 155 | ``` js 156 | window.alert("Hello World!") 157 | ``` 158 | 159 | Here is how you would embed your JS code within the HTML file using the `script` tag: 160 | 161 | ``` html 162 | 163 | 164 | 165 | 166 | 167 | 168 | Introduction to JS 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | ``` 177 | 178 | Alternatively, you can use the `script` tag to call and execute the JS script file. Let's copy our JS code to the `index.js` file and call it with the `src` argument of the `script` tag: 179 | 180 | **index.js** 181 | 182 | ``` js 183 | window.alert("Hello World!") 184 | ``` 185 | 186 | **index.html** 187 | 188 | ``` html 189 | 190 | 191 | 192 | 193 | 194 | 195 | Introduction to JS 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | ``` 204 | 205 | In both cases, here is the expected output: 206 | 207 | Live Server 208 | 209 | 210 | That's it! We are ready to write our first JS code! -------------------------------------------------------------------------------- /summary.qmd: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tutorials.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | --------------------------------------------------------------------------------