├── .gitignore ├── .travis.yml ├── README.md ├── archetypes ├── default.md ├── helpers.md └── polyfills.md ├── config.yml ├── content ├── 404.md ├── _index.md ├── boilerplates │ ├── _index.md │ ├── class.md │ ├── constructor.md │ ├── iife.md │ ├── revealing-module-pattern.md │ ├── service-worker.md │ └── web-component.md ├── helpers │ ├── _index.md │ ├── animate.md │ ├── arrayIntersect.md │ ├── buildQuery.md │ ├── cleanHTML.md │ ├── createColor.md │ ├── decodeHTML.md │ ├── dedupe.md │ ├── deepMerge.md │ ├── emitEvent.md │ ├── encodeHTML.md │ ├── getContrast.md │ ├── getCookie.md │ ├── getFlagEmoji.md │ ├── getMonths.md │ ├── getParam.md │ ├── getParams.md │ ├── parseJWT.md │ ├── randomNumber.md │ ├── randomString.md │ ├── range.md │ ├── round.md │ ├── scrollDistance.md │ ├── serialize.md │ ├── shuffle.md │ └── trueTypeOf.md ├── libraries.md ├── mit.md ├── offline.md ├── projects.md ├── reference │ ├── _index.md │ ├── ajax │ │ ├── _index.md │ │ ├── async-await.md │ │ ├── fetch.md │ │ └── multiple-endpoints.md │ ├── arrays │ │ ├── _index.md │ │ ├── array-concat.md │ │ ├── array-filter.md │ │ ├── array-find.md │ │ ├── array-findIndex.md │ │ ├── array-from.md │ │ ├── array-indexOf.md │ │ ├── array-join.md │ │ ├── array-map.md │ │ ├── array-pop.md │ │ ├── array-push.md │ │ ├── array-reduce.md │ │ ├── array-reverse.md │ │ ├── array-shift.md │ │ ├── array-slice.md │ │ ├── array-sort.md │ │ └── array-splice.md │ ├── attributes │ │ ├── _index.md │ │ ├── getAttribute.md │ │ ├── hasAttribute.md │ │ ├── properties.md │ │ ├── removeAttribute.md │ │ └── setAttribute.md │ ├── browser-storage │ │ ├── _index.md │ │ ├── cookies.md │ │ ├── localStorage.md │ │ └── sessionStorage.md │ ├── classes │ │ ├── _index.md │ │ ├── classList.md │ │ └── className.md │ ├── dom-injection │ │ ├── _index.md │ │ ├── createElement.md │ │ ├── element-after.md │ │ ├── element-append.md │ │ ├── element-before.md │ │ ├── element-prepend.md │ │ ├── element-remove.md │ │ ├── node-clone.md │ │ └── node-replaceWith.md │ ├── es-modules │ │ ├── _index.md │ │ ├── default-exports.md │ │ ├── export.md │ │ ├── import-all.md │ │ └── side-effects.md │ ├── event-listeners │ │ ├── _index.md │ │ ├── addEventListener.md │ │ └── customEvent.md │ ├── extract-copy │ │ ├── _index.md │ │ ├── array-destructuring.md │ │ ├── object-destructuring.md │ │ ├── spread-syntax.md │ │ └── structuredClone.md │ ├── html-text │ │ ├── _index.md │ │ ├── innerHTML.md │ │ ├── innerText.md │ │ ├── outerHTML.md │ │ └── textContent.md │ ├── javascript-free │ │ ├── _index.md │ │ ├── autocomplete.md │ │ ├── disclosure.md │ │ └── smooth-scrolling.md │ ├── json │ │ ├── _index.md │ │ ├── json-parse.md │ │ └── json-stringify.md │ ├── loops │ │ ├── _index.md │ │ ├── for-in.md │ │ ├── for-of.md │ │ ├── for.md │ │ └── foreach.md │ ├── numbers │ │ ├── _index.md │ │ ├── basic-math.md │ │ ├── comparisons.md │ │ ├── increment-decrement.md │ │ ├── math-abs.md │ │ ├── math-ceil.md │ │ ├── math-floor.md │ │ ├── math-max.md │ │ ├── math-min.md │ │ ├── math-random.md │ │ ├── number-toFixed.md │ │ ├── number-toString.md │ │ ├── number.md │ │ ├── parseFloat.md │ │ └── parseInt.md │ ├── objects │ │ ├── _index.md │ │ ├── delete.md │ │ ├── object-assign.md │ │ ├── object-entries.md │ │ ├── object-freeze.md │ │ ├── object-function-shorthand.md │ │ ├── object-keys.md │ │ ├── object-property-shorthand.md │ │ └── optional-chaining.md │ ├── selectors │ │ ├── _index.md │ │ ├── document-querySelector.md │ │ ├── document-querySelectorAll.md │ │ └── element-matches.md │ ├── strings │ │ ├── _index.md │ │ ├── string-includes.md │ │ ├── string-indexOf.md │ │ ├── string-padEnd.md │ │ ├── string-padStart.md │ │ ├── string-replace.md │ │ ├── string-replaceAll.md │ │ ├── string-slice.md │ │ ├── string-split.md │ │ ├── string-toLowerCase.md │ │ ├── string-toUpperCase.md │ │ ├── string-trim.md │ │ └── template-literals.md │ ├── style │ │ ├── _index.md │ │ ├── element-style.md │ │ └── window-getComputedStyle.md │ ├── traversal │ │ ├── _index.md │ │ ├── element-childNodes.md │ │ ├── element-children.md │ │ ├── element-closest.md │ │ ├── element-parentNode.md │ │ ├── firstChild-lastChild.md │ │ ├── firstElementChild-lastElementChild.md │ │ ├── nextElementSibling-previousElementSibling.md │ │ └── nextSibling-previousSibling.md │ ├── variables-functions │ │ ├── _index.md │ │ ├── arrow-functions.md │ │ ├── default-parameters.md │ │ ├── rest-parameters.md │ │ └── ternary-operator.md │ └── viewport │ │ ├── _index.md │ │ ├── getBoundingClientRect.md │ │ ├── innerHeight.md │ │ └── innerWidth.md ├── resources.md └── search.md ├── deploy.sh ├── i18n └── en.toml ├── package-lock.json ├── static ├── automate │ └── deploy.php ├── img │ └── chris-ferdinandi-high-res.jpg └── robots.txt └── themes └── gmt ├── LICENSE.md ├── archetypes └── default.md ├── layouts ├── 404.html ├── _default │ ├── list.html │ ├── single.html │ └── terms.html ├── boilerplates │ ├── list.html │ └── single.html ├── helpers │ ├── list.html │ └── single.html ├── index.html ├── page │ └── single.html ├── partials │ ├── _nav-items_BACKUP.html │ ├── content-page-no-article.html │ ├── content-page.html │ ├── email.html │ ├── footer.html │ ├── header.html │ ├── mailchimp-form.html │ ├── mailchimp-intro.html │ ├── nav-a11y.html │ ├── nav-items.html │ ├── nav-main.html │ └── nav-secondary.html ├── reference │ ├── list.html │ └── single.html ├── rss-feed │ └── single.html ├── search │ └── single.html └── shortcodes │ ├── cta.html │ ├── email.html │ ├── learn-how.html │ ├── learn-more.html │ ├── mailchimp.html │ ├── md.html │ ├── search-form.html │ ├── testimonial.html │ ├── toc.html │ └── year.html ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── img │ ├── favicon-144.png │ └── favicon.ico ├── js │ ├── main.js │ ├── search.js │ └── swInit.js ├── static │ └── README.md └── svg │ └── icecream.svg ├── static ├── css │ ├── fonts.css │ ├── main.css │ └── main.min.css ├── img │ ├── favicon-144.png │ └── favicon.ico ├── js │ ├── main.js │ ├── main.min.js │ ├── search.js │ ├── search.min.js │ ├── swInit.js │ └── swInit.min.js ├── svg │ └── icecream.svg └── sw.js └── theme.yml /.gitignore: -------------------------------------------------------------------------------- 1 | ## Node 2 | node_modules 3 | #themes 4 | 5 | ## OS X 6 | .DS_Store 7 | ._* 8 | .Spotlight-V100 9 | .Trashes -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "7" 4 | before_script: 5 | - rm -rf public 6 | script: hugo -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vanilla JS Toolkit 2 | 3 | A growing collection of vanilla JavaScript code snippets, helper functions, polyfills, plugins, and learning resources. 4 | 5 | _**Note:** The toolkit has been relocated to [GoMakeThings.com/toolkit](https://gomakethings.com/toolkit/)_ 6 | 7 | ## Todo 8 | 9 | - [ ] Add [autoexpanding text area](https://gomakethings.com/automatically-expand-a-textarea-as-the-user-types-using-vanilla-javascript/) 10 | -------------------------------------------------------------------------------- /archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .TranslationBaseName "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: false 5 | noTitle: false 6 | noIndex: false 7 | --- 8 | 9 | -------------------------------------------------------------------------------- /archetypes/helpers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .TranslationBaseName "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: false 5 | description: "" 6 | weight: 10 7 | noIndex: false 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /archetypes/polyfills.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .TranslationBaseName "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: false 5 | weight: 10 6 | noIndex: false 7 | --- 8 | 9 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | # hostname (and path) to the root 2 | baseURL: "https://vanillajstoolkit.com" 3 | 4 | # Customer parameters 5 | params: 6 | description: "A collection of tools and snippets for working with JavaScript." 7 | api: "https://gomakethings.com/api/data.json" 8 | rssURL: "" 9 | rssLimit: 7 10 | minify: false 11 | 12 | # Caches 13 | caches: 14 | getjson: 15 | maxAge: "10m" 16 | 17 | # The language code for the site 18 | languageCode: "en-us" 19 | 20 | # Site title 21 | title: "The Vanilla JS Toolkit" 22 | 23 | # theme to use (located by default in /themes/THEMENAME/) 24 | theme: "gmt" 25 | 26 | # Permalinks 27 | # See "content-management/permalinks" 28 | permalinks: 29 | articles: /:title/ 30 | reference: /:sections/:filename/ 31 | 32 | # Allows you to disable all page types and will render nothing related to 'kind'; 33 | # values = "page", "home", "section", "taxonomy", "taxonomyTerm", "RSS", "sitemap", "robotsTXT", "404" 34 | disableKinds: ["RSS", "hugoGeneratorInject", "404"] 35 | 36 | # Files to ignore while rendering 37 | ignoreFiles: [] 38 | 39 | # the length of text to show in a .Summary 40 | summaryLength: 70 41 | 42 | # Pagination 43 | paginate: 35 44 | paginatePath: "page" 45 | 46 | # Markdown Options 47 | blackfriday: 48 | fractions: false 49 | 50 | # Syntax Highlighting 51 | pygmentsCodefences: true 52 | pygmentsUseClasses: true -------------------------------------------------------------------------------- /content/404.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Oops!" 3 | date: 2018-01-11T16:03:33-05:00 4 | draft: false 5 | --- 6 | 7 | 8 | 9 | I can't seem to find the page you're looking for. Sorry! Send me an email me at {{}} and I'll help you find it. -------------------------------------------------------------------------------- /content/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: true 6 | fullWidth: false 7 | --- 8 | 9 |

A collection of tools and snippets for working with JavaScript.

10 |

Find modern JS methods and utility functions, and browse hand‑selected libraries, boilerplates, and learning resources.

11 | 12 | {{}} 13 | 14 | {{}} 15 | 16 | {{}} -------------------------------------------------------------------------------- /content/boilerplates/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Boilerplates" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | anchors: true 8 | --- 9 | 10 | A set of templates to help you kick-start your next JavaScript project. 11 | 12 | {{}} -------------------------------------------------------------------------------- /content/boilerplates/class.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Class Pattern" 3 | date: 2018-01-24T12:16:26-05:00 4 | description: "An alternative approach to implementing the constructor pattern, with a nicer syntax and some additional features." 5 | example: "a piggy bank library." 6 | draft: false 7 | weight: 40 8 | noIndex: false 9 | --- 10 | 11 | Change `MyLibrary` to whatever namespace you’d like to use for your library. The constructor object is lowercase, and functions are automatically attached to the instance `prototype`. 12 | 13 | ## Examples 14 | 15 | ```js 16 | // Create new instances of the constructor 17 | let dugg = new MyLibrary(); 18 | let kevin = new MyLibrary(4); 19 | 20 | // Run methods 21 | dugg.add(2); 22 | kevin.subtract(1); 23 | let total = dug.total; 24 | ``` 25 | 26 | ## The Boilerplate 27 | 28 | ```js 29 | class MyLibrary { 30 | 31 | /** 32 | * Create the constructor object 33 | * @param {Number} start The starting amount 34 | */ 35 | 36 | constructor (start = 0) { 37 | this.total = start; 38 | } 39 | 40 | /** 41 | * Add money to the total 42 | */ 43 | add (num = 1) { 44 | this.total = this.total + num; 45 | } 46 | 47 | /** 48 | * Remove money from the total 49 | */ 50 | subtract (num = 1) { 51 | this.total = this.total - num; 52 | } 53 | } 54 | ``` -------------------------------------------------------------------------------- /content/boilerplates/constructor.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Constructor Pattern" 3 | date: 2018-01-24T12:16:26-05:00 4 | description: "Create multiple instances of script that share methods but contain unique information." 5 | example: "a piggy bank library." 6 | draft: false 7 | weight: 30 8 | noIndex: false 9 | --- 10 | 11 | Change `MyLibrary` to whatever namespace you’d like to use for your library. Constructors start with a capital letter. 12 | 13 | ## Examples 14 | 15 | ```js 16 | // Create new instances of the constructor 17 | let dugg = new MyLibrary(); 18 | let kevin = new MyLibrary(4); 19 | 20 | // Run methods 21 | dugg.add(2); 22 | kevin.subtract(1); 23 | let total = dug.total; 24 | ``` 25 | 26 | ## The Boilerplate 27 | 28 | ```js 29 | /** 30 | * Constructor Pattern Boilerplate 31 | */ 32 | let MyLibrary = (function () { 33 | 34 | /** 35 | * Create the Constructor object 36 | * @param {Number} start The starting amount 37 | */ 38 | function Constructor (start = 0) { 39 | this.total = start; 40 | } 41 | 42 | /** 43 | * Add money to the total 44 | */ 45 | Constructor.prototype.add = function (num = 1) { 46 | this.total = this.total + num; 47 | }; 48 | 49 | /** 50 | * Remove money from the total 51 | */ 52 | Constructor.prototype.subtract = function (num = 1) { 53 | this.total = this.total - num; 54 | }; 55 | 56 | return Constructor; 57 | 58 | })(); 59 | ``` -------------------------------------------------------------------------------- /content/boilerplates/iife.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "IIFE" 3 | date: 2018-01-24T12:16:26-05:00 4 | description: "Used when you want your code to run immediately, but want to keep all of your variables and functions scoped to avoid conflicts. Stands for _Immediately Invoked Function Expression_." 5 | draft: false 6 | weight: 10 7 | noIndex: false 8 | --- 9 | 10 | Add your code inside the IIFE. 11 | 12 | ```js 13 | /** 14 | * Immediately Invoked Function Expression Boilerplate 15 | */ 16 | ;(function () { 17 | // Code goes here... 18 | })(); 19 | ``` -------------------------------------------------------------------------------- /content/boilerplates/revealing-module-pattern.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Revealing Module Pattern" 3 | date: 2018-01-24T12:16:26-05:00 4 | description: "Allows you to keep most of your variables and functions out of the global scope, but make some of them publicly available." 5 | example: "a helper library like lodash." 6 | draft: false 7 | weight: 20 8 | noIndex: false 9 | --- 10 | 11 | Change `MyLibrary` to whatever namespace you’d like to use for your library. 12 | 13 | ## Examples 14 | 15 | ```js 16 | MyLibrary.sayHi(); 17 | MyLibrary.sayBye(); 18 | ``` 19 | 20 | ## The Boilerplate 21 | 22 | ```js 23 | /** 24 | * Revealing Module Pattern Boilerplate 25 | */ 26 | let MyLibrary = (function () { 27 | 28 | // This variable is scoped internally 29 | // It can't be accessed externally 30 | let name = 'Wall-E'; 31 | 32 | // This is returned at the end and can be run externally 33 | function sayHi () { 34 | console.log(`Hi ${name}`); 35 | } 36 | 37 | // This can also be run externally 38 | function sayBye () { 39 | console.log(`Bye ${name}`); 40 | } 41 | 42 | // Return and functions and variables that should be accessible externally 43 | return {sayHi, sayBye}; 44 | 45 | })(); 46 | ``` -------------------------------------------------------------------------------- /content/boilerplates/web-component.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Web Component" 3 | date: 2018-01-24T12:16:26-05:00 4 | description: "A way to define reusable custom HTML elements, with built-in styles and interactivity." 5 | example: "a loading icon." 6 | draft: false 7 | weight: 60 8 | noIndex: false 9 | --- 10 | 11 | Change `my-library` to whatever namespace you'd like to use for your custom element, and `MyLibrary` to whatever namespace you’d like to use for your library. 12 | 13 | Web Component element names must include a `-`, and be registered with JavaScript. The JavaScript class for your library `extends` the `HTMLElement` object. 14 | 15 | ## Examples 16 | 17 | ```html 18 | 19 | ``` 20 | 21 | ## The Boilerplate 22 | 23 | ```js 24 | class MyLibrary extends HTMLElement { 25 | 26 | // The class constructor object 27 | constructor () { 28 | 29 | // Always call super first in constructor 30 | super(); 31 | 32 | // Creates a shadow root 33 | this.root = this.attachShadow({mode: 'closed'}); 34 | 35 | // Render HTML 36 | this.root.innerHTML = 37 | ` 100 | 101 | Loading... 102 | 103 |
104 |
105 |
106 |
107 |
108 |
`; 109 | 110 | } 111 | 112 | // Runs when the value of an attribute is changed on the component 113 | attributeChangedCallback (name, oldValue, newValue) { 114 | 115 | // Remove the icon 116 | let icon = this.root.querySelector('.loading-ring'); 117 | icon.remove(); 118 | 119 | // Show a content loaded message 120 | let notify = this.root.querySelector('[role="status"]'); 121 | notify.textContent = newValue.length ? newValue : 'Content loaded'; 122 | 123 | } 124 | 125 | // Create a list of attributes to observe 126 | static get observedAttributes () { 127 | return ['loaded']; 128 | } 129 | 130 | } 131 | 132 | if ('customElements' in window) { 133 | customElements.define('my-library', MyLibrary); 134 | } 135 | ``` -------------------------------------------------------------------------------- /content/helpers/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Helper Functions" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | --- 8 | 9 | Helper functions make complicated or repetitive tasks a bit easier, and keep your code DRY (an acronym for *Don't Repeat Yourself*). 10 | 11 | _Unless otherwise noted, these helper functions work in all modern browsers on desktop and mobile._ 12 | 13 | {{}} 14 | 15 | ## The Functions -------------------------------------------------------------------------------- /content/helpers/animate.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "animate.js" 3 | date: 2018-01-24T12:16:26-05:00 4 | draft: false 5 | description: "Apply a CSS animation to an element." 6 | how: "https://gomakethings.com/how-to-easily-add-css-animations-to-your-projects/" 7 | demo: "https://codepen.io/cferdinandi/pen/wvJzMmV" 8 | weight: 10 9 | noIndex: false 10 | --- 11 | 12 | ```js 13 | /*! 14 | * Apply a CSS animation to an element 15 | * (c) 2021 Chris Ferdinandi, MIT License, https://gomakethings.com 16 | * @param {Node} node The element to animate 17 | * @param {String} animation The animation class to apply 18 | * @param {Function} onEnd A callback function to run when the animation ends [optional] 19 | */ 20 | function animate (node, animation, onEnd = function () {}) { 21 | node.classList.add(animation); 22 | node.addEventListener('animationend', function () { 23 | node.classList.remove(animation); 24 | onEnd(node, animation); 25 | }, {once: true}); 26 | } 27 | ``` -------------------------------------------------------------------------------- /content/helpers/arrayIntersect.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "arrayIntersect.js" 3 | date: 2018-01-24T12:16:26-05:00 4 | draft: false 5 | description: "Get the intersecting values between two arrays." 6 | how: "https://gomakethings.com/how-to-find-the-intersecting-values-of-two-arrays-with-vanilla-javascript/" 7 | demo: "https://codepen.io/cferdinandi/pen/xxjmRwK?editors=0011" 8 | weight: 10 9 | noIndex: false 10 | --- 11 | 12 | ```js 13 | /*! 14 | * Get the intersecting values between two arrays 15 | * (c) 2022 Chris Ferdinandi, MIT License, https://gomakethings.com 16 | * @param {Array} arr1 The first array 17 | * @param {Array} arr2 The second array 18 | * @return {Array} The array of overlapping values 19 | */ 20 | function arrayIntersect (arr1, arr2) { 21 | return arr1.filter(function (item) { 22 | return arr2.includes(item); 23 | }); 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /content/helpers/buildQuery.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "buildQuery.js" 3 | date: 2018-01-24T12:16:26-05:00 4 | draft: false 5 | description: "Build a query string from an object of data." 6 | how: "https://gomakethings.com/how-to-build-a-query-string-from-an-object-of-data-with-vanilla-js/" 7 | demo: "https://codepen.io/cferdinandi/pen/rPNgEe" 8 | weight: 10 9 | noIndex: false 10 | --- 11 | 12 | ```js 13 | /*! 14 | * Build a query string from an object of data 15 | * (c) 2021 Chris Ferdinandi, MIT License, https://gomakethings.com 16 | * @param {Object} data The data to turn into a query string 17 | * @return {String} The query string 18 | */ 19 | function buildQuery (data) { 20 | return new URLSearchParams(data).toString(); 21 | } 22 | ``` -------------------------------------------------------------------------------- /content/helpers/cleanHTML.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "cleanHTML.js" 3 | date: 2018-01-24T12:16:26-05:00 4 | draft: false 5 | description: "Sanitize an HTML string to reduce the risk of XSS attacks." 6 | how: "https://gomakethings.com/how-to-sanitize-html-strings-with-vanilla-js-to-reduce-your-risk-of-xss-attacks/" 7 | demo: "https://codepen.io/cferdinandi/pen/MWmXNeN" 8 | weight: 10 9 | noIndex: false 10 | --- 11 | 12 | ```js 13 | /*! 14 | * Sanitize an HTML string 15 | * (c) 2021 Chris Ferdinandi, MIT License, https://gomakethings.com 16 | * @param {String} str The HTML string to sanitize 17 | * @param {Boolean} nodes If true, returns HTML nodes instead of a string 18 | * @return {String|NodeList} The sanitized string or nodes 19 | */ 20 | function cleanHTML (str, nodes) { 21 | 22 | /** 23 | * Convert the string to an HTML document 24 | * @return {Node} An HTML document 25 | */ 26 | function stringToHTML () { 27 | let parser = new DOMParser(); 28 | let doc = parser.parseFromString(str, 'text/html'); 29 | return doc.body || document.createElement('body'); 30 | } 31 | 32 | /** 33 | * Remove -------------------------------------------------------------------------------- /content/projects.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Project Ideas" 3 | date: 2018-01-24T11:48:20-05:00 4 | draft: false 5 | noTitle: false 6 | noIndex: false 7 | anchors: true 8 | --- 9 | 10 | The best way to learn JavaScript is by writing lots of code, but coming up with ideas for projects can be hard. Here's a short list to get you started. 11 | 12 | {{}} 13 | 14 | **Need help?** [Check out my vanilla JS learning resources.](/resources) 15 | 16 | 0. A show-and-hide/accordion script 17 | 0. Toggle password visibility with a checkbox 18 | 0. An app that converts Farenheit to Celcius and back 19 | 0. Display a random image or quote using [a free API](https://github.com/toddmotto/public-apis) 20 | 0. Pull in a list of today's top stories from the New York Times API 21 | 0. Count the number of words and characters in a block of text 22 | 0. Get a visitor's location and display their local weather 23 | 0. A toggle tab plugin 24 | 0. An image lazy loader 25 | 0. Automatically save form data as you type 26 | 0. Update a progress bar as you complete fields in a form 27 | 0. Filter a list of items using checkboxes (like on a shopping website) 28 | 0. Display a preview of content typed into a text field 29 | 0. A countdown timer 30 | 0. A todo list app 31 | 0. An app to randomly choose from a list 32 | 33 | {{}} 34 | -------------------------------------------------------------------------------- /content/reference/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Reference Guide" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | anchors: true 8 | --- 9 | 10 | A quick reference for commonly used JavaScript methods and browser APIs. 11 | 12 | *Unless otherwise noted, these work in all modern browsers on desktop and mobile. You can extend support back further with [polyfills](/polyfills).* 13 | 14 | {{}} 15 | 16 |
-------------------------------------------------------------------------------- /content/reference/ajax/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Ajax & APIs" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 160 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/ajax/async-await.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "async & await" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Write asynchronous code like it's synchronous." 8 | weight: 30 9 | --- 10 | 11 | When you use the `async` operator before a `function`, you turn it into an _async function_. 12 | 13 | Inside an _async function_, you can use the `await` operator before asynchronous code to tell the function to wait for that operation to complete before moving on. 14 | 15 | To handle errors, wrap your code in a `try...catch()`. 16 | 17 | ```javascript 18 | async function getAPIData () { 19 | try { 20 | let request = await fetch('https://jsonplaceholder.typicode.com/posts/'); 21 | if (!request.ok) throw request; 22 | let response = await request.json(); 23 | console.log(response); 24 | } catch (err) { 25 | console.warn(err); 26 | } 27 | } 28 | 29 | getAPIData(); 30 | ``` 31 | 32 | _**Note:** an async function always returns a promise, even if you're not actually making any asynchronous calls in it._ -------------------------------------------------------------------------------- /content/reference/ajax/fetch.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "fetch()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Make Promise-based HTTP request." 8 | weight: 10 9 | --- 10 | 11 | The Fetch API is used to make Promise-based, asynchronous HTTP requests. 12 | 13 | ## Basic Syntax 14 | 15 | Pass the URL for your HTTP request into the `fetch()` method as an argument. 16 | 17 | In a `then()` callback method, if the `response.ok` property is `true`, return the `response.json()`. Otherwise, return a rejected Promise. In the next `then()` callback, you can work with the JSON response `data`. Use the `catch()` method to handle errors. 18 | 19 | ```javascript 20 | fetch('https://jsonplaceholder.typicode.com/posts').then(function (response) { 21 | 22 | // The API call was successful! 23 | if (response.ok) { 24 | return response.json(); 25 | } 26 | 27 | // There was an error 28 | return Promise.reject(response); 29 | 30 | }).then(function (data) { 31 | // This is the JSON from our response 32 | console.log(data); 33 | }).catch(function (err) { 34 | // There was an error 35 | console.warn('Something went wrong.', err); 36 | }); 37 | ``` 38 | 39 | ## Options 40 | 41 | The `fetch()` method accepts a second argument that you can use to pass in an object of options. 42 | 43 | You can pass in the HTTP `method` (if you don't, `GET` is used by default), the request `body`, `header` details, and more. You can find [a full list of options on the Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters). 44 | 45 | ```javascript 46 | fetch('https://jsonplaceholder.typicode.com/posts', { 47 | method: 'POST', 48 | body: 'title=' + encodeURIComponent('My awesome new article') + '&body=' + encodeURIComponent('This is the text of my article'), 49 | headers: { 50 | 'Content-Type': 'application/json' 51 | }, 52 | referrer: 'no-referrer' 53 | }).then(function (response) { 54 | 55 | // The API call was successful! 56 | if (response.ok) { 57 | return response.json(); 58 | } 59 | 60 | // There was an error 61 | return Promise.reject(response); 62 | 63 | }).then(function (data) { 64 | // This is the JSON from our response 65 | console.log(data); 66 | }).catch(function (err) { 67 | // There was an error 68 | console.warn('Something went wrong.', err); 69 | }); 70 | ``` -------------------------------------------------------------------------------- /content/reference/ajax/multiple-endpoints.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Promise.all()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Wait for two or more asynchronous tasks to resolve." 8 | weight: 20 9 | --- 10 | 11 | The `Promise.all()` method accepts an array of promises. It doesn't resolve itself until all of the promises in the array resolve. If one of them fails, it rejects. 12 | 13 | This is useful when you have two or more APIs, and need data from both to continue. 14 | 15 | ```javascript 16 | Promise.all([ 17 | fetch('https://jsonplaceholder.typicode.com/posts'), 18 | fetch('https://jsonplaceholder.typicode.com/users') 19 | ]).then(function (responses) { 20 | // Get a JSON object from each of the responses 21 | return Promise.all(responses.map(function (response) { 22 | return response.json(); 23 | })); 24 | }).then(function (data) { 25 | // You would do something with both sets of data here 26 | // data[0] is the /posts endpoint 27 | // data[1] is the /users endpoint 28 | console.log(data); 29 | }).catch(function (error) { 30 | // if there's an error, log it 31 | console.log(error); 32 | }); 33 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arrays" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 70 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/arrays/array-concat.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.concat()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Merge two or more arrays together." 8 | weight: 80 9 | --- 10 | 11 | Merge two or more arrays together. Call `Array.concat()` on the first array, and pass each array to merge with it in as arguments. 12 | 13 | It returns a new array. The original arrays are not modified. 14 | 15 | ```javascript 16 | let sandwiches1 = ['turkey', 'tuna', 'blt']; 17 | let sandwiches2 = ['chicken', 'pb&j']; 18 | let allSandwiches = sandwiches1.concat(sandwiches2); 19 | 20 | // logs ["turkey", "tuna", "blt"] 21 | console.log(sandwiches1); 22 | 23 | // logs ["chicken", "pb&j"] 24 | console.log(sandwiches2); 25 | 26 | // logs ["turkey", "tuna", "blt", "chicken", "pb&j"] 27 | console.log(allSandwiches); 28 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-filter.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.filter()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Create a new array containing a subset of items from an existing ones." 8 | weight: 20 9 | --- 10 | 11 | Create a new array with only elements that pass a test you include as a callback function. The callback accepts three arguments: the current item in the loop's value, its index, and the array itself. All three are optional. 12 | 13 | ```javascript 14 | let numbers = [1, 2, 7, 42, 99, 101]; 15 | 16 | // Create a new array with only numbers greater than 10 17 | let biggerThanTen = numbers.filter(function (item) { 18 | return item > 10; 19 | }); 20 | 21 | // logs [42, 99, 101] 22 | console.log(biggerThanTen); 23 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-find.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.find()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the first item in an array that satisfies a condition." 8 | weight: 150 9 | --- 10 | 11 | Get the first item in an array that satisfies a conditions you specify in a callback function. If no match is found, it returns `undefined`. 12 | 13 | The callback accepts an argument that represents the current item as the method loops through the array. It should return a boolean value (`true` or `false`). 14 | 15 | ```javascript 16 | let sandwiches = ['turkey', 'tuna', 'ham', 'pb&j']; 17 | 18 | // logs "turkey" 19 | let turkey = sandwiches.find(function (sandwich) { 20 | return sandwich === 'turkey'; 21 | }); 22 | console.log(turkey); 23 | 24 | // logs "ham" 25 | // "pb&j "also has 3 letters, but "ham" shows up first in the array 26 | let threeLetters = sandwiches.find(function (sandwich) { 27 | return sandwich.length === 3; 28 | }); 29 | console.log(threeLetters); 30 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-findIndex.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.findIndex()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Find the index of an item in a multidimensional array." 8 | weight: 160 9 | --- 10 | 11 | Find the index of an item in a _multidimensional array_ (an array whose items include other arrays or objects). 12 | 13 | Pass a callback function into the `Array.findIndex()` method. The callback itself accepts three arguments: the current item in the loop, the index of the current item in the loop, and the array itself. All three are optional, and you can name them anything you want. 14 | 15 | Inside the callback, you can check some conditions about the current item. The `Array.findIndex()` method will return the index of the first item that you return `true` for. 16 | 17 | ```javascript 18 | let sandwiches = [ 19 | { 20 | name: 'turkey', 21 | smelly: false 22 | }, 23 | { 24 | name: 'tuna', 25 | smelly: true 26 | }, 27 | { 28 | name: 'pb&j', 29 | smelly: false 30 | } 31 | ]; 32 | 33 | // Find the index of the tuna sandwich 34 | // returns 1 35 | sandwiches.findIndex(function (sandwich) { 36 | if (sandwich.name === 'tuna') { 37 | return true; 38 | } 39 | }); 40 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-from.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.from()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Create a new array from an existing array or array-like object." 8 | weight: 130 9 | --- 10 | 11 | Create a new array from an existing one, or transform an array-like object (like a NodeList) into an array. Pass the array (or array-like object) to copy in as an argument. 12 | 13 | ```javascript 14 | let sandwiches = ['turkey', 'tuna', 'ham', 'pb&j']; 15 | let sandwichesCopy = Array.from(sandwiches); 16 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-indexOf.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.indexOf()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the index of the first matching item in an array." 8 | weight: 140 9 | --- 10 | 11 | Get the index of an item in an array. It returns the index of the item if it's in the array, and `-1` if it's not. 12 | 13 | ```javascript 14 | let sandwiches = ['turkey', 'tuna', 'ham', 'pb&j']; 15 | 16 | // returns 0 17 | sandwiches.indexOf('turkey'); 18 | 19 | // returns 3 20 | sandwiches.indexOf('pb&j'); 21 | 22 | // returns -1 23 | sandwiches.indexOf('grilled cheese'); 24 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-join.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.join()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Combine all items in an array into a string." 8 | weight: 60 9 | --- 10 | 11 | Combine all items in an array into a string, separated by a delimiter that you can pass in as an argument. By default, it will use a comma (`,`) as the delimiter if one is not provided. 12 | 13 | ```javascript 14 | let messages = [ 15 | 'I love Cape Cod potato chips.', 16 | 'What about you?' 17 | ]; 18 | 19 | let str = messages.join(); 20 | let strWithSpace = messages.join(' '); 21 | let strWithSmiley = messages.join(' =) '); 22 | 23 | // logs "I love Cape Cod potato chips.,What about you?" 24 | console.log(str); 25 | 26 | // logs "I love Cape Cod potato chips. What about you?" 27 | console.log(strWithSpace); 28 | 29 | // logs "I love Cape Cod potato chips. =) What about you?" 30 | console.log(strWithSmiley); 31 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-map.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.map()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Transform the items in an array and create a new one." 8 | weight: 10 9 | --- 10 | 11 | Loop through each item in an array, transform it, and return a new array. Pass in a callback function that accepts three arguments: the current item in the loop, its index, and the array itself. All three are optional. 12 | 13 | Whatever you `return` inside the callback function becomes the new value at that index in the new array. 14 | 15 | ```javascript 16 | /** 17 | * Double each number in an array 18 | */ 19 | 20 | let numbers = [1, 4, 9]; 21 | let doubles = numbers.map(function(num) { 22 | return num * 2; 23 | }); 24 | 25 | // logs [2, 8, 18] 26 | console.log(doubles); 27 | 28 | 29 | /** 30 | * Get an array of just names 31 | */ 32 | let data = [ 33 | { 34 | name: 'Kyle', 35 | occupation: 'Fashion Designer' 36 | }, 37 | { 38 | name: 'Liza', 39 | occupation: 'Web Developer' 40 | }, 41 | { 42 | name: 'Emily', 43 | occupation: 'Web Designer' 44 | }, 45 | { 46 | name: 'Melissa', 47 | occupation: 'Fashion Designer' 48 | }, 49 | { 50 | name: 'Tom', 51 | occupation: 'Web Developer' 52 | } 53 | ]; 54 | 55 | let names = data.map(function (item) { 56 | return item.name; 57 | }); 58 | 59 | // logs ["Kyle", "Liza", "Emily", "Melissa", "Tom"] 60 | console.log(names); 61 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-pop.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.pop()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Remove the last item from an array. " 8 | weight: 120 9 | --- 10 | 11 | Remove the last item from an array and returns it. The array is modified. 12 | 13 | ```javascript 14 | let wizards = ['Gandalf', 'Radagast', 'Merlin']; 15 | let last = wizards.pop(); 16 | 17 | // logs "Merlin" 18 | console.log(last); 19 | 20 | // logs ["Gandalf", "Radagast"] 21 | console.log(wizards); 22 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-push.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.push()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Add items to an array." 8 | weight: 70 9 | --- 10 | 11 | Add items to an array. Pass the new items in as arguments. 12 | 13 | ```javascript 14 | let sandwiches = ['turkey', 'tuna', 'blt']; 15 | sandwiches.push('chicken', 'pb&j'); 16 | 17 | // logs ["turkey", "tuna", "blt", "chicken", "pb&j"] 18 | console.log(sandwiches); 19 | ``` 20 | -------------------------------------------------------------------------------- /content/reference/arrays/array-reduce.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.reduce()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Take the content of an array and return a single value." 8 | weight: 30 9 | --- 10 | 11 | Take the content of an array and return a single value. That value can be anything: a string, number, object, or even another array. 12 | 13 | The `Array.reduce()` method accepts two arguments: a callback method to run against each item in the array, and a starting value. Both are required. 14 | 15 | The callback also accepts two arguments: the `accumulator`, which is the current combined value, and the `current` item in the loop. Whatever you return is used as the accumulator for the next item in the loop. On the very first loop, that starting value is used instead. 16 | 17 | ```javascript 18 | /** 19 | * Add all of the numbers in an array 20 | */ 21 | 22 | let numbers = [1, 2, 3]; 23 | let total = [1, 2, 3].reduce(function (sum, current) { 24 | return sum + current; 25 | }, 0); 26 | 27 | // logs 6 28 | console.log(total); 29 | 30 | 31 | /** 32 | * Create a new array with only the names of wizards in Huffepuff 33 | */ 34 | 35 | let wizards = [ 36 | { 37 | name: 'Harry Potter', 38 | house: 'Gryfindor' 39 | }, 40 | { 41 | name: 'Cedric Diggory', 42 | house: 'Hufflepuff' 43 | }, 44 | { 45 | name: 'Tonks', 46 | house: 'Hufflepuff' 47 | }, 48 | { 49 | name: 'Ronald Weasley', 50 | house: 'Gryfindor' 51 | }, 52 | { 53 | name: 'Hermione Granger', 54 | house: 'Gryfindor' 55 | } 56 | ]; 57 | 58 | // This combines what you would otherwise do with map() and filter() into one step 59 | let hufflepuff = wizards.reduce(function (newArr, wizard) { 60 | if (wizard.house === 'Hufflepuff') { 61 | newArr.push(wizard.name); 62 | } 63 | return newArr; 64 | }, []); 65 | 66 | // logs ["Cedric Diggory", "Tonks"] 67 | console.log(hufflepuff); 68 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-reverse.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.reverse()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Reverse the order of items in an array." 8 | weight: 40 9 | --- 10 | 11 | Reverse the order of items in an array. 12 | 13 | ```javascript 14 | let count = [1, 2, 3, 4, 5]; 15 | 16 | // Reverse the array order 17 | count.reverse(); 18 | 19 | // logs [5, 4, 3, 2, 1] 20 | console.log(count); 21 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-shift.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.shift()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Remove the first item from an array. " 8 | weight: 110 9 | --- 10 | 11 | Remove the first item from an array and returns it. The array is modified. 12 | 13 | ```javascript 14 | let wizards = ['Gandalf', 'Radagast', 'Merlin']; 15 | let first = wizards.shift(); 16 | 17 | // logs "Gandalf" 18 | console.log(first); 19 | 20 | // logs ["Radagast", "Merlin"] 21 | console.log(wizards); 22 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-slice.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.slice()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Copy a segment of an array into a new array." 8 | weight: 90 9 | --- 10 | 11 | Copy a segment of an array into a new array. 12 | 13 | The first argument is the array index to start at, and the second is the index to end on. Both are optional. If you omit the start index, it will start at the beginning. If you omit the end index, it will go to the end. 14 | 15 | The original array is not modified. 16 | 17 | ```javascript 18 | let sandwiches = ['turkey', 'tuna', 'chicken salad', 'italian', 'blt', 'grilled cheese']; 19 | 20 | // ["chicken salad", "italian", "blt", "grilled cheese"] 21 | let fewerSandwiches = sandwiches.slice(2); 22 | 23 | // ["chicken salad", "italian", "blt"] 24 | let fewerSandwiches2 = sandwiches.slice(2, 4); 25 | ``` 26 | 27 | To create a brand new copy of an array in its entirety, you can use `slice()` with no arguments. 28 | 29 | ```javascript 30 | let sandwichesCopy = sandwiches.slice(); 31 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-sort.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.sort()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Sort and reorder the items in an array." 8 | weight: 50 9 | --- 10 | 11 | Sort and reorder the items in an array. It modifies the original array, and by default will order the items alphanumerically. 12 | 13 | ```javascript 14 | let wizards = ['Merlin', 42, 'Gandalf', 2022, 'Radagast']; 15 | 16 | // Sort the wizard array 17 | // [2022, 42, "Gandalf", "Merlin", "Radagast"] 18 | wizards.sort(); 19 | ``` 20 | 21 | You can optionally pass in a callback function that will modify the default sorting behavior. 22 | 23 | The `Array.sort()` method loops through each item, and passes two items at a time as arguments into the callback function. You can compare those two items, and return an integer telling `Array.sort()` what to do with them. 24 | 25 | If you return `-1`, it will place the first item before the second one. If you return `1`, it will move the second item before the current one. If you return `0` (or nothing at all), it will leave them unchanged. 26 | 27 | ```javascript 28 | let trees = [ 29 | { 30 | type: 'White pine', 31 | pineCones: 4 32 | }, 33 | { 34 | type: 'Blue spruce', 35 | pineCones: 3 36 | }, 37 | { 38 | type: 'Douglas fir', 39 | pineCones: 7 40 | } 41 | ]; 42 | 43 | // sort the array so that the tree with the most pine cones is first, 44 | // and the one with the least pine cones is last 45 | trees.sort(function (tree1, tree2) { 46 | 47 | // If the tree1 has more pine cones, put it before tree2 48 | if (tree1.pineCones > tree2.pineCones) { 49 | return -1; 50 | } 51 | 52 | // Otherwise, put tree2 before tree1 53 | return 1; 54 | 55 | }); 56 | ``` -------------------------------------------------------------------------------- /content/reference/arrays/array-splice.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.splice()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Delete, replace, and add items to an array at specific indexes." 8 | weight: 100 9 | --- 10 | 11 | Delete, replace, and add items to an array at specific indexes. The `Array.splice()` method accepts three arguments: `start`, `delete`, and `items`. 12 | 13 | The first, `start`, is the index of the item you want to modify in the array. It's the only required argument. 14 | 15 | The second, `delete`, is the number of items to delete from the array. If you omit this argument, the `Array.splice()` method will remove every item from the `start` index on. If you set it to `0`, it won't remove any items. 16 | 17 | Finally, if you want to insert one or more items into the array, you can pass them in as additional arguments. 18 | 19 | ```javascript 20 | let sandwiches = ['turkey', 'tuna', 'ham', 'pb&j']; 21 | 22 | // Remove "ham" from the array 23 | // It has an index of 2, and we only want to remove 1 item 24 | sandwiches.splice(2, 1); 25 | 26 | // Add "italian" between "tuna" and and "ham" 27 | // Our target index is 2, we want to remove 0 items, and add "italian" 28 | sandwiches.splice(2, 0, 'italian'); 29 | 30 | // Replace "tuna" with "chicken salad" 31 | // It has an index of 1, we want to remove 1 item, and add "chicken salad" 32 | sandwiches.splice(1, 1, 'chicken salad'); 33 | ``` 34 | 35 | You can combine `splice()` with `indexOf()` to remove an item by it's name. 36 | 37 | ```javascript 38 | // Remove "pb&j" 39 | sandwiches.splice(sandwiches.indexOf('pb&j'), 1); 40 | ``` -------------------------------------------------------------------------------- /content/reference/attributes/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Attributes & Properties" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 50 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/attributes/getAttribute.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.getAttribute()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get an attribute on an element." 8 | weight: 10 9 | --- 10 | 11 | Get attributes (including data attributes) on an element. 12 | 13 | ```javascript 14 | let elem = document.querySelector('#lunch'); 15 | let sandwich = elem.getAttribute('data-sandwich'); 16 | ``` -------------------------------------------------------------------------------- /content/reference/attributes/hasAttribute.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.hasAttribute()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Check if an element has an attribute." 8 | weight: 40 9 | --- 10 | 11 | Check for the existence of an attribute (including data attributes) on an element. 12 | 13 | ```javascript 14 | let elem = document.querySelector('#lunch'); 15 | 16 | if (elem.hasAttribute('data-drink')) { 17 | console.log('Add a drink!'); 18 | } 19 | ``` -------------------------------------------------------------------------------- /content/reference/attributes/properties.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Properties" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get and set element properties." 8 | weight: 50 9 | --- 10 | 11 | HTML elements have dozens of properties that you can access directly. 12 | 13 | Some of them are _read only_, meaning you can get their value but not set it. Others can be used to both read and set values. [You can find a full list on the Mozilla Developer Network.](https://developer.mozilla.org/en-US/docs/Web/API/element) 14 | 15 | ```javascript 16 | let elem = document.querySelector('#main'); 17 | 18 | // Get the ID of the element 19 | // returns "main" 20 | let id = elem.id; 21 | 22 | // Set the ID of the element 23 | elem.id = 'secondary'; 24 | 25 | // Get the parentNode of the element 26 | // This property is read-only 27 | let parent = elem.parentNode; 28 | ``` -------------------------------------------------------------------------------- /content/reference/attributes/removeAttribute.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.removeAttribute()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Remove an attribute from an element." 8 | weight: 30 9 | --- 10 | 11 | Remove an attribute (including data attributes) on an element. 12 | 13 | ```javascript 14 | let elem = document.querySelector('#lunch'); 15 | elem.removeAttribute('data-chips'); 16 | ``` -------------------------------------------------------------------------------- /content/reference/attributes/setAttribute.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.setAttribute()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Set an attribute on an element." 8 | weight: 20 9 | --- 10 | 11 | Set an attribute (including data attributes) on an element. 12 | 13 | ```javascript 14 | let elem = document.querySelector('#lunch'); 15 | elem.setAttribute('data-sandwich', 'turkey'); 16 | ``` -------------------------------------------------------------------------------- /content/reference/browser-storage/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Browser Storage" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 140 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/browser-storage/cookies.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Cookies" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get and set cookie values." 8 | weight: 10 9 | --- 10 | 11 | You can use the `document.cookie` property to set a cookie. 12 | 13 | It's a string, using a `{KEY}={VALUE};` format. Cookies can only contain string values. 14 | 15 | ```javascript 16 | // Set a cookie named sandwich, with a value of turkey 17 | document.cookie = 'sandwich=turkey;'; 18 | ``` 19 | 20 | Cookies can also include several optional settings, most using a `key=value` format, separated by a semicolon (`;`). 21 | 22 | - **`path={path}`** - The path to set the cookie at. Defaults to the current path. It might be a good idea to set this to the root path: `path=/`. 23 | - **`domain={domain}`** - The domain for the cookie. Defaults to the current host name. 24 | - **`max-age={max age in seconds}`** - The maximum amount of time to keep the cookie, in seconds. 25 | - **`expires={date in GMT form}`** - A date on which to expire the cookie. 26 | - **`secure`** - The cookie can only be transmitted over HTTPS. 27 | - **`same-site={lax|strict|none}`** - Whether or not the browser can send the cookie to other sites. The default, `lax`, only sends with same-site requests and navigation `GET` requests; `strict` does not send to any external sites, even when following a link; and `none` does not place any restrictions. 28 | 29 | ```javascript 30 | // set to the root path 31 | // expires in two weeks: 60 seconds x 60 minutes x 24 hours x 14 days 32 | // (we'll look at the math behind this in the next section) 33 | document.cookie = `snack=chips; path=/; max-age=${60 * 60 * 24 * 14};`; 34 | ``` 35 | 36 | If you do not set either a `max-age` or `expires` value, cookies can potentially remain in the browser indefinitely. As a best practice, you should generally always set one of the two values. 37 | 38 | You can use the `document.cookie` property to get the cookies for a site. However, all of the cookies for a site are stored as a single string, which makes getting the value of one of them a bit tedious. 39 | 40 | [The `getCookie()` helper method](https://vanillajstoolkit.com/helpers/getcookie/) makes this easier. 41 | 42 | ```javascript 43 | let sandwich = getCookie('sandwich'); 44 | let snack = getCookie('snack'); 45 | ``` 46 | 47 | To delete a cookie, you set it again with a `max-age` of `0` or an `expires` date to the current time or sooner. The cookie value can be anything. 48 | 49 | Be sure that the `path` matches the one used to set the cookie, or it will not work. 50 | 51 | ```javascript 52 | // Delete the cookie 53 | document.cookie = `sandwich=turkey; path=/; max-age=0;`; 54 | ``` -------------------------------------------------------------------------------- /content/reference/browser-storage/localStorage.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "localStorage" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Store data locally in the browser for later use." 8 | weight: 20 9 | --- 10 | 11 | Use the local storage API to store data locally that the browser can access later. Data is stored indefinitely, and must be a string. 12 | 13 | ```javascript 14 | // Store data 15 | var someData = 'The data that I want to store for later.'; 16 | localStorage.setItem('myDataKey', someData); 17 | 18 | // Get data 19 | var data = localStorage.getItem('myDataKey'); 20 | 21 | // Remove data 22 | localStorage.removeItem('myDatakey'); 23 | ``` -------------------------------------------------------------------------------- /content/reference/browser-storage/sessionStorage.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "sessionStorage" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Store data locally for the duration of the current browser session." 8 | weight: 30 9 | --- 10 | 11 | Use the local storage API to store data locally that the browser can access later. Data is cleared when the browser session ends, and must be a string. 12 | 13 | ```javascript 14 | // Store data 15 | var someTempData = 'The data that I want to store temporarily.'; 16 | sessionStorage.setItem('myTempDataKey', someTempData); 17 | 18 | // Get data 19 | var tempData = sessionStorage.getItem('myTempDataKey'); 20 | 21 | // Remove data 22 | sessionStorage.removeItem('myTempDatakey'); 23 | ``` -------------------------------------------------------------------------------- /content/reference/classes/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Classes" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 30 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/classes/classList.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.classList" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Add, remove, toggle, and check for classes on an element." 8 | weight: 10 9 | --- 10 | 11 | Add, remove, toggle, and check for classes on an element. 12 | 13 | ```javascript 14 | let elem = document.querySelector('#sandwich'); 15 | 16 | // Add the .turkey class 17 | elem.classList.add('turkey'); 18 | 19 | // Remove the .tuna class 20 | elem.classList.remove('tuna'); 21 | 22 | // Toggle the .tomato class on or off 23 | // (Add the class if it's not already on the element, remove it if it is.) 24 | elem.classList.toggle('tomato'); 25 | 26 | // Check if an element has the .mayo class 27 | if (elem.classList.contains('mayo')) { 28 | console.log('add mayo!'); 29 | } 30 | ``` -------------------------------------------------------------------------------- /content/reference/classes/className.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.className" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get and set classes on an element." 8 | weight: 20 9 | --- 10 | 11 | Get all of the classes on an element as a string, add a class or classes, or completely replace or remove all classes. 12 | 13 | ```javascript 14 | let elem = document.querySelector('div'); 15 | 16 | // Get all of the classes on an element 17 | let elemClasses = elem.className; 18 | 19 | // Add a class to an element 20 | elem.className += ' vanilla-js'; 21 | 22 | // Completely replace all classes on an element 23 | elem.className = 'new-class'; 24 | ``` -------------------------------------------------------------------------------- /content/reference/dom-injection/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "DOM Injection" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 100 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/dom-injection/createElement.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "document.createElement()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Create an element." 8 | weight: 10 9 | --- 10 | 11 | Create an element. Pass in the element to create, without angled brackets (`<>`), as an argument 12 | 13 | ```javascript 14 | let div = document.createElement('div'); 15 | let link = document.createElement('a'); 16 | let article = document.createElement('article'); 17 | ``` -------------------------------------------------------------------------------- /content/reference/dom-injection/element-after.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.after()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Insert an element into the DOM after another one." 8 | weight: 30 9 | --- 10 | 11 | Insert elements and strings after another element. Call the `Node.after()` method on the node you want to insert after, and pass in one or more new elements or strings as arguments. 12 | 13 | ```html 14 |
Good morning
15 | ``` 16 | 17 | ```javascript 18 | // Create a new element 19 | let p = document.createElement('p'); 20 | p.textContent = 'Hello!'; 21 | 22 | // Get the target node 23 | let app = document.querySelector('#app'); 24 | 25 | // Insert the new node after the target node 26 | //
Good morning

Hello!

27 | app.after(p); 28 | 29 | // You can inject more than one item by passing in multiple arguments 30 | //
Good morning

Hello!

What's poppin' 31 | app.after(p, `What's poppin?`); 32 | ``` -------------------------------------------------------------------------------- /content/reference/dom-injection/element-append.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.append()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Insert an element at the end of a set of elements inside a shared parent." 8 | weight: 40 9 | --- 10 | 11 | Insert one or more elements or strings at the end of a set elements inside a shared parent. Call the `Element.append()` method on the target node, and pass in one or more new elements or strings as arguments. 12 | 13 | ```html 14 |
    15 |
  • Item 1
  • 16 |
  • Item 2
  • 17 |
  • Item 3
  • 18 |
19 | ``` 20 | 21 | ```javascript 22 | // Create a new element 23 | let li = document.createElement('li'); 24 | li.textContent = 'I am new here.'; 25 | 26 | // Create another new element 27 | let liToo = document.createElement('li'); 28 | liToo.textContent = `I'm new, too!`; 29 | 30 | // Get the parent node 31 | let list = document.querySelector('#list'); 32 | 33 | // Insert the new node after the last element in the parent node 34 | // ...
  • Item 3
  • I am new here.
  • 35 | list.append(li); 36 | 37 | // You can inject more than one item by passing in multiple arguments 38 | // ...
  • Item 3
  • I am new here.
  • I'm new, too!
  • 39 | list.append(li, liToo); 40 | ``` -------------------------------------------------------------------------------- /content/reference/dom-injection/element-before.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.before()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Insert an element into the DOM before another one." 8 | weight: 20 9 | --- 10 | 11 | Insert elements and strings before another element. Call the `Node.before()` method on the node you want to insert before, and pass in one or more new elements or strings as arguments. 12 | 13 | ```html 14 |
    Good evening
    15 | ``` 16 | 17 | ```javascript 18 | // Create a new element 19 | let p = document.createElement('p'); 20 | p.textContent = 'Hello!'; 21 | 22 | // Get the target node 23 | let app = document.querySelector('#app'); 24 | 25 | // Insert the new node before the target node 26 | //

    Hello!

    Good evening
    27 | app.before(p); 28 | 29 | // You can inject more than one item by passing in multiple arguments 30 | //

    Hello!

    What's poppin'
    Good evening
    31 | app.before(p, `What's poppin?`); 32 | ``` -------------------------------------------------------------------------------- /content/reference/dom-injection/element-prepend.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.prepend()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Insert an element at the beginning of a set of elements inside a shared parent." 8 | weight: 50 9 | --- 10 | 11 | Insert one or more elements or strings at the beginning of a set elements inside a shared parent. Call the `Element.prepend()` method on the target node, and pass in one or more new elements or strings as arguments. 12 | 13 | ```html 14 |
      15 |
    • Item 1
    • 16 |
    • Item 2
    • 17 |
    • Item 3
    • 18 |
    19 | ``` 20 | 21 | ```javascript 22 | // Create a new element 23 | let li = document.createElement('li'); 24 | li.textContent = 'I am new here.'; 25 | 26 | // Create another new element 27 | let liToo = document.createElement('li'); 28 | liToo.textContent = `I'm new, too!`; 29 | 30 | // Get the parent node 31 | let list = document.querySelector('#list'); 32 | 33 | // Insert the new node before the first element in the parent node 34 | //
  • I am new here.
  • Item 1
  • ... 35 | list.prepend(li); 36 | 37 | // You can inject more than one item by passing in multiple arguments 38 | //
  • I am new here.
  • I'm new, too!
  • Item 1
  • ... 39 | list.prepend(li, liToo); 40 | ``` -------------------------------------------------------------------------------- /content/reference/dom-injection/element-remove.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.remove()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Remove an element from the DOM." 8 | weight: 60 9 | --- 10 | 11 | Remove an element from the DOM. Call the `Node.remove()` method on the element you want to remove. 12 | 13 | ```html 14 |

    Hello, world!

    15 | ``` 16 | 17 | ```javascript 18 | let h1 = document.querySelector('h1'); 19 | h1.remove(); 20 | ``` -------------------------------------------------------------------------------- /content/reference/dom-injection/node-clone.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.clone()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Create a copy of a node." 8 | weight: 80 9 | --- 10 | 11 | Create a copy of a node. Call on the node to clone. If you want all of a node's child nodes to also be copied, pass in `true` as an argument. 12 | 13 | ```html 14 |
    15 |

    Hello, world!

    16 |

    How are you today?

    17 | Nice to see you again. 18 |
    19 | ``` 20 | 21 | ```javascript 22 | // returns
    23 | let app = document.querySelector('#app'); 24 | 25 | // Create a shallow clone 26 | // returns
    as an empty node 27 | let clone = app.cloneNode(); 28 | 29 | // Create a deep clone 30 | // returns
    with the h1, p, and text nodes 31 | let deepClone = app.cloneNode(true); 32 | ``` -------------------------------------------------------------------------------- /content/reference/dom-injection/node-replaceWith.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.replaceWith()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Replace an element with another." 8 | weight: 70 9 | --- 10 | 11 | Replace an element (and all of its HTML elements and content) with another. Call the `Node.replaceWith()` method on the target node, and pass in one or more elements or strings as arguments. 12 | 13 | ```html 14 |

    Good evening

    15 | ``` 16 | 17 | ```javascript 18 | // Get the target element 19 | let h1 = document.querySelector('h1'); 20 | 21 | // Create a new element 22 | let p = document.createElement('p'); 23 | p.textContent = 'Good morning'; 24 | 25 | // Replace the target with the new element 26 | //

    Good morning

    27 | h1.replaceWith(p); 28 | 29 | // You can replace it with more than one item by passing in multiple arguments 30 | //

    Good morning

    How are you today? 31 | h1.replaceWith(p, 'How are you today?'); 32 | ``` -------------------------------------------------------------------------------- /content/reference/es-modules/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "ES Modules" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 170 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/es-modules/default-exports.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Default exports" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Import all modules from a file." 8 | weight: 20 9 | --- 10 | 11 | Instead of naming every function you want to import, you can alternatively import _everything_, and assign all of the imported items to a variable. 12 | 13 | Instead of using object destructuring, `import *`, then, assign it to a variable using the `as` opertor. In our case, let's use an underscore (`_`), common with helper libraries. 14 | 15 | ```javascript 16 | import * as _ from './helpers.js'; 17 | 18 | // Get the total 19 | let total = _.add(num1, num2); 20 | ``` -------------------------------------------------------------------------------- /content/reference/es-modules/export.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "export" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Export modules for use in other files." 8 | weight: 10 9 | --- 10 | 11 | Use the `export` operator to export modules for use in other files. 12 | 13 | One way to do that is by adding the `export` operator before the variable or function expression. 14 | 15 | ```javascript 16 | export function add (num1, num2) { 17 | return num1 + num2; 18 | } 19 | 20 | export function subtract (num1, num2) { 21 | return num1 - num2; 22 | } 23 | ``` 24 | 25 | Alternatively, you can include an `export` at the end as a single line, with an object of exported variables and functions. You can use the object property shorthand approach for this. 26 | 27 | ```javascript 28 | function add (num1, num2) { 29 | return num1 + num2; 30 | } 31 | 32 | function subtract (num1, num2) { 33 | return num1 - num2; 34 | } 35 | 36 | export {add, subtract}; 37 | ``` -------------------------------------------------------------------------------- /content/reference/es-modules/import-all.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "import all" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Import all modules from a file." 8 | weight: 30 9 | --- 10 | 11 | Instead of naming every function you want to import, you can alternatively import _everything_, and assign all of the imported items to a variable. 12 | 13 | Instead of using object destructuring, `import *`, then, assign it to a variable using the `as` opertor. In our case, let's use an underscore (`_`), common with helper libraries. 14 | 15 | ```javascript 16 | import * as _ from './helpers.js'; 17 | 18 | // Get the total 19 | let total = _.add(num1, num2); 20 | ``` -------------------------------------------------------------------------------- /content/reference/es-modules/side-effects.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Side effects" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Import all modules from a file." 8 | weight: 40 9 | --- 10 | 11 | In ES modules, _side effects_ are "things that happen" in the module automatically, without the need for the developer to explicitly run a function. 12 | 13 | ES modules don't _need_ to have an `export`, and when you `import` a module, you don't _have_ to access any exports if it has them. Anything that runs as part of the imported file will run automatically when imported. 14 | 15 | ```js 16 | // sayHi.js 17 | function sayHi () { 18 | console.log('Hello there!'); 19 | } 20 | 21 | // Run on init 22 | sayHi(); 23 | ``` 24 | 25 | ```js 26 | // "Hello there!" will be automatically logged 27 | import './sayHi.js'; 28 | ``` -------------------------------------------------------------------------------- /content/reference/event-listeners/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Event Listeners" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 60 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/event-listeners/addEventListener.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.addEventListener()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Listen for events on an element." 8 | weight: 10 9 | --- 10 | 11 | Listen for events on an element. [You can find a full list of available events on the Mozilla Developer Network.](https://developer.mozilla.org/en-US/docs/Web/Events) 12 | 13 | ```javascript 14 | let btn = document.querySelector('#click-me'); 15 | 16 | btn.addEventListener('click', function (event) { 17 | console.log(event); // The event details 18 | console.log(event.target); // The clicked element 19 | }); 20 | ``` 21 | 22 | Certain events, like `focus`, don't bubble. In order to use event delegation with events that don't bubble, you can set an optional third argument on the `EventTarget.addEventListener()` method, called `useCapture`, to `true`. 23 | 24 | ```javascript 25 | // Listen for all focus events in the document 26 | document.addEventListener('focus', function (event) { 27 | // Run functions whenever an element in the document comes into focus 28 | }, true); 29 | ``` -------------------------------------------------------------------------------- /content/reference/event-listeners/customEvent.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "CustomEvent()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Create and emit custom events." 8 | weight: 20 9 | --- 10 | 11 | Create and emit custom events. 12 | 13 | The `CustomEvent()` method accepts two arguments: an event name, and and object of options. In the options, you can specify if the event should bubble and be cancelable (both `false` by default). You can also pass along additional information that an event listener can use with the `detail` property. 14 | 15 | After setting up your event, call the `dispatchEvent()` method on your element and pass in the event as an argument. 16 | 17 | ```javascript 18 | // Create a new event 19 | let event = new CustomEvent('myCustomEvent', { 20 | bubbles: true, 21 | cancelable: true, 22 | detail: { 23 | someDetail: 'the detail value' 24 | } 25 | }); 26 | 27 | // Dispatch the event 28 | let elem = document.querySelector('#the-element-to-emit-on'); 29 | elem.dispatchEvent(event); 30 | ``` -------------------------------------------------------------------------------- /content/reference/extract-copy/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Extract & Copy Properties" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 85 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/extract-copy/array-destructuring.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array Destructuring" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Extract variables from array properties." 8 | weight: 10 9 | --- 10 | 11 | A way to extract variables from array properties. 12 | 13 | Define _an array of variables_, and the destructuring syntax will pull the values at the matching indexes out and assign them to the variables. 14 | 15 | ```javascript 16 | let lunch = ['turkey sandwich', 'soda', 'chips', 'cookie']; 17 | 18 | let [entree, drink, side, desert] = lunch; 19 | 20 | // logs "turkey sandwich" 21 | console.log(entree); 22 | 23 | // logs "chips" 24 | console.log(side); 25 | ``` -------------------------------------------------------------------------------- /content/reference/extract-copy/object-destructuring.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Object Destructuring" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Assign variables from object properties." 8 | weight: 20 9 | --- 10 | 11 | A way to assign variables from object properties. 12 | 13 | Define _an object of variables_, and the destructuring syntax will pull the properties at the matching keys out and assign them to the variables. 14 | 15 | ```javascript 16 | let movies = { 17 | disney: 'Moana', 18 | pixar: 'Up', 19 | dreamworks: 'How to Train Your Dragon', 20 | nickelodeon: 'Wonder Park' 21 | }; 22 | 23 | let {disney, pixar, dreamworks, nickelodeon} = movies; 24 | 25 | // logs "Up" 26 | console.log(pixar); 27 | ``` 28 | 29 | You can also rename a variable to something different than its key in the object. In your object variable, add a colon (`:`) and the new variable name you'd like to use. 30 | 31 | ```javascript 32 | let {disney, pixar, dreamworks, nickelodeon: nick} = movies; 33 | 34 | // logs "Wonder Park" 35 | console.log(nick); 36 | ``` -------------------------------------------------------------------------------- /content/reference/extract-copy/spread-syntax.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Spread Syntax" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Expand array or object properties into their own values." 8 | weight: 30 9 | --- 10 | 11 | Take an array or object (or other iterable) and expand its items into their own individual values. 12 | 13 | ```javascript 14 | let sandwiches = ['tuna', 'turkey', 'pb&j']; 15 | 16 | // logs ["tuna", "turkey", "pb&j"] 17 | console.log(sandwiches); 18 | 19 | // logs tuna turkey pb&j 20 | console.log(...sandwiches); 21 | ``` 22 | 23 | You can use it to pass array values into a function. 24 | 25 | ```js 26 | let numbers = [4, 2]; 27 | 28 | // Instead of this... 29 | add(numbers[0], numbers[1]); 30 | 31 | // You can do this... 32 | add(...numbers); 33 | ``` 34 | 35 | You can also use to copy or merge arrays or objects. 36 | 37 | ```js 38 | let moreSandwiches = [...sandwiches1, ...sandwiches2]; 39 | let allWizards = {...radagast, ...gandalf}; 40 | ``` 41 | -------------------------------------------------------------------------------- /content/reference/extract-copy/structuredClone.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "structuredClone()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Expand array or object properties into their own values." 8 | weight: 40 9 | --- 10 | 11 | The `structuredClone()` method accepts an array or object as an argument, and returns a deep copy or deep clone. 12 | 13 | ```js 14 | // A multidimensional array 15 | let wizards = [{ 16 | name: 'Radagast', 17 | color: 'brown' 18 | }, { 19 | name: 'Gandalf', 20 | color: 'gray' 21 | }]; 22 | 23 | // Create a copy of the wizards array 24 | let wizardsCopy = structuredClone(wizards); 25 | ``` -------------------------------------------------------------------------------- /content/reference/html-text/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "HTML & Text" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 95 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/html-text/innerHTML.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.innerHTML" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get and set HTML content for an element." 8 | weight: 10 9 | --- 10 | 11 | Get and set the HTML content inside an element as a string. 12 | 13 | ```html 14 |
    15 |

    Hello world!

    16 |
    17 | ``` 18 | 19 | ```javascript 20 | let greeting = document.querySelector('.greeting'); 21 | 22 | // Get HTML content 23 | // returns "

    Hello world!

    " 24 | let html = greeting.innerHTML; 25 | 26 | // Set HTML content 27 | // This replaces what was in there already 28 | greeting.innerHTML = 'We can dynamically change the HTML. We can even include HTML elements like this link.'; 29 | 30 | // Add HTML to the end of an element's existing content 31 | greeting.innerHTML += ' Add this after what is already there.'; 32 | 33 | // Add HTML to the beginning of an element's existing content 34 | greeting.innerHTML = 'We can add this to the beginning. ' + elem.innerHTML; 35 | 36 | // You can inject entire elements into other ones, too 37 | greeting.innerHTML += '

    A new paragraph

    '; 38 | ``` -------------------------------------------------------------------------------- /content/reference/html-text/innerText.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.innerText" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get and set the _rendered text_ of an element." 8 | weight: 40 9 | --- 10 | 11 | Get and set the _rendered text_ of an element (and omit the markup). 12 | 13 | The `Element.innerText` property returns only rendered text, similar to what a user would be able to select with their cursor or the keyboard when highlighting text. Any HTML elements included in a string when setting content are automatically encoded and rendered as-is. 14 | 15 | ```html 16 |
    17 | 22 | 23 |

    Hello world!

    24 |
    25 | ``` 26 | 27 | ```javascript 28 | let elem = document.querySelector('.greeting'); 29 | 30 | // Get text content 31 | // returns "Hello world!" 32 | let text = elem.innerText; 33 | 34 | // Set text content 35 | // This completely replaces whats there, including any HTML elements 36 | elem.innerText = 'We can dynamically change the content.'; 37 | 38 | // Add text to the end of an element's existing content 39 | elem.innerText += ' Add this after what is already there.'; 40 | 41 | // Add text to the beginning of an element's existing content 42 | elem.innerText = 'We can add this to the beginning. ' + elem.innerText; 43 | 44 | // HTML elements are automatically encoded and rendered as-is 45 | elem.innerText = '

    See you later!

    '; 46 | ``` -------------------------------------------------------------------------------- /content/reference/html-text/outerHTML.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.outerHTML" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get and set HTML content _including_ an element." 8 | weight: 20 9 | --- 10 | 11 | Get and set the HTML content _including_ an element. This works the same as `Element.innerHTML`, but includes the element itself when getting and updating HTML content. 12 | 13 | ```html 14 |
    15 |

    Hello world!

    16 |
    17 | ``` 18 | 19 | ```javascript 20 | let greeting = document.querySelector('.greeting'); 21 | 22 | // Get HTML content 23 | // returns "

    Hello world!

    " 24 | let html = greeting.outerHTML; 25 | 26 | // Set HTML content 27 | // This completely replaces the
    element and all of its content 28 | greeting.outerHTML = '

    Goodbye, friend! Click here to leave.'; 29 | 30 | // Add HTML after the element (and outside of it) 31 | greeting.outerHTML += ' Add this after what is already there.'; 32 | 33 | // Add HTML before the element (and outside of it) 34 | greeting.outerHTML = 'We can add this to the beginning. ' + greeting.innerHTML; 35 | ``` -------------------------------------------------------------------------------- /content/reference/html-text/textContent.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.textContent" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get and set the text of an element (without markup)." 8 | weight: 30 9 | --- 10 | 11 | Get and set the text of an element (and omit the markup) as a string. 12 | 13 | The `Node.textContent` property gets _all_ of the text content, including CSS properties inside of a `style` element and `hidden` UI elements. Any HTML elements included in a string when setting content with the `Node.textContent` property are automatically encoded and rendered as-is. 14 | 15 | ```html 16 |

    17 | 22 | 23 |

    Hello world!

    24 |
    25 | ``` 26 | 27 | ```javascript 28 | let greeting = document.querySelector('.greeting'); 29 | 30 | // Get text content 31 | // returns "p {color: rebeccapurple;} This is not rendered. Hello world!" 32 | let text = greeting.textContent; 33 | 34 | // Set text content 35 | // This completely replaces whats there, including any HTML elements 36 | greeting.textContent = 'We can dynamically change the content.'; 37 | 38 | // Add text to the end of an element's existing content 39 | greeting.textContent += ' Add this after what is already there.'; 40 | 41 | // Add text to the beginning of an element's existing content 42 | greeting.textContent = 'We can add this to the beginning. ' + greeting.textContent; 43 | 44 | // HTML elements are automatically encoded and rendered as-is 45 | greeting.textContent = '

    See you later!

    '; 46 | ``` -------------------------------------------------------------------------------- /content/reference/javascript-free/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "JavaScript-Free Components" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 999 8 | --- 9 | 10 | It's sometimes possible to create JavaScript-free interactive components entirely with native HTML elements. 11 | 12 | These are *not* hacks. They're semantically valid, accessible components that browsers give you out-of-the-box. These can all be treated as progressive enhancements, with no fallbacks needed for unsupported browsers. 13 | 14 | *__Quick aside:__ many of the CSS-only versions of JavaScript components that you see on other sites __are__ hacks, and suffer from usability and accessibility issues as a result.* -------------------------------------------------------------------------------- /content/reference/javascript-free/autocomplete.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Autocomplete" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Create an autocompletion text input." 8 | weight: 20 9 | --- 10 | 11 | Create a label and input like you normally would. Then create a `datalist` element, and add an `option` element for each autocomplete choice. 12 | 13 | Give the `datalist` an ID. Add the `list` property to your input with a value equal to your `datalist` ID. 14 | 15 | ```html 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ``` 26 | 27 | [Autocomplete Demo →](https://codepen.io/cferdinandi/pen/BMEVrx) -------------------------------------------------------------------------------- /content/reference/javascript-free/disclosure.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Disclosure" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Create an expand-and-collapse disclosure element." 8 | weight: 10 9 | --- 10 | 11 | Use the `details` and `summary` elements to create expand-and-collapse disclosure components. 12 | 13 | Put your entire content inside a `details` element. The heading that should act as the toggle goes inside a `summary` element. Use the `open` attribute to make your disclosure component expanded by default. 14 | 15 | ```html 16 |
    17 | The toggle 18 | The content. 19 |
    20 | 21 |
    22 | Another toggle 23 | Expanded by default 24 |
    25 | ``` 26 | 27 | You can style the dropdown arrow with CSS. 28 | 29 | ```css 30 | /** 31 | * 1. Styling for Firefox and other non-webkit/blink browsers 32 | * 2. Styling for webkit and blink 33 | */ 34 | summary, /* 1 */ 35 | summary::-webkit-details-marker { /* 2 */ 36 | list-style-image: url(''); 37 | } 38 | ``` 39 | 40 | [Disclosure Demo →](https://codepen.io/cferdinandi/pen/exoKgo) -------------------------------------------------------------------------------- /content/reference/javascript-free/smooth-scrolling.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Smooth Scrolling" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Animate scrolling to anchor links." 8 | weight: 30 9 | --- 10 | 11 | The `scroll-behavior` CSS property tells the browser how to handle scrolling triggered by anchor links and such. 12 | 13 | The default behavior, `auto`, is the jump-to-location you’re used to seeing. If you set it to `smooth`, the browser animates scrolling down the page. 14 | 15 | If you only want this behavior inside a container, apply it to that element. Otherwise, apply it to the whole document. 16 | 17 | ```css 18 | /** 19 | * Smooth scrolling inside an element 20 | */ 21 | #my-element { 22 | scroll-behavior: smooth; 23 | } 24 | 25 | /** 26 | * Smooth scrolling on the whole document 27 | */ 28 | html { 29 | scroll-behavior: smooth; 30 | } 31 | ``` 32 | 33 | For people prone to motion sickness, this effect can be really jarring, though. 34 | 35 | Fortunately, users in some browsers/operating systems can express their preference for reduced motion effects with the Reduce Motion API. We can listen for that setting in our CSS, and turn off smooth scrolling for them. 36 | 37 | ```css 38 | @media screen and (prefers-reduced-motion: reduce) { 39 | #my-element { 40 | scroll-behavior: auto; 41 | } 42 | 43 | html { 44 | scroll-behavior: auto; 45 | } 46 | } 47 | ``` 48 | 49 | *If you're using a fixed or sticky header, you can prevent anchor links from scrolling behind it with [the `scroll-margin-top` property](https://gomakethings.com/how-to-prevent-anchor-links-from-scrolling-behind-a-sticky-header-with-one-line-of-css/).* 50 | 51 | [Smooth Scroll Demo →](https://codepen.io/cferdinandi/pen/LqGZrb) -------------------------------------------------------------------------------- /content/reference/json/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "JSON" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 150 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/json/json-parse.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "JSON.parse()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Convert stringified JSON back into an object or array." 8 | weight: 20 9 | --- 10 | 11 | Convert stringified JSON back into an object or array. 12 | 13 | ```javascript 14 | // Get data from local storage 15 | let savedLunch = JSON.parse(localStorage.getItem('lunchOrder')); 16 | let savedDrinks = JSON.parse(localStorage.getItem('drinkOptions')); 17 | ``` -------------------------------------------------------------------------------- /content/reference/json/json-stringify.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "JSON.stringify()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Convert object or array data into a string." 8 | weight: 20 9 | --- 10 | 11 | Convert object or array data into a string. 12 | 13 | ```js 14 | // Save an object 15 | let lunch = { 16 | sandwich: 'turkey', 17 | chips: 'Cape Cod', 18 | drink: 'Pepsi' 19 | }; 20 | localStorage.setItem('lunchOrder', JSON.stringify(lunch)); 21 | 22 | // Save an array 23 | let drinks = ['Pepsi', 'water', 'lemonade']; 24 | localStorage.setItem('drinkOptions', JSON.stringify(drinks)); 25 | ``` -------------------------------------------------------------------------------- /content/reference/loops/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Loops" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 20 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/loops/for-in.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "for...in" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Loop over plain objects." 8 | weight: 30 9 | --- 10 | 11 | Loop over plain objects (`{}`). 12 | 13 | ```javascript 14 | let lunch = { 15 | sandwich: 'ham', 16 | snack: 'chips', 17 | drink: 'soda', 18 | desert: 'cookie', 19 | guests: 3, 20 | alcohol: false, 21 | }; 22 | 23 | // logs "sandwich", "ham", "snack", "chips", "drink", "soda", "desert", "cookie", "guests", 3, "alcohol", false 24 | for (let key in lunch) { 25 | console.log(key); // key 26 | console.log(lunch[key]); // value 27 | } 28 | ``` -------------------------------------------------------------------------------- /content/reference/loops/for-of.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "for...of" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Loop over iterable objects." 8 | weight: 20 9 | --- 10 | 11 | Loop over _iterable objects_. That includes strings, arrays, and other array-like objects such as NodeLists, HTMLCollections, and HTMLFormControlsCollection, but _not_ plain objects (`{}`). 12 | 13 | ```javascript 14 | let sandwiches = ['turkey', 'tuna', 'ham', 'pb&j']; 15 | 16 | // logs "tuna", "ham", "turkey", "pb&j" 17 | for (let sandwich of sandwiches) { 18 | console.log(sandwich); 19 | } 20 | ``` -------------------------------------------------------------------------------- /content/reference/loops/for.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "for" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Loop through arrays and array-like objects." 8 | weight: 10 9 | --- 10 | 11 | Loop through arrays, NodeLists, and other array-like objects. 12 | 13 | ```javascript 14 | let sandwiches = ['turkey', 'tuna', 'ham', 'pb&j']; 15 | 16 | // logs 0, "tuna", 1, "ham", 2, "turkey", 3, "pb&j" 17 | for (let i = 0; i < sandwiches.length; i++) { 18 | console.log(i); // index 19 | console.log(sandwiches[i]); // value 20 | } 21 | ``` -------------------------------------------------------------------------------- /content/reference/loops/foreach.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Array.forEach() & NodeList.forEach()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Loop through arrays and NodeLists." 8 | weight: 40 9 | --- 10 | 11 | The `Array.forEach()` and `NodeList.forEach()` methods provide a simpler way to iterate over arrays and NodeLists while still having access to the index. 12 | 13 | You pass a callback function into the `forEach()` method. The callback itself accepts three arguments: the current item in the loop, the index of the current item in the loop, and the array itself. All three are optional, and you can name them anything you want. 14 | 15 | ```javascript 16 | let sandwiches = ['turkey', 'tuna', 'ham', 'pb&j']; 17 | 18 | // logs 0, "tuna", 1, "ham", 2, "turkey", 3, "pb&j" 19 | sandwiches.forEach(function (sandwich, index) { 20 | console.log(index); // index 21 | console.log(sandwich); // value 22 | }); 23 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Numbers" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 65 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/numbers/basic-math.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Basic math" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Do basic arithmetic with JavaScript." 8 | weight: 60 9 | --- 10 | 11 | JavaScript includes a handful of basic arithmetic operators: 12 | 13 | | Operator | Action | 14 | |----------|-----------| 15 | | `+` | Add | 16 | | `-` | Subtract | 17 | | `*` | Multiply | 18 | | `/` | Divide | 19 | | `%` | Remainder | 20 | 21 | ```javascript 22 | // Add 23 | // logs 4 24 | console.log(2 + 2); 25 | 26 | // Subtract 27 | // logs 3 28 | console.log(4 - 1); 29 | 30 | // Divide 31 | // logs 2 32 | console.log(4 / 2); 33 | 34 | // Multiply 35 | // logs 10 36 | console.log(5 * 2); 37 | 38 | // Remainder 39 | // logs 1 (2 goes into 5 twice, with 1 left over) 40 | console.log(5 % 2); 41 | ``` 42 | 43 | You can combine operators. Group the items you want to run first/together with parentheses. 44 | 45 | ```javascript 46 | let total = (3 + 1) * 2; 47 | 48 | // logs 8 (3 plus 1 is 4, multiplied by 2) 49 | console.log(total); 50 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/comparisons.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Comparisons" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Compare two numbers." 8 | weight: 80 9 | --- 10 | 11 | JavaScript includes a handful of comparison operators: 12 | 13 | | Operator | Action | 14 | |----------|--------------------------| 15 | | `>` | Greater than | 16 | | `<` | Less than | 17 | | `===` | Equals | 18 | | `!==` | Does not equal | 19 | | `>=` | Greater than or equal to | 20 | | `<=` | Less than or equal to | 21 | 22 | ```javascript 23 | // Greater than 24 | // logs true 25 | console.log(2 > 1); 26 | 27 | // Less than 28 | // logs false 29 | console.log(2 < 1); 30 | 31 | // Equals 32 | // logs true 33 | console.log(2 === 2); 34 | 35 | // Does not equal 36 | // logs true 37 | console.log(2 !== 1); 38 | 39 | // Greater than or equal to 40 | // logs true 41 | console.log(2 >= 1); 42 | 43 | // Less than or equal to 44 | // logs true 45 | console.log(2 <= 2); 46 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/increment-decrement.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Increment & Decrement" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Increment numbers up and down." 8 | weight: 70 9 | --- 10 | 11 | You can increment numbers up one in value with the `++` operator, and decrement them down one in value using the `--` operator. 12 | 13 | ```javascript 14 | let num = 1; 15 | 16 | // Increment 17 | // logs 2 18 | num++; 19 | console.log(num); 20 | 21 | // Decrement 22 | // logs 1 23 | num--; 24 | console.log(num); 25 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/math-abs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Math.abs()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the absolute value of a number." 8 | weight: 90 9 | --- 10 | 11 | Get the absolute (positive) value of a number. 12 | 13 | ```javascript 14 | // returns 42 15 | Math.abs(42); 16 | 17 | // also returns 42 18 | Math.abs(-42); 19 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/math-ceil.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Math.ceil()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the smallest integer greater than or equal to a number." 8 | weight: 110 9 | --- 10 | 11 | Returns the smallest integer (whole number) greater than or equal to a number. 12 | 13 | ```javascript 14 | // returns 42 15 | Math.ceil(42); 16 | 17 | // returns 4 18 | Math.ceil(3.14); 19 | 20 | // Returns -3 21 | Math.ceil(-3.14); 22 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/math-floor.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Math.floor()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the largest integer less than or equal to a number." 8 | weight: 100 9 | --- 10 | 11 | Returns the largest integer (whole number) less than or equal to a number. 12 | 13 | ```javascript 14 | // returns 42 15 | Math.floor(42); 16 | 17 | // returns 3 18 | Math.floor(3.14); 19 | 20 | // Returns -4 21 | Math.floor(-3.14); 22 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/math-max.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Math.max()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the largest number from a set of numbers" 8 | weight: 120 9 | --- 10 | 11 | Returns the largest number from a set of numbers. Pass each number in as an argument. 12 | 13 | ```javascript 14 | // returns 42 15 | Math.max(42, 3.14, 27); 16 | 17 | // returns -3.14 18 | Math.max(-42, -3.14, -27); 19 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/math-min.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Math.min()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the lowest number from a set of numbers." 8 | weight: 130 9 | --- 10 | 11 | Returns the lowest number from a set of numbers. Pass each number in as an argument. 12 | 13 | ```javascript 14 | // returns 3.14 15 | Math.min(42, 3.14, 27); 16 | 17 | // returns -42 18 | Math.min(-42, -3.14, -27); 19 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/math-random.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Math.random()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Return a random float between `0` and `1`." 8 | weight: 140 9 | --- 10 | 11 | Returns a random float (decimal) between `0` and `1`. 12 | 13 | This is _not_ cryptographically secure. Do not use it for anything security related. 14 | 15 | ```javascript 16 | // returns random decimal 17 | Math.random(); 18 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/number-toFixed.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Number.toFixed()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Format a number to a fixed number of decimal places." 8 | weight: 40 9 | --- 10 | 11 | Format a number to a fixed number of decimal places. Pass in the number of decimal places as an argument. 12 | 13 | ```javascript 14 | let pi = 3.14159; 15 | let eleven = 11; 16 | 17 | // returns 3.14 18 | pi.toFixed(2); 19 | 20 | // returns 11.000 21 | eleven.toFixed(3); 22 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/number-toString.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Number.toString()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Convert a number to a string." 8 | weight: 50 9 | --- 10 | 11 | Convert a number to a string. 12 | 13 | ```javascript 14 | let pi = 3.14; 15 | let eleven = 11; 16 | 17 | // returns "3.14" 18 | pi.toString(); 19 | 20 | // returns "11" 21 | eleven.toString(); 22 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/number.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Number()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Convert a string into a number." 8 | weight: 30 9 | --- 10 | 11 | Convert a string to a number. 12 | 13 | Sometimes it returns integer. Other times it returns a float. And if you pass in a string with random text in it, you’ll get `NaN`, an acronym for *Not a Number*. 14 | 15 | As a result of this inconsistency, it’s generally safer to use `parseInt()` or `parseFloat()`. If you know the format of the number you’d like, use those instead. If you want the string to fail with `NaN` if it has other characters in it, though, `Number()` may actually be a better choice. 16 | 17 | ```javascript 18 | // returns 123 19 | Number('123'); 20 | 21 | // returns 12.3 22 | Number('12.3'); 23 | 24 | // returns NaN 25 | Number('3.14someRandomStuff'); 26 | ``` -------------------------------------------------------------------------------- /content/reference/numbers/parseFloat.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "parseFloat()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Convert a string into a point number (a number with decimal points)." 8 | weight: 20 9 | --- 10 | 11 | Convert a string into a point number (a number with decimal points). 12 | 13 | ```javascript 14 | // returns 3.14 15 | parseFloat('3.14'); 16 | 17 | // also returns 3.14 18 | parseFloat('3.14someRandomStuff'); 19 | 20 | // returns 3 21 | parseFloat('3'); 22 | ``` 23 | -------------------------------------------------------------------------------- /content/reference/numbers/parseInt.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "parseInt()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Convert a string into an integer (whole number)." 8 | weight: 10 9 | --- 10 | 11 | Convert a string into an integer (a whole number). The second argument, `10`, is called the `radix`. This is the base number used in mathematical systems. For our use, it should always be `10`. 12 | 13 | ```javascript 14 | // returns 42 15 | parseInt('42', 10); 16 | 17 | // also returns 42 18 | parseInt('42px', 10); 19 | ``` -------------------------------------------------------------------------------- /content/reference/objects/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Objects" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 80 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/objects/delete.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "delete" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Remove an item from an object." 8 | weight: 30 9 | --- 10 | 11 | Remove an item from an object. Use the `delete` operator on the key to remove. 12 | 13 | ```javascript 14 | let lunch = { 15 | sandwich: 'turkey', 16 | chips: 'cape cod', 17 | drink: 'soda' 18 | }; 19 | 20 | // Remove the chips key from the lunch object 21 | delete lunch.chips; 22 | 23 | // logs {sandwich: 'turkey', drink: 'soda'} 24 | console.log(lunch); 25 | ``` -------------------------------------------------------------------------------- /content/reference/objects/object-assign.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Object.assign()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Perform a shallow merge of two or more objects." 8 | weight: 40 9 | --- 10 | 11 | Perform a shallow merge of two or more objects into the first. Pass in each object to merge as an argument. 12 | 13 | *__Note:__ in a shallow merge, nested objects are overwritten completely rather than having their values merged together.* 14 | 15 | ```javascript 16 | let object1 = { 17 | apple: 0, 18 | banana: { 19 | weight: 52, 20 | price: 100 21 | }, 22 | cherry: 97 23 | }; 24 | 25 | let object2 = { 26 | banana: { 27 | price: 200 28 | }, 29 | durian: 100 30 | }; 31 | 32 | let object3 = { 33 | apple: 'yum', 34 | pie: 3.214, 35 | applePie: true 36 | }; 37 | 38 | // In this example, "banana" will only contain {price: 200} 39 | // In a deep merge, it would contain {price: 200, weight: 52} 40 | let merged = Object.assign(object1, object2, object3); 41 | ``` 42 | 43 | All objects are merged into the first. To create a new object, pass in an empty object as the first argument. 44 | 45 | ```javascript 46 | let mergedNewObj = Object.assign({}, object1, object2, object3); 47 | ``` -------------------------------------------------------------------------------- /content/reference/objects/object-entries.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Object.entries()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get an array of key/value pairs from an object." 8 | weight: 20 9 | --- 10 | 11 | Return an array of key/value pairs from an object, also represented as arrays. Pass in the object as an argument. 12 | 13 | ```javascript 14 | let lunch = { 15 | sandwich: 'turkey', 16 | chips: 'cape cod', 17 | drink: 'soda' 18 | }; 19 | 20 | // logs [["sandwich", "turkey"], ["chips", "cape cod"], ["drink", "soda"]] 21 | let entries = Object.entries(lunch); 22 | console.log(entries); 23 | ``` -------------------------------------------------------------------------------- /content/reference/objects/object-freeze.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Object.freeze()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Make an object or array immutable." 8 | weight: 50 9 | --- 10 | 11 | Make an object or array itself immutable. Pass the array or object in as an argument. Once run, you can't add, update, or delete items or properties from the array or object. 12 | 13 | ```javascript 14 | let wizard = { 15 | name: 'Merlin', 16 | age: 'old AF' 17 | }; 18 | 19 | // Freeze the wizard object 20 | Object.freeze(wizard); 21 | 22 | // Try to make updates 23 | // This will not work 24 | wizard.age = 42; 25 | wizard.wand = true; 26 | delete wizard.name; 27 | 28 | // logs {name: "Merlin", age: "old AF"} 29 | console.log(wizard); 30 | ``` -------------------------------------------------------------------------------- /content/reference/objects/object-function-shorthand.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Object Function Shorthand" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "A shorthand for defining functions in an object." 8 | weight: 70 9 | --- 10 | 11 | Instead of creating a key name and then writing `function () {}`, you can add a named function _without_ the `function` keyword. 12 | 13 | ```javascript 14 | let wizard = { 15 | 16 | // The old way of adding functions 17 | summon: function () { 18 | console.log('From out of thin air, watch me make a bear'); 19 | }, 20 | 21 | // The ES6 shorthand way 22 | vanish () { 23 | console.log(`Now you see me, now you don't.`); 24 | } 25 | 26 | }; 27 | ``` -------------------------------------------------------------------------------- /content/reference/objects/object-keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Object.keys()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get an array of keys from an object." 8 | weight: 10 9 | --- 10 | 11 | Return an array of keys from an object. Pass in the object as an argument. 12 | 13 | ```javascript 14 | let lunch = { 15 | sandwich: 'turkey', 16 | chips: 'cape cod', 17 | drink: 'soda' 18 | }; 19 | 20 | // logs ["sandwich", "chips", "drink"] 21 | let keys = Object.keys(lunch); 22 | console.log(keys); 23 | ``` -------------------------------------------------------------------------------- /content/reference/objects/object-property-shorthand.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Object Property Shorthand" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "A shorthand for defining object properties." 8 | weight: 60 9 | --- 10 | 11 | If you want to define a property in an object, and that key name already exists as a variable within the object's scope, you don't have to explicitly assign a value. You can use just the key name, and that variable's value is used automatically. 12 | 13 | ```javascript 14 | // Some details 15 | let name = 'Merlin'; 16 | let job = 'wizard'; 17 | let age = 'old AF'; 18 | 19 | // The object 20 | let wizard = { 21 | name: name, // The old way 22 | job, // ES6 shorthand 23 | age // ES6 shorthand 24 | }; 25 | ``` -------------------------------------------------------------------------------- /content/reference/objects/optional-chaining.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Optional Chaining" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Chain properties only if they're not `undefined` or `null`." 8 | weight: 80 9 | --- 10 | 11 | Optional chaining is a browser-native way to chain methods or properties, and conditionally continue down the chain only if the value is not `null` or `undefined`. 12 | 13 | To use optional chaining, add a question mark (`?`) before the dot (`.`) in your chain. 14 | 15 | ```javascript 16 | // returns "Abracadabra!" 17 | let summonOptional = wizard?.spells?.summon?.phrase; 18 | 19 | // returns undefined but does not throw an error 20 | let teacupsOptional = wizard?.spells?.teacup?.phrase; 21 | ``` 22 | -------------------------------------------------------------------------------- /content/reference/selectors/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Selectors" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 10 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/selectors/document-querySelector.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "document.querySelector()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Find the first matching element on a page." 8 | weight: 20 9 | --- 10 | 11 | Find the first matching element on a page. If an element isn't found, `querySelector()` returns `null`. 12 | 13 | ```javascript 14 | // The first button 15 | let button = document.querySelector('button'); 16 | 17 | // The first element with the .bg-red class 18 | let red = document.querySelector('.bg-red'); 19 | 20 | // The first element with a data attribute of snack equal to carrots 21 | let carrots = document.querySelector('[data-snack="carrots"]'); 22 | ``` -------------------------------------------------------------------------------- /content/reference/selectors/document-querySelectorAll.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "document.querySelectorAll()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Find all matching elements on a page." 8 | weight: 10 9 | --- 10 | 11 | Find all matching elements on a page. You can use any valid CSS selector. 12 | 13 | ```javascript 14 | // Get all button elements 15 | let buttons = document.querySelectorAll('button'); 16 | 17 | // Get all elements with the .bg-red class 18 | let elemsRed = document.querySelectorAll('.bg-red'); 19 | 20 | // Get all elements with the [data-snack] attribute 21 | let elemsSnacks = document.querySelectorAll('[data-snack]'); 22 | ``` -------------------------------------------------------------------------------- /content/reference/selectors/element-matches.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.matches()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Check if an element would be selected by a particular selector or set of selectors." 8 | weight: 30 9 | --- 10 | 11 | Check if an element would be selected by a particular selector or set of selectors. Returns `true` if the element is a match, and `false` when it's not. 12 | 13 | ```javascript 14 | // Check if the first .bg-red element has the [data-snack attribute] 15 | let red = document.querySelector('.bg-red'); 16 | if (red.matches('[data-snack]')) { 17 | console.log('Yummy snack!'); 18 | } else { 19 | console.log('No snacks'); 20 | } 21 | ``` -------------------------------------------------------------------------------- /content/reference/strings/string-includes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.includes()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Check if a string contains a substring." 8 | weight: 110 9 | --- 10 | 11 | Check if a string contains a substring. Returns a boolean: `true` if the string has the substring, and `false` if it doesn't. It's case-sensitive. 12 | 13 | ```javascript 14 | let str = 'I love Cape Cod potato chips.'; 15 | 16 | // returns true 17 | str.includes('Cape Cod'); 18 | 19 | // returns false 20 | str.includes('cape cod'); 21 | 22 | // returns false 23 | str.includes('chocolate'); 24 | ``` -------------------------------------------------------------------------------- /content/reference/strings/string-indexOf.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.indexOf()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Find the index of a substring inside a string." 8 | weight: 100 9 | --- 10 | 11 | Find a substring inside a string. It returns the index of where the substring starts in the string, or `-1` if the substring isn't found. It's case-sensitive. 12 | 13 | ```javascript 14 | let str = 'I love Cape Cod potato chips.'; 15 | 16 | // Returns 7 17 | str.indexOf('Cape Cod'); 18 | 19 | // Returns 7 20 | str.indexOf('Cape C'); 21 | 22 | // Returns -1 23 | str.indexOf('cape cod'); 24 | ``` 25 | -------------------------------------------------------------------------------- /content/reference/strings/string-padEnd.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.padEnd()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Add characters to the end of a string if it's less than a certain length." 8 | weight: 20 9 | --- 10 | 11 | Add characters to the end of a string if it's less than a certain length. Accepts two arguments: the length the string should be, and what characters to add if it's not that length. The characters to use is optional, and defaults to a space (` `). 12 | 13 | ```javascript 14 | // Add a leading zero for hours below 10 15 | let minutes0 = '0'; 16 | let minutes12 = '12'; 17 | 18 | // returns "00" 19 | minutes0.padEnd(2, '0'); 20 | 21 | // returns "12" 22 | minutes12.padEnd(2, '0'); 23 | ``` -------------------------------------------------------------------------------- /content/reference/strings/string-padStart.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.padStart()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Add characters to the beginning of a string if it's less than a certain length." 8 | weight: 10 9 | --- 10 | 11 | Add characters to the beginning of a string if it's less than a certain length. Accepts two arguments: the length the string should be, and what characters to add if it's not that length. The characters to use is optional, and defaults to a space (` `). 12 | 13 | ```javascript 14 | // Add a leading zero for hours below 10 15 | let hour3 = '3'; 16 | let hour12 = '12'; 17 | 18 | // returns "03" 19 | hour3.padStart(2, '0'); 20 | 21 | // returns "12" 22 | hour12.padStart(2, '0'); 23 | ``` -------------------------------------------------------------------------------- /content/reference/strings/string-replace.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.replace()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Replace a portion of a string with something else." 8 | weight: 60 9 | --- 10 | 11 | Replace a portion of text in a string with something else. The `String.replace()` method accepts two arguments: the string to find, and the string to replace it with. 12 | 13 | ```javascript 14 | let text = 'I love Cape Cod potato chips!'; 15 | 16 | // returns "I love Lays potato chips!" 17 | text.replace('Cape Cod', 'Lays'); 18 | ``` 19 | 20 | By default, the `String.replace()` method replaces the first match. To replace all matches, you'll need to pass in a regular expression with the global flag (`g`). 21 | 22 | ```javascript 23 | let chips = 'Cape Cod potato chips are my favorite brand of chips.'; 24 | 25 | // Only replaces the first instance of the word "chips" 26 | chips.replace('chips', 'deep fried potato slices'); 27 | 28 | // Replaces all instances of the word "chips" 29 | chips.replace(new RegExp('chips', 'g'), 'deep fried potato slices'); 30 | ``` -------------------------------------------------------------------------------- /content/reference/strings/string-replaceAll.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.replaceAll()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Replace all instances of a string inside another string." 8 | weight: 70 9 | --- 10 | 11 | Replace all instances of a string inside another string, without the need for a regular expression. The `String.replaceAll()` method accepts two arguments: the string to find, and the string to replace it with. 12 | 13 | ```javascript 14 | // Awkwardly worded, but roll with it 15 | let wizards = 'Of all the wizards in Lord of the Rings, Radagast is my favorite of the wizards.'; 16 | 17 | // returns "Of all the sorcerers in Lord of the Rings, Radagast is my favorite of the sorcerers." 18 | let sorcerers = wizards.replaceAll('wizards', 'sorcerers'); 19 | ``` 20 | 21 | _The `String.replaceAll()` method works in all modern browsers, with the exception of the Samsung Internet mobile browser. [You can add support with a polyfill.](https://vanillajstoolkit.com/polyfills/stringreplaceall/)_ -------------------------------------------------------------------------------- /content/reference/strings/string-slice.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.slice()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get a portion of a string starting and ending at specific characters." 8 | weight: 80 9 | --- 10 | 11 | Get a portion of a string starting (and optionally ending) at a particular character. 12 | 13 | The first argument is where to start. Use `0` to include the first character. The second argument is where to end (and is optional). 14 | 15 | If either argument is a negative integer, it will start at the end of the string and work backwards. 16 | 17 | ```javascript 18 | let text = 'Cape Cod potato chips'; 19 | 20 | // returns "Cod potato chips" 21 | text.slice(5); 22 | 23 | // returns "Cod" 24 | text.slice(5, 8); 25 | 26 | // returns "Cape Cod potato" 27 | text.slice(0, -6); 28 | 29 | // returns "chips" 30 | text.slice(-5); 31 | ``` -------------------------------------------------------------------------------- /content/reference/strings/string-split.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.split()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Convert a string to an array." 8 | weight: 90 9 | --- 10 | 11 | Convert a string into an array by splitting it after a specific character (or characters). 12 | 13 | The first argument, the `delimiter`, the character or characters to split by. As an optional second argument, you can stop splitting your string after a certain number of delimiter matches have been found. 14 | 15 | ```javascript 16 | let shoppingList = 'Soda, turkey sandwiches, potato chips, chocolate chip cookies'; 17 | let menu = shoppingList.split(', '); 18 | let limitedMenu = shoppingList.split(', ', 2); 19 | 20 | // logs ["Soda", "turkey sandwiches", "potato chips", "chocolate chip cookies"] 21 | console.log(menu); 22 | 23 | // logs ["Soda", "turkey sandwiches"] 24 | console.log(limitedMenu); 25 | ``` -------------------------------------------------------------------------------- /content/reference/strings/string-toLowerCase.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.toLowerCase()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Transform all text in a string to lowercase." 8 | weight: 50 9 | --- 10 | 11 | Transform all text in a string to lowercase. 12 | 13 | ```javascript 14 | let text = 'This sentence has some MIXED CASE LeTTeRs in it.'; 15 | 16 | // returns "this sentence has some mixed case letters in it." 17 | let lower = text.toLowerCase(); 18 | ``` -------------------------------------------------------------------------------- /content/reference/strings/string-toUpperCase.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.toUpperCase()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Transform all text in a string to uppercase." 8 | weight: 40 9 | --- 10 | 11 | Transform all text in a string to uppercase. 12 | 13 | ```javascript 14 | let text = 'This sentence has some MIXED CASE LeTTeRs in it.'; 15 | 16 | // returns "THIS SENTENCE HAS SOME MIXED CASE LETTERS IN IT." 17 | let upper = text.toUpperCase(); 18 | ``` -------------------------------------------------------------------------------- /content/reference/strings/string-trim.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "String.trim()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Remove leading and trailing whitespace from a string." 8 | weight: 30 9 | --- 10 | 11 | Remove leading and trailing whitespace from a string. 12 | 13 | ```javascript 14 | let str = ' I love Cape Cod potato chips. '; 15 | 16 | // Returns "I love Cape Cod potato chips." 17 | str.trim(); 18 | ``` -------------------------------------------------------------------------------- /content/reference/strings/template-literals.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Template Literals" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "More easily create multi-line or complex strings." 8 | weight: 120 9 | --- 10 | 11 | Introduced in ES6, *template literals* provide a simpler way to create strings that span multiple lines or contain data. 12 | 13 | Instead of quotes, template literals start and end with backticks (`` ` ``). You do *not* need to concatenate new lines in template literals. 14 | 15 | ```javascript 16 | let str1 = 17 | `

    Hello, world!

    18 |

    How are you today?

    `; 19 | 20 | // logs "

    Hello, world!

    How are you today?

    " 21 | console.log(str1); 22 | ``` 23 | 24 | You can use variables in template literals (sometimes called *expressions*) by wrapping the name of the variable in curly brackets with a leading dollar sign (`${VARIABLE_NAME}`). 25 | 26 | ```javascript 27 | let greeting = 'Hi, universe!'; 28 | let message = 'How is the weather today?'; 29 | 30 | let str2 = 31 | `

    ${greeting}

    32 |

    ${message}

    `; 33 | 34 | // logs "

    Hi, universe!

    How is the weather today?

    " 35 | console.log(str2); 36 | ``` -------------------------------------------------------------------------------- /content/reference/style/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Styles" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 40 8 | --- 9 | 10 | ## Inline Styles 11 | 12 | Get and set inline styles for an element. 13 | 14 | ```javascript 15 | var elem = document.querySelector('#sandwich'); 16 | 17 | // Get a style 18 | // If this style is not set as an inline style directly on the element, it returns an empty string 19 | // ex.
    20 | var bgColor = elem.style.backgroundColor; // this will return "green" 21 | var fontWeight = elem.style.fontWeight; // this will return "" 22 | 23 | // Set a style 24 | elem.style.backgroundColor = 'purple'; 25 | ``` 26 | 27 | *Works back to at least IE6.* 28 | 29 | 30 | 31 | ## Computed Styles 32 | 33 | Get the actual computed style of an element. This factors in browser default stylesheets as well as external styles you've specified. 34 | 35 | ```javascript 36 | var elem = document.querySelector('#some-elem'); 37 | var bgColor = window.getComputedStyle(elem).backgroundColor; 38 | ``` -------------------------------------------------------------------------------- /content/reference/style/element-style.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.style" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get and set inline styles for an element." 8 | weight: 10 9 | --- 10 | 11 | Get and set inline styles for an element. 12 | 13 | ```html 14 |

    15 | Sandwich 16 |

    17 | ``` 18 | 19 | ```javascript 20 | let sandwich = document.querySelector('#sandwich'); 21 | 22 | // Get a style 23 | // If this style is not set as an inline style directly on the element, it returns an empty string 24 | let bgColor = sandwich.style.backgroundColor; // this will return "green" 25 | let fontWeight = sandwich.style.fontWeight; // this will return "" 26 | 27 | // Set the background-color style property 28 | sandwich.style.backgroundColor = 'purple'; 29 | ``` 30 | 31 | You can also get and set a string representation of the entire inline `style` property on the element itself with the `Element.style.cssText` property. 32 | 33 | ```javascript 34 | // Get the styles on an element 35 | // returns "background-color: green; color: white;" 36 | let styles = sandwich.style.cssText; 37 | 38 | // Completely replace the inline styles on an element 39 | sandwich.style.cssText = 'font-size: 2em; font-weight: bold;'; 40 | 41 | // Add additional styles 42 | sandwich.style.cssText += 'color: purple;'; 43 | ``` -------------------------------------------------------------------------------- /content/reference/style/window-getComputedStyle.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Window.getComputedStyle()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the computed style of an element." 8 | weight: 20 9 | --- 10 | 11 | Get the actual computed style of an element. This factors in browser default stylesheets as well as external styles you've specified. 12 | 13 | ```javascript 14 | let sandwich = document.querySelector('#sandwich'); 15 | let bgColor = window.getComputedStyle(sandwich).backgroundColor; 16 | ``` -------------------------------------------------------------------------------- /content/reference/traversal/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Traversing the DOM" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 110 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/traversal/element-childNodes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.childNodes" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the immediate descendants of an element, including text fragments and other non-element nodes." 8 | weight: 40 9 | --- 10 | 11 | Get the immediate descendants of an element, including text fragments and other non-element nodes. 12 | 13 | ```html 14 |
      15 | 16 |
    • Gandalf
    • 17 |
    • Radagast
    • 18 |
    • Hermione
    • 19 | 20 |
    • Neville
    • 21 |
    22 | ``` 23 | 24 | ```javascript 25 | let wizards = document.querySelector('ul'); 26 | 27 | // returns all nodes, including the comments 28 | let descendants = wizards.childNodes; 29 | ``` -------------------------------------------------------------------------------- /content/reference/traversal/element-children.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.children" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the immediate descendant elements of an element." 8 | weight: 30 9 | --- 10 | 11 | Returns a live HTMLCollection, which means if items are added to it later, the collection updates as well. 12 | 13 | ```html 14 |
    15 |
      16 |
    • Gandalf
    • 17 |
    • Radagast
    • 18 |
    • Hermione
    • 19 |
    • Neville
    • 20 |
    21 |
    22 | ``` 23 | 24 | ```javascript 25 | let wizards = document.querySelector('.wizards'); 26 | let wizardsList = document.querySelector('.wizards ul'); 27 | 28 | // returns an HTMLCollection with the ul element 29 | let wizardDescendants = wizards.children; 30 | 31 | // returns an HTMLCollection with the list items 32 | let wizardListDescendants = wizardsList.children; 33 | 34 | // Add a new item 35 | let li = document.createElement('li'); 36 | li.textContent = 'Merlin'; 37 | wizardsList.append(li); 38 | 39 | // wizardListDescendants now automatically contains the new li 40 | ``` -------------------------------------------------------------------------------- /content/reference/traversal/element-closest.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.closest()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the closest parent element that matches a selector." 8 | weight: 20 9 | --- 10 | 11 | Get the closest parent up the DOM tree that matches against a selector. 12 | 13 | The `Element.closest()` method starts with the element itself. You can start with the first parent element by pairing it with the `Node.parentNode` property. 14 | 15 | ```html 16 |
    17 |
    18 |
    19 |

    Hello, world!

    20 |
    21 |
    22 |
    23 | ``` 24 | 25 | ```javascript 26 | let h1 = document.querySelector('h1'); 27 | 28 | // returns the .hero element 29 | let hero = h1.closest('.hero'); 30 | 31 | // returns the h1 element itself 32 | let sandwich = h1.closest('[data-sandwich]'); 33 | 34 | // Start with the element's parent 35 | // returns null 36 | let sandwich2 = h1.parentNode.closest('[data-sandwich]'); 37 | ``` -------------------------------------------------------------------------------- /content/reference/traversal/element-parentNode.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.parentNode" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the parent of an element." 8 | weight: 10 9 | --- 10 | 11 | Get the parent of an element. 12 | 13 | ```html 14 |
    15 |

    Hello, world!

    16 |
    17 | ``` 18 | 19 | ```javascript 20 | let h1 = document.querySelector('h1'); 21 | 22 | // returns the #app element 23 | let parent = h1.parentNode; 24 | ``` -------------------------------------------------------------------------------- /content/reference/traversal/firstChild-lastChild.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.firstChild & Node.lastChild" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the first and last child nodes of a parent element." 8 | weight: 50 9 | --- 10 | 11 | Get the first and last child nodes of a parent element, including nodes that aren't elements (such as comments and text fragments). 12 | 13 | ```html 14 |
      15 | 16 |
    • Gandalf
    • 17 |
    • Radagast
    • 18 |
    • Hermione
    • 19 | 20 |
    • Neville
    • 21 |
    22 | ``` 23 | 24 | ```javascript 25 | let wizards = document.querySelector('ul'); 26 | 27 | // returns the comment node 28 | let firstDescendant = wizards.firstChild; 29 | 30 | // returns
  • Neville
  • 31 | let lastDescendant = wizards.lastChild; 32 | ``` -------------------------------------------------------------------------------- /content/reference/traversal/firstElementChild-lastElementChild.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.firstElementChild & Node.lastElementChild" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the first and last child element of a parent element." 8 | weight: 60 9 | --- 10 | 11 | Get the first and last child element of a parent element. 12 | 13 | ```html 14 |
      15 | 16 |
    • Gandalf
    • 17 |
    • Radagast
    • 18 |
    • Hermione
    • 19 | 20 |
    • Neville
    • 21 |
    22 | ``` 23 | 24 | ```javascript 25 | let wizards = document.querySelector('ul'); 26 | 27 | // returns
  • Gandalf
  • 28 | let firstDescendant = wizards.firstElementChild; 29 | 30 | // returns
  • Neville
  • 31 | let lastDescendant = wizards.lastElementChild; 32 | ``` -------------------------------------------------------------------------------- /content/reference/traversal/nextElementSibling-previousElementSibling.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.nextElementSibling & Node.previousElementSibling" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the next and previous sibling element of an element." 8 | weight: 80 9 | --- 10 | 11 | Get the next and previous sibling element of an element. 12 | 13 | ```html 14 |
      15 | 16 |
    • Gandalf
    • 17 |
    • Radagast
    • 18 |
    • Hermione
    • 19 | 20 |
    • Neville
    • 21 |
    22 | ``` 23 | 24 | ```javascript 25 | let hermione = document.querySelector('#hermione'); 26 | 27 | // returns
  • Neville
  • 28 | let next = hermione.nextElementSibling; 29 | 30 | // returns
  • Radagast
  • 31 | let previous = hermione.previousElementSibling; 32 | ``` -------------------------------------------------------------------------------- /content/reference/traversal/nextSibling-previousSibling.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Node.nextSibling & Node.previousSibling" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the next and previous sibling node of an element." 8 | weight: 70 9 | --- 10 | 11 | Get the next and previous sibling node of an element, including nodes that aren't elements (such as comments and text fragments). 12 | 13 | ```html 14 |
      15 | 16 |
    • Gandalf
    • 17 |
    • Radagast
    • 18 |
    • Hermione
    • 19 | 20 |
    • Neville
    • 21 |
    22 | ``` 23 | 24 | ```javascript 25 | let hermione = document.querySelector('#hermione'); 26 | 27 | // returns 28 | let next = hermione.nextSibling; 29 | 30 | // returns
  • Radagast
  • 31 | let previous = hermione.previousSibling; 32 | ``` -------------------------------------------------------------------------------- /content/reference/variables-functions/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Variables & Functions" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 90 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/variables-functions/arrow-functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Arrow Functions" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "An alternate way to define functions." 8 | weight: 40 9 | --- 10 | 11 | A basic arrow function isn't all that different from a traditional function. The word `function` gets dropped, and a fat arrow (`=>`) is added between the parentheses and brackets (`()` and `{}`, respectively). 12 | 13 | ```javascript 14 | // A traditional function 15 | function add (num1, num2) { 16 | return num1 + num2; 17 | } 18 | 19 | // The arrow function version 20 | let add = (num1, num2) => { 21 | return num1 + num2; 22 | }; 23 | ``` 24 | 25 | *__Note:__ Named arrow functions have to be written as a function expression. There's no way to write one as a function declaration.* 26 | 27 | If your function is only returning a value, as is the case with our `add()` function, you can simplify the function even further by dropping the curly brackets (`{}`) and `return` operator. 28 | 29 | ```javascript 30 | // returns the value of `num1 + num2` 31 | let add = (num1, num2) => num1 + num2; 32 | ``` 33 | 34 | This only works if the only thing you're doing is returning a value. If you need to do more stuff with your function, you have to include curly brackets. -------------------------------------------------------------------------------- /content/reference/variables-functions/default-parameters.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Default Parameters" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Define default values for function parameters." 8 | weight: 20 9 | --- 10 | 11 | Set a default value for each parameter by adding `= default value` when defining it. 12 | 13 | ```javascript 14 | function add (num1 = 0, num2 = 0) { 15 | 16 | // Add the numbers 17 | // If num1 or num2 is not provided, 0 will be used 18 | return num1 + num2; 19 | 20 | } 21 | 22 | // returns 4 23 | add(4); 24 | ``` -------------------------------------------------------------------------------- /content/reference/variables-functions/rest-parameters.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Rest Parameters" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Create an array with multiple function arguments." 8 | weight: 30 9 | --- 10 | 11 | Define *rest parameters* by creating a parameter prefixed with `...`. Any arguments provided at or beyond the rest parameter on a function get combined into an array that's assigned to the rest parameter's name. 12 | 13 | In the example below, `...moreArgs` is a _rest parameter_. 14 | 15 | ```javascript 16 | function logStuff (arg1, arg2, ...moreArgs) { 17 | 18 | // Logs arg1 19 | console.log(arg1); 20 | 21 | // Logs arg2 22 | console.log(arg2); 23 | 24 | // Logs an array of any other arguments you pass in after arg2 25 | console.log(moreArgs); 26 | 27 | } 28 | 29 | // In this example... 30 | // arg1 = 'chicken' 31 | // arg2 = 'tuna' 32 | // moreArgs = ['chips', 'cookie', 'soda', 'delicious'] 33 | logStuff('chicken', 'tuna', 'chips', 'cookie', 'soda', 'delicious'); 34 | ``` -------------------------------------------------------------------------------- /content/reference/variables-functions/ternary-operator.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Ternary Operator" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "A shorter way to write `if...else` statements." 8 | weight: 10 9 | --- 10 | 11 | A shorter way to write `if...else` statements. It has three parts: 12 | 13 | ```javascript 14 | let someVar = [the condition] ? [the value if true] : [the value if false]; 15 | ``` 16 | 17 | It's the equivalent of this. 18 | 19 | ```javascript 20 | let someVar; 21 | 22 | if ([the condition]) { 23 | someVar = [the value if true]; 24 | } else { 25 | someVar = [the value if false]; 26 | } 27 | ``` 28 | 29 | Let's say we wanted to define `answer` as `num` if `num` is greater than `10`. If not, we'll use `42`. 30 | 31 | ```javascript 32 | let num = 0; 33 | let answer = num > 10 ? num : 42; 34 | ``` -------------------------------------------------------------------------------- /content/reference/viewport/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "The Viewport" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | weight: 120 8 | --- 9 | 10 | -------------------------------------------------------------------------------- /content/reference/viewport/getBoundingClientRect.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Element.getBoundingClientRect()" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get information about the size of an element and its position relative to the viewport." 8 | weight: 30 9 | --- 10 | 11 | Get information about the size of an element and its position relative to the viewport. 12 | 13 | ```javascript 14 | let app = document.querySelector('#app'); 15 | let details = app.getBoundingClientRect(); 16 | 17 | // logs an object with top, let, bottom, right, height, and width properties 18 | console.log(details); 19 | ``` -------------------------------------------------------------------------------- /content/reference/viewport/innerHeight.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "window.innerHeight" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the height of the viewport." 8 | weight: 10 9 | --- 10 | 11 | Get the viewport height. 12 | 13 | ```javascript 14 | let viewportHeight = window.innerHeight; 15 | ``` -------------------------------------------------------------------------------- /content/reference/viewport/innerWidth.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "window.innerWidth" 3 | date: 2018-01-14T21:38:44-05:00 4 | draft: false 5 | noTitle: false 6 | fullWidth: false 7 | description: "Get the width of the viewport." 8 | weight: 20 9 | --- 10 | 11 | Get the viewport width. 12 | 13 | ```javascript 14 | let viewportWidth = window.innerWidth; 15 | ``` -------------------------------------------------------------------------------- /content/resources.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Learning Resources" 3 | date: 2018-01-24T11:48:20-05:00 4 | draft: false 5 | noTitle: false 6 | noIndex: false 7 | anchors: true 8 | --- 9 | 10 | Let's make {{}} the year that you master JavaScript! You can do this. I can help. 11 | 12 | {{}} 13 | 14 | {{}} -------------------------------------------------------------------------------- /content/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Search" 3 | date: 2018-01-11T16:03:33-05:00 4 | draft: false 5 | type: "search" 6 | noSearch: true 7 | --- 8 | 9 | {{}} -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | git add . && git commit -a -m "Updated resource" && git push origin master -------------------------------------------------------------------------------- /i18n/en.toml: -------------------------------------------------------------------------------- 1 | [wordCount] 2 | other = "{{ .WordCount }} words" -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 1 3 | } 4 | -------------------------------------------------------------------------------- /static/automate/deploy.php: -------------------------------------------------------------------------------- 1 | commits)){ 56 | // When merging and pushing to GitHub, the commits array will be empty. 57 | // In this case there is no way to know what branch was pushed to, so we will do an update. 58 | $commit_message .= 'true'; 59 | } else { 60 | foreach ($data->commits as $commit) { 61 | $commit_message .= $commit->message; 62 | } 63 | } 64 | 65 | if (!empty($commit_message)) { 66 | 67 | // Do a git checkout, run Hugo, and copy files to public directory 68 | exec('cd ' . $repo_dir . ' && git fetch --all && git reset --hard origin/master'); 69 | exec('cd ' . $repo_dir . ' && ' . $hugo_path); 70 | exec('cd ' . $repo_dir . ' && cp -r ' . $repo_dir . $rendered_dir . '/. ' . $web_root_dir); 71 | 72 | // Log the deployment 73 | file_put_contents('deploy.log', date('m/d/Y h:i:s a') . " Deployed branch: " . $branch . " Commit: " . $commit_message . "\n", FILE_APPEND); 74 | 75 | } -------------------------------------------------------------------------------- /static/img/chris-ferdinandi-high-res.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cferdinandi/vanilla-js-toolkit/eb8619bd3568ac00d863f32d616e67863e174392/static/img/chris-ferdinandi-high-res.jpg -------------------------------------------------------------------------------- /static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /img/* 3 | Disallow: /automate/* 4 | Disallow: /css/* 5 | Disallow: /js/* 6 | Disallow: /svg/* -------------------------------------------------------------------------------- /themes/gmt/LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) Go Make Things, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /themes/gmt/archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: '' 3 | date: '' 4 | --- 5 | -------------------------------------------------------------------------------- /themes/gmt/layouts/404.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 |

    Oops!

    4 | 5 |

    6 | 7 |

    I can't seem to find the page you're looking for. Sorry! Send me an email me at {{ partial "email.html" }} and I'll help you find it.

    8 | 9 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/_default/list.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 | {{ partial "content-page.html" . }} 4 | 5 | {{ $paginate := .Paginate .Pages }} 6 | {{ range $paginate.Pages }} 7 | 8 | {{ if ne ( $.Scratch.Get "pubDate" ) ( .PublishDate.Format "200601" ) }} 9 |

    {{ .PublishDate.Format "January 2006" }}

    10 | {{ end }} 11 | {{ $.Scratch.Set "pubDate" ( .PublishDate.Format "200601" ) }} 12 | 13 |
    14 | 15 |
    16 | 17 |
    18 | 21 |
    22 | 23 |
    24 |

    25 | {{ .Title }} 26 |

    27 |
    28 | 29 |
    30 | 31 | 32 |
    33 | 34 | {{ end }} 35 | 36 | {{ if gt $paginate.TotalPages 1 }} 37 | 44 | {{ end }} 45 | 46 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/_default/single.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 |
    4 | 5 |
    6 | 7 | 10 | 11 |

    12 | {{ .Title }} 13 |

    14 | 15 |
    16 | 17 | {{ .Content }} 18 | 19 |
    20 | 21 | {{ partial "cta-individual-post.html" }} 22 | 23 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/_default/terms.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 |

    {{ .Title }}

    4 | 5 |
      6 | {{ range $key, $value := .Data.Terms }} 7 |
    • 8 | 9 | {{ $key }} 10 | 11 | ({{ len $value }}) 12 |
    • 13 | {{ end }} 14 |
    15 | 16 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/boilerplates/list.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 |
    4 | 5 | {{ partial "content-page-no-article.html" . }} 6 | 7 |
      8 | {{ range .Pages }} 9 |
    • 10 | {{ .Title }}. {{ .Description | markdownify }} {{ if isset .Params "example" }}Example: {{ .Params.example | markdownify }}{{ end }} 11 |
    • 12 | {{ end }} 13 |
    14 | 15 | 19 | 20 |
    21 | 22 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/boilerplates/single.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 |
    4 | 5 | {{ if not .Params.noTitle }} 6 |

    {{ ( .Title | htmlUnescape ) }}

    7 | {{ end }} 8 | 9 |

    {{ .Description | markdownify }}

    10 | 11 | {{- if isset .Params "example" -}}

    Example: {{ .Params.example | markdownify }}

    {{- end -}} 12 | 13 | {{ .Content }} 14 | 15 | 19 | 20 |
    21 | 22 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/helpers/list.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 | {{ partial "content-page.html" . }} 4 | 5 |
      6 | {{ range .Pages }} 7 |
    • 8 | {{ .Title }}. {{ markdownify .Description }} 9 |
    • 10 | {{ end }} 11 |
    12 | 13 | 17 | 18 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/helpers/single.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 |
    4 | 5 |

    {{ ( .Title | htmlUnescape ) }}

    6 | 7 |

    {{ markdownify .Params.description }}

    8 | 9 | {{ if isset .Params "support" }}

    {{ markdownify .Params.support }}

    {{ end }} 10 | 11 | {{ if or (isset .Params "demo") (isset .Params "how") }} 12 |
      13 | {{ if and (isset .Params "demo") (ne .Params.demo "") }}
    • Demo on CodePen
    • {{ end }} 14 | {{ if and (isset .Params "how") (ne .Params.how "") }}
    • How It Works
    • {{ end }} 15 |
    16 | {{ end }} 17 | 18 | {{ .Content }} 19 | 20 | 24 | 25 |
    26 | 27 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/index.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 | {{ partial "content-page.html" . }} 4 | 5 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/page/single.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 | {{ partial "content-page.html" . }} 4 | 5 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/_nav-items_BACKUP.html: -------------------------------------------------------------------------------- 1 | Code SnippetsHelper FunctionsBoilerplatesPolyfillsPluginsLearning Resources -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/content-page-no-article.html: -------------------------------------------------------------------------------- 1 | {{ if not .Params.noTitle }} 2 |

    {{ ( .Title | htmlUnescape ) }}

    3 | {{ end }} 4 | 5 | {{ .Content }} -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/content-page.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | {{ if not .Params.noTitle }} 4 |

    {{ ( .Title | htmlUnescape ) }}

    5 | {{ end }} 6 | 7 | {{ .Content }} 8 | 9 |
    -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/email.html: -------------------------------------------------------------------------------- 1 | chris@gomakethings.com -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/footer.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 |
    6 | {{ partial "nav-secondary.html" }} 7 |

    Made with ❤️ in Massachusetts by Chris Ferdinandi. Unless otherwise noted, all code is free to use under the MIT License.

    8 |
    9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ if not .IsHome }}{{ .Title }} | {{ end }}{{ .Site.Title }} 7 | 8 | {{ if .Params.noIndex }}{{ end }} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {{ if .Params.image }}{{ end }} 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 34 | 35 | {{ partial "nav-a11y.html" }} 36 | 37 | {{ partial "nav-main.html" . }} 38 | 39 |
    40 | 41 |
    -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/mailchimp-form.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 4 | 5 |
    6 |
    7 |
    8 | 9 | 10 |
    11 | 12 | 13 |
    14 | 15 |
    16 |
    17 |
    18 |
    -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/mailchimp-intro.html: -------------------------------------------------------------------------------- 1 | {{- $data := getJSON $.Site.Params.api -}} 2 | {{- $ctas := index $data "ctas" -}} 3 | 4 |

    Get Daily Developer Tips

    5 | 6 | {{ if isset $ctas "ck-blurb" }}

    {{ index $ctas "ck-blurb" | markdownify }}

    {{ end }} -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/nav-a11y.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | Skip to main content 5 | 6 | 7 | Accessibility Feedback 8 | 9 |
    -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/nav-items.html: -------------------------------------------------------------------------------- 1 | Methods & APIsUtilitiesLibrariesBoilerplatesLearning Search -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/nav-main.html: -------------------------------------------------------------------------------- 1 |
    2 | 13 |
    -------------------------------------------------------------------------------- /themes/gmt/layouts/partials/nav-secondary.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/gmt/layouts/reference/list.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 | {{ partial "content-page.html" . }} 4 | 5 | {{ if ne (len .Sections) 0 }} 6 | 7 | {{ range .Sections }} 8 |

    {{ .Title }}

    9 | 10 |
      11 | {{ range .Pages }} 12 |
    • {{ .Title | htmlUnescape }}{{ if ne .Description "" }} - {{ .Description | markdownify }}{{ end }}
    • 13 | {{ end }} 14 |
    15 | {{ end }} 16 | 17 | {{ else }} 18 | 19 |
      20 | {{ range .Pages }} 21 |
    • {{ .Title | htmlUnescape }}{{ if ne .Description "" }} - {{ .Description | markdownify }}{{ end }}
    • 22 | {{ end }} 23 |
    24 | 25 | {{ end }} 26 | 27 | 31 | 32 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/reference/single.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 |
    4 | 5 |

    {{ .Page.Parent.Title }}

    6 |

    {{ ( .Title | htmlUnescape ) }}

    7 | 8 | {{ .Content }} 9 | 10 | 14 | 15 |
    16 | 17 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/rss-feed/single.html: -------------------------------------------------------------------------------- 1 | {{ `` | safeHTML }} 2 | 10 | 11 | {{ .Site.Title }} 12 | 13 | {{ .Site.BaseURL }} 14 | {{ $.Site.Params.description }} 15 | {{ if not .Date.IsZero }}{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0500" | safeHTML }}{{ end }} 16 | {{ with .Site.LanguageCode }}{{.}}{{end}} 17 | hourly 18 | 1 19 | Hugo -- gohugo.io 20 | {{ $all := where .Site.RegularPages "Type" "articles" }} 21 | {{ range first ($.Site.Params.rssLimit) $all }} 22 | 23 | {{ .Title }} 24 | {{ .Permalink }} 25 | {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }} 26 | {{ with .Site.Author.name }}{{.}}{{end}} 27 | {{ .Permalink }} 28 | {{ ` 29 | {{ ` 30 | 31 | {{ end }} 32 | 33 | -------------------------------------------------------------------------------- /themes/gmt/layouts/search/single.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 | 3 | {{ partial "content-page.html" . }} 4 | 5 | {{- $.Scratch.Add "index" slice -}} 6 | {{- range .Site.Pages -}} 7 | {{- if ne .Params.noSearch true -}} 8 | {{- $.Scratch.Set "content" (.Content | plainify) -}} 9 | {{- if or (eq .Type "boilerplates") (eq .Type "helpers") -}} 10 | {{- if isset .Params "description" -}} 11 | {{- $.Scratch.Set "content" .Params.description -}} 12 | {{- else -}} 13 | {{- $.Scratch.Set "content" "" -}} 14 | {{- end -}} 15 | {{- end -}} 16 | {{- $.Scratch.Add "index" (dict "title" .Title "url" .Permalink "content" ($.Scratch.Get "content") "type" .Type ) -}} 17 | {{- end -}} 18 | {{- end -}} 19 | 22 | 23 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /themes/gmt/layouts/shortcodes/cta.html: -------------------------------------------------------------------------------- 1 | {{- $data := getJSON $.Site.Params.api -}} 2 | {{- $ctas := index $data "ctas" -}} 3 | {{- if isset $ctas (.Get "for") -}} 4 | {{ index $ctas (.Get "for") | safeHTML }} 5 | {{- end -}} -------------------------------------------------------------------------------- /themes/gmt/layouts/shortcodes/email.html: -------------------------------------------------------------------------------- 1 | {{ if .Get "icon" }}Email: {{ end }}chris@gomakethings.com -------------------------------------------------------------------------------- /themes/gmt/layouts/shortcodes/learn-how.html: -------------------------------------------------------------------------------- 1 | Learn how it works. -------------------------------------------------------------------------------- /themes/gmt/layouts/shortcodes/learn-more.html: -------------------------------------------------------------------------------- 1 | Learn more in the {{ .Get "title" }} pocket guide and mini course. -------------------------------------------------------------------------------- /themes/gmt/layouts/shortcodes/mailchimp.html: -------------------------------------------------------------------------------- 1 | {{ if .Get "intro" }}{{ partial "mailchimp-intro.html" . }}{{ end }} 2 | {{ partial "mailchimp-form.html" }} -------------------------------------------------------------------------------- /themes/gmt/layouts/shortcodes/md.html: -------------------------------------------------------------------------------- 1 | {{ .Inner }} -------------------------------------------------------------------------------- /themes/gmt/layouts/shortcodes/search-form.html: -------------------------------------------------------------------------------- 1 | 9 | 10 |
    11 |
      -------------------------------------------------------------------------------- /themes/gmt/layouts/shortcodes/testimonial.html: -------------------------------------------------------------------------------- 1 | {{- $data := getJSON $.Site.Params.api -}} 2 | {{- $testimonials := index $data "testimonials" -}} 3 | {{- if isset $testimonials (.Get "for") -}} 4 | {{- $testimonial := index $testimonials (.Get "for") -}} 5 | {{- if ne (.Get "photo") "true" -}} 6 |
      7 | {{ index $testimonial "quote" | safeHTML }} 8 | {{- if isset $testimonial "url" -}} 9 | - {{ index $testimonial "name" }} 10 | {{- else -}} 11 | - {{ index $testimonial "name" }} 12 | {{- end -}} 13 |
      14 | {{- else -}} 15 |
      16 |
      17 | 18 |
      19 |
      20 |
      21 | {{ index $testimonial "quote" | safeHTML }} 22 | {{- if isset $testimonial "url" -}} 23 | - {{ index $testimonial "name" }} 24 | {{- else -}} 25 | - {{ index $testimonial "name" }} 26 | {{- end -}} 27 |
      28 |
      29 |
      30 | {{- end -}} 31 | {{- end -}} -------------------------------------------------------------------------------- /themes/gmt/layouts/shortcodes/toc.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/gmt/layouts/shortcodes/year.html: -------------------------------------------------------------------------------- 1 | {{- $.Scratch.Set "year" ( dateFormat "2006" now ) -}} 2 | {{- if ge ( int ( strings.TrimLeft "0" (dateFormat "0102" now) ) ) 1115 -}} 3 | {{- $.Scratch.Set "year" ( add (int (dateFormat "2006" now)) 1 ) -}} 4 | {{- end -}} 5 | 6 | {{- if eq (.Get "noround") "true" -}} 7 | {{ dateFormat "2006" now }} 8 | {{- else -}} 9 | {{ $.Scratch.Get "year" }} 10 | {{- end -}} -------------------------------------------------------------------------------- /themes/gmt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vanillajs", 3 | "version": "1.5.0", 4 | "description": "The theme for vanillajstoolkit.com", 5 | "author": { 6 | "name": "Chris Ferdinandi", 7 | "url": "http://gomakethings.com" 8 | }, 9 | "license": "MIT", 10 | "openSource": { 11 | "credits": "https://github.com/toddmotto/fluidvids, http://prismjs.com, https://github.com/filamentgroup/loadJS/, https://github.com/filamentgroup/loadCSS, https://github.com/bramstein/fontfaceobserver" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "http://github.com/cferdinandi/vanilla-js-toolkit" 16 | }, 17 | "scripts": { 18 | "clean": "rm -rf static/img && rm -rf static/js && rm -rf static/svg", 19 | "js": "rollup --config", 20 | "svg": "svgo -f src/svg static/svg --disable=removeViewBox,removeTitle", 21 | "copy": "cp -r src/img static/img", 22 | "build": "npm run clean && npm run js && npm run svg && npm run copy" 23 | }, 24 | "devDependencies": { 25 | "rollup": "^2.6.1", 26 | "rollup-plugin-terser": "^5.3.0", 27 | "svgo": "^2.8.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /themes/gmt/rollup.config.js: -------------------------------------------------------------------------------- 1 | // Plugins 2 | import { terser } from 'rollup-plugin-terser'; 3 | import pkg from './package.json'; 4 | 5 | 6 | // Configs 7 | var configs = { 8 | files: ['main.js', 'search.js', 'swInit.js'], 9 | formats: ['iife'], 10 | default: 'iife', 11 | pathIn: 'src/js', 12 | pathOut: 'static/js', 13 | minify: true 14 | }; 15 | 16 | // Banner 17 | var banner = `/*! ${configs.name ? configs.name : pkg.name} v${pkg.version} | (c) ${new Date().getFullYear()} ${pkg.author.name} | ${pkg.license} License | ${pkg.repository.url} */`; 18 | 19 | var createOutput = function (filename, minify) { 20 | return configs.formats.map(function (format) { 21 | var output = { 22 | file: `${configs.pathOut}/${filename}${format === configs.default ? '' : `.${format}`}${minify ? '.min' : ''}.js`, 23 | format: format, 24 | banner: banner 25 | }; 26 | if (format === 'iife') { 27 | output.name = filename; 28 | } 29 | if (minify) { 30 | output.plugins = [terser()]; 31 | } 32 | return output; 33 | }); 34 | }; 35 | 36 | /** 37 | * Create output formats 38 | * @param {String} filename The filename 39 | * @return {Array} The outputs array 40 | */ 41 | var createOutputs = function (filename) { 42 | 43 | // Create base outputs 44 | var outputs = createOutput(filename); 45 | 46 | // If not minifying, return outputs 47 | if (!configs.minify) return outputs; 48 | 49 | // Otherwise, ceate second set of outputs 50 | var outputsMin = createOutput(filename, true); 51 | 52 | // Merge and return the two arrays 53 | return outputs.concat(outputsMin); 54 | 55 | }; 56 | 57 | /** 58 | * Create export object 59 | * @return {Array} The export object 60 | */ 61 | var createExport = function (file) { 62 | return configs.files.map(function (file) { 63 | var filename = file.replace('.js', ''); 64 | return { 65 | input: `${configs.pathIn}/${file}`, 66 | output: createOutputs(filename) 67 | }; 68 | }); 69 | }; 70 | 71 | export default createExport(); -------------------------------------------------------------------------------- /themes/gmt/src/img/favicon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cferdinandi/vanilla-js-toolkit/eb8619bd3568ac00d863f32d616e67863e174392/themes/gmt/src/img/favicon-144.png -------------------------------------------------------------------------------- /themes/gmt/src/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cferdinandi/vanilla-js-toolkit/eb8619bd3568ac00d863f32d616e67863e174392/themes/gmt/src/img/favicon.ico -------------------------------------------------------------------------------- /themes/gmt/src/js/main.js: -------------------------------------------------------------------------------- 1 | import addHeadingLinks from '../../../../../gmt-theme/dist/js/heading-links.js'; 2 | import convertkit from '../../../../../gmt-theme/dist/js/convertkit.js'; 3 | import tableOfContents from '../../../../../gmt-theme/dist/js/tableOfContents.js'; 4 | import {products, getAffiliate, setAffiliate} from '../../../../../gmt-theme/dist/js/affiliates.js'; 5 | 6 | // ConvertKit form 7 | convertkit(); 8 | 9 | // Add table of contents 10 | if (document.querySelector('#table-of-contents')) { 11 | tableOfContents('#table-of-contents', 'h2', '

      On this page

      ', null, 'ul'); 12 | } 13 | 14 | // Anchor links on posts 15 | if (document.body.matches('.js-anchors')) { 16 | addHeadingLinks('h2, h3, h4, h5, h6', '#', 'link-no-underline'); 17 | } 18 | 19 | // Affiliate marketing 20 | getAffiliate(); 21 | setAffiliate(products); -------------------------------------------------------------------------------- /themes/gmt/src/js/search.js: -------------------------------------------------------------------------------- 1 | import crowsNest from '../../../../../gmt-theme/dist/js/search.js'; 2 | 3 | crowsNest(function (article, id) { 4 | if (!article.title || article.url.includes('/offline/')) return ''; 5 | return ` 6 |
    • 7 |
      ${article.type.replace('page', 'reference')}
      8 | 9 |
    • `; 10 | }); -------------------------------------------------------------------------------- /themes/gmt/src/js/swInit.js: -------------------------------------------------------------------------------- 1 | import '../../../../../gmt-theme/dist/js/swInit.js'; -------------------------------------------------------------------------------- /themes/gmt/src/static/README.md: -------------------------------------------------------------------------------- 1 | # static 2 | Add your static files and folders to this directory. They'll be copied as-is into the dist directory. 3 | -------------------------------------------------------------------------------- /themes/gmt/src/svg/icecream.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | icecream 4 | 5 | 6 | -------------------------------------------------------------------------------- /themes/gmt/static/css/fonts.css: -------------------------------------------------------------------------------- 1 | /*! gmt-theme v2.8.1 | (c) 2023 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/gmt-theme */ 2 | /* pt-serif-regular - latin */ 3 | @font-face { 4 | font-display: swap; 5 | font-family: "PT Serif"; 6 | font-style: normal; 7 | font-weight: 400; 8 | src: url("https://gomakethings.com/fonts/pt-serif-v11-latin-regular.woff2") format("woff2"), url("https://gomakethings.com/fonts/pt-serif-v11-latin-regular.woff") format("woff"); 9 | } 10 | /* pt-serif-italic - latin */ 11 | @font-face { 12 | font-display: swap; 13 | font-family: "PT Serif"; 14 | font-style: italic; 15 | font-weight: 400; 16 | src: url("https://gomakethings.com/fonts/pt-serif-v11-latin-italic.woff2") format("woff2"), url("https://gomakethings.com/fonts/pt-serif-v11-latin-italic.woff") format("woff"); 17 | } 18 | /* pt-serif-700 - latin */ 19 | @font-face { 20 | font-display: swap; 21 | font-family: "PT Serif"; 22 | font-style: normal; 23 | font-weight: 700; 24 | src: url("https://gomakethings.com/fonts/pt-serif-v11-latin-700.woff2") format("woff2"), url("https://gomakethings.com/fonts/pt-serif-v11-latin-700.woff") format("woff"); 25 | } 26 | /* pt-serif-700italic - latin */ 27 | @font-face { 28 | font-display: swap; 29 | font-family: "PT Serif"; 30 | font-style: italic; 31 | font-weight: 700; 32 | src: url("https://gomakethings.com/fonts/pt-serif-v11-latin-700italic.woff2") format("woff2"), url("https://gomakethings.com/fonts/pt-serif-v11-latin-700italic.woff") format("woff"); 33 | } 34 | /* pt-sans-regular - latin */ 35 | @font-face { 36 | font-display: swap; 37 | font-family: "PT Sans"; 38 | font-style: normal; 39 | font-weight: 400; 40 | src: url("https://gomakethings.com/fonts/pt-sans-v12-latin-regular.woff2") format("woff2"), url("https://gomakethings.com/fonts/pt-sans-v12-latin-regular.woff") format("woff"); 41 | } 42 | /* pt-sans-italic - latin */ 43 | @font-face { 44 | font-display: swap; 45 | font-family: "PT Sans"; 46 | font-style: italic; 47 | font-weight: 400; 48 | src: url("https://gomakethings.com/fonts/pt-sans-v12-latin-italic.woff2") format("woff2"), url("https://gomakethings.com/fonts/pt-sans-v12-latin-italic.woff") format("woff"); 49 | } 50 | /* pt-sans-700 - latin */ 51 | @font-face { 52 | font-display: swap; 53 | font-family: "PT Sans"; 54 | font-style: normal; 55 | font-weight: 700; 56 | src: url("https://gomakethings.com/fonts/pt-sans-v12-latin-700.woff2") format("woff2"), url("https://gomakethings.com/fonts/pt-sans-v12-latin-700.woff") format("woff"); 57 | } 58 | /* pt-sans-700italic - latin */ 59 | @font-face { 60 | font-display: swap; 61 | font-family: "PT Sans"; 62 | font-style: italic; 63 | font-weight: 700; 64 | src: url("https://gomakethings.com/fonts/pt-sans-v12-latin-700italic.woff2") format("woff2"), url("https://gomakethings.com/fonts/pt-sans-v12-latin-700italic.woff") format("woff"); 65 | } -------------------------------------------------------------------------------- /themes/gmt/static/img/favicon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cferdinandi/vanilla-js-toolkit/eb8619bd3568ac00d863f32d616e67863e174392/themes/gmt/static/img/favicon-144.png -------------------------------------------------------------------------------- /themes/gmt/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cferdinandi/vanilla-js-toolkit/eb8619bd3568ac00d863f32d616e67863e174392/themes/gmt/static/img/favicon.ico -------------------------------------------------------------------------------- /themes/gmt/static/js/main.min.js: -------------------------------------------------------------------------------- 1 | /*! vanillajs v1.5.0 | (c) 2023 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/vanilla-js-toolkit */ 2 | !function(){"use strict";!function(e){let t=document.querySelector('[data-form="convertkit"]');if(!t)return;let n=t.querySelector("#email");if(!n)return;let r=t.querySelector("[data-status]"),a=t.querySelector("[data-processing]"),o="Please provide an email address.",s="Please use a valid email address.";function x(e,t){r&&(r.textContent=e,t?(r.classList.add("success-message"),r.classList.remove("error-message"),n.classList.remove("error")):(r.classList.add("error-message"),r.classList.remove("success-message"),n.classList.add("error")))}function c(){return n.value.length<1?(x(o),!1):!!/^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*(\.\w{2,})+$/.test(n.value)||(x(s),!1)}t.addEventListener("submit",(function(e){e.preventDefault(),t.hasAttribute("data-submitting")||(x(a.getAttribute("data-processing"),!0),c()&&(t.setAttribute("data-submitting",""),fetch(t.action,{method:"POST",body:new FormData(t),headers:{Accept:"application/json"}}).then((function(e){if(e.ok)return e.json();throw e})).then((function(e){x(e.msg,!0),e.redirect&&(window.location.href=e.redirect)})).catch((function(e){e.json().then((function(e){x(e.msg)}))})).finally((function(){t.removeAttribute("data-submitting")}))))})),t.setAttribute("novalidate","")}(),document.querySelector("#table-of-contents")&&function(e,t,n,r,a){if(!e||!t)return;let o=document.querySelector(e);if(!o)return;document.querySelectorAll(t),a=a||"ul";let s=Array.from(document.querySelectorAll(t)).map((function(e){return e.id?`
    • ${e.textContent}
    • `:""})).join("");s.length<1||(o.innerHTML=`${n||""}\n\t\t<${a}${r?` class="${r}"`:""}>\n\t\t\t${s}\n\t\t`)}("#table-of-contents","h2",'

      On this page

      ',null,"ul"),document.body.matches(".js-anchors")&&function(e,t,n){if(!e)return;let r=document.querySelectorAll(e),a=document.createElement("a");a.textContent=t||"#",a.className=n||"anchor-link";for(let e of r){if(!e.id)continue;let t=a.cloneNode(!0);t.href="#"+e.id,e.append(" ",t)}}("h2, h3, h4, h5, h6","#","link-no-underline"),function(){let e=new URL(window.location.href),t=e.searchParams.get("friend");t&&(e.searchParams.delete("friend"),history.replaceState(history.state,"",e.href),document.cookie=`gmt_aff=${t}; path=/; max-age=2419200;`)}(),function(e=".edd-buy-now-button"){let t=function(){let e=("; "+document.cookie).split("; gmt_aff=");if(2==e.length)return e.pop().split(";").shift()}();if(!t)return;let n=document.querySelectorAll(e);for(let e of n){let n=new URL(e);n.searchParams.set("friend",t),e.href=n.href}}('[href*="https://learnvanillajs.com"], [href*="https://vanillajsprojects.com"], [href*="https://vanillajstoolkit.com"], [href="https://vanillajspodcast.com"], [href*="https://vanillajsguides.com"], [href*="https://vanillajsacademy.com"], [href*="https://vanillajsshorts.com"], [href*="https://leanwebclub.com"], .edd-buy-now-button')}(); 3 | -------------------------------------------------------------------------------- /themes/gmt/static/js/search.min.js: -------------------------------------------------------------------------------- 1 | /*! vanillajs v1.5.0 | (c) 2023 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/vanilla-js-toolkit */ 2 | !function(){"use strict";!function(t){let e=document.querySelector("#form-search"),n=document.querySelector("#input-search"),r=document.querySelector("#search-results"),i=document.querySelector("#search-status"),o=["a","an","and","are","aren't","as","by","can","cannot","can't","could","couldn't","how","is","isn't","it","its","it's","that","the","their","there","they","they're","them","to","too","us","very","was","we","well","were","what","whatever","when","whenever","where","with","would","yet","you","your","yours","yourself","yourselves","the","vanilla","javascript","js"];function u(e){e.length?(i.innerHTML=`

      Found ${e.length} matching articles

      `,r.innerHTML=function(e){return e.map((function(e,n){return t(e.article,n)})).join("")}(e)):(i.innerHTML="

      Sorry, no matches were found.

      ",r.innerHTML="")}function a(t){let e=t.toLowerCase().split(" ").filter((function(t){return t.length&&!o.includes(t)})).map((function(t){return new RegExp(t,"i")}));u(searchIndex.reduce((function(t,n,r){let i=0;for(let t of e){t.test(n.title)&&(i+=100);let e=n.content.match(t);e&&(i+=e.length)}return i>0&&t.push({priority:i,article:n}),t}),[]).sort((function(t,e){return e.priority-t.priority}))),function(t){history.pushState&&history.pushState({},document.title,window.location.origin+window.location.pathname+"?s="+encodeURI(t))}(t)}t&&"function"==typeof t&&e&&n&&r&&i&&searchIndex&&(e.addEventListener("submit",(function(t){t.preventDefault(),a(n.value)})),function(){let t=(e="s",new URLSearchParams(window.location.search).get(e));var e;if(!t)return;let r=decodeURI(t);n.value=r,a(r)}())}((function(t,e){return!t.title||t.url.includes("/offline/")?"":`\n\t\t
    • \n\t\t\t
      ${t.type.replace("page","reference")}
      \n\t\t\t\n\t\t
    • `}))}(); 3 | -------------------------------------------------------------------------------- /themes/gmt/static/js/swInit.js: -------------------------------------------------------------------------------- 1 | /*! vanillajs v1.5.0 | (c) 2023 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/vanilla-js-toolkit */ 2 | (function () { 3 | 'use strict'; 4 | 5 | // Initialize the service worker 6 | if (navigator && navigator.serviceWorker) { 7 | navigator.serviceWorker.register('/sw.js'); 8 | } 9 | 10 | // Cleanup old cache on page load 11 | if (navigator.serviceWorker.controller) { 12 | window.addEventListener('load', function () { 13 | navigator.serviceWorker.controller.postMessage('cleanUp'); 14 | }); 15 | } 16 | 17 | }()); 18 | -------------------------------------------------------------------------------- /themes/gmt/static/js/swInit.min.js: -------------------------------------------------------------------------------- 1 | /*! vanillajs v1.5.0 | (c) 2023 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/vanilla-js-toolkit */ 2 | !function(){"use strict";navigator&&navigator.serviceWorker&&navigator.serviceWorker.register("/sw.js"),navigator.serviceWorker.controller&&window.addEventListener("load",(function(){navigator.serviceWorker.controller.postMessage("cleanUp")}))}(); 3 | -------------------------------------------------------------------------------- /themes/gmt/static/svg/icecream.svg: -------------------------------------------------------------------------------- 1 | icecream -------------------------------------------------------------------------------- /themes/gmt/theme.yml: -------------------------------------------------------------------------------- 1 | name: "Go Make Things" 2 | license: "MIT" 3 | 4 | Author: 5 | name: "Chris Ferdinandi" 6 | homepage: "https://gomakethings.com" --------------------------------------------------------------------------------