├── .gitignore ├── README.md ├── docker ├── commands │ ├── rm.md │ ├── push.md │ ├── stop.md │ ├── login.md │ ├── start.md │ ├── ps.md │ ├── container.md │ ├── image.md │ ├── build.md │ └── run.md ├── docker.md └── Dockerfile.md ├── http ├── README.md ├── csrf.md ├── cookies.md ├── origins.md ├── http.md └── cors.md ├── typescript ├── README.md ├── assertions-and-guards.md └── types.md ├── django ├── README.md ├── basics.md ├── urls.md ├── admin.md ├── views.md └── templates.md ├── d3 ├── README.md ├── intro.md ├── terminology.md ├── canvas.md ├── formatting.md ├── path.md ├── geo.md ├── axes.md ├── interpolators.md ├── data-binding.md ├── layouts.md └── svg.md ├── css ├── units.md ├── animations.md ├── flex.md └── grid.md ├── babel └── jest.md ├── svelte └── testing.md ├── graphql ├── prisma.md └── graphql.md ├── db └── mongo.md ├── git └── git.md ├── redux ├── redux.md └── react-redux.md ├── react-native ├── react-native.md └── animated.md └── ast └── nodes.md /.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Notes 2 | 3 | Various notes kept here for quick reference. 4 | -------------------------------------------------------------------------------- /docker/commands/rm.md: -------------------------------------------------------------------------------- 1 | # rm 2 | 3 | ```bash 4 | docker rm 5 | ``` 6 | 7 | Delete a container. 8 | -------------------------------------------------------------------------------- /docker/commands/push.md: -------------------------------------------------------------------------------- 1 | # push 2 | 3 | ```bash 4 | docker push 5 | ``` 6 | 7 | Push a container to Docker hub 8 | -------------------------------------------------------------------------------- /docker/commands/stop.md: -------------------------------------------------------------------------------- 1 | # stop 2 | 3 | ```bash 4 | docker stop 5 | ``` 6 | 7 | Stop a running container. 8 | -------------------------------------------------------------------------------- /docker/commands/login.md: -------------------------------------------------------------------------------- 1 | # login 2 | 3 | ```bash 4 | docker login 5 | ``` 6 | 7 | Login so that you can publish containers 8 | -------------------------------------------------------------------------------- /docker/commands/start.md: -------------------------------------------------------------------------------- 1 | # start 2 | 3 | ```bash 4 | docker start 5 | ``` 6 | 7 | Start an existing container that is not running. 8 | -------------------------------------------------------------------------------- /http/README.md: -------------------------------------------------------------------------------- 1 | * [HTTP](./http.md) 2 | * [Origins](./origins.md) 3 | * [CORS](./cors.md) 4 | * [CSRF](./csrf.md) 5 | * [Cookies](./cookies.md) 6 | -------------------------------------------------------------------------------- /docker/commands/ps.md: -------------------------------------------------------------------------------- 1 | # ps 2 | 3 | ```bash 4 | docker ps [-a] 5 | ``` 6 | 7 | Print a list of running container. 8 | 9 | ## Tags 10 | 11 | * `-a` - include stopped containers 12 | -------------------------------------------------------------------------------- /docker/commands/container.md: -------------------------------------------------------------------------------- 1 | # container 2 | 3 | ```bash 4 | docker container 5 | ``` 6 | 7 | Used to interact with containers 8 | 9 | ## ls 10 | 11 | ```bash 12 | docker container ls 13 | ``` 14 | -------------------------------------------------------------------------------- /typescript/README.md: -------------------------------------------------------------------------------- 1 | # TypeScript 2 | 3 | TypeScript is used to specify types. Variables have types. Function arguments have types. Function return values have types. 4 | 5 | * [Types](types.md) 6 | * [Assertions and Guards](assertions-and-guards.md) -------------------------------------------------------------------------------- /docker/commands/image.md: -------------------------------------------------------------------------------- 1 | # image 2 | 3 | ```bash 4 | docker image 5 | ``` 6 | 7 | Information about images. 8 | 9 | ## ls 10 | 11 | lists images 12 | 13 | ```bash 14 | docker image ls 15 | ``` 16 | 17 | ## rm 18 | 19 | remove an image 20 | 21 | ```bash 22 | docker image rm 23 | ``` 24 | -------------------------------------------------------------------------------- /docker/docker.md: -------------------------------------------------------------------------------- 1 | # Docker 2 | 3 | A container is defined using a [Dockerfile](./Dockerfile.md). 4 | 5 | An image is built using [`docker build`](./commands/build.md). 6 | 7 | Images can be viewed using [`docker image ls`](./commands/image.md). 8 | 9 | An image can be run using [`docker run`](./commands/run.md). -------------------------------------------------------------------------------- /docker/commands/build.md: -------------------------------------------------------------------------------- 1 | # build 2 | 3 | ```bash 4 | docker build 5 | ``` 6 | 7 | Create an image. The image will be stored in the local Docker image registry. 8 | 9 | This must be provided the location of the `Dockerfile`. If it is in the current directory, then `.` can be provided. 10 | 11 | ## Tags 12 | 13 | * `-t ` tags the build. 14 | -------------------------------------------------------------------------------- /docker/commands/run.md: -------------------------------------------------------------------------------- 1 | # run 2 | 3 | ```bash 4 | docker run 5 | ``` 6 | 7 | Create a container from the image and start the container 8 | 9 | ## Tags 10 | 11 | * `--name ` gives the container a name. 12 | * `--expose :` (short `-p`) specifies what container port to bind to what host (where the container is run) port. 13 | * `-d` runs in detached mode (background). -------------------------------------------------------------------------------- /django/README.md: -------------------------------------------------------------------------------- 1 | # Django Notes 2 | 3 | Django's [documentation](https://docs.djangoproject.com/en/2.0/) is great, but this has some helpful reminders for getting back up to speed. 4 | 5 | * [Basics](basics.md) 6 | * [Models](models.md) 7 | * [Views](views.md) 8 | * [URLs](urls.md) 9 | * [ORM](orm.md) 10 | * [Forms](forms.md) 11 | * [Users](users.md) 12 | * [Templates](templates.md) 13 | * [Admin](admin.md) 14 | -------------------------------------------------------------------------------- /d3/README.md: -------------------------------------------------------------------------------- 1 | # D3 2 | 3 | * [Intro](intro.md) 4 | * [Terminology](terminology.md) 5 | * [`` Overview](canvas.md) 6 | * [`` Overview](svg.md) 7 | 8 | ## Packages 9 | 10 | * [`d3-selection`](selections); 11 | * [`d3-scale`](scales.md) 12 | * [`d3-path`](path.md) 13 | * [Layouts with `d3-shape` and `d3-hierarchy`](layouts.md) 14 | * [`d3-format` and `d3-time-format`](formatting.md) 15 | * [`d3-interpolate`](interpolators.md) 16 | * [`d3-geo`](geo.md) 17 | * [`d3-axis`](axes.md) 18 | -------------------------------------------------------------------------------- /css/units.md: -------------------------------------------------------------------------------- 1 | # CSS Units 2 | 3 | ## px 4 | 5 | An absolute measurement of pixels 6 | 7 | ## % 8 | 9 | Percentage relative to the size of the parent 10 | 11 | ## em 12 | 13 | Relative to font size of current element (if font size is 16px, 1em = 16px) 14 | 15 | ### rem 16 | 17 | Relative to font size of root element (usually ``). 18 | 19 | ### vw 20 | 21 | 1vw = 1% of viewport width 22 | 23 | ### vh 24 | 25 | 1vh = 1% of viewport height 26 | 27 | ### fr 28 | 29 | A fractional measurement used by CSS grid. The value that an `fr` represents is determined by the sum of `fr`s in a column/row. 30 | -------------------------------------------------------------------------------- /http/csrf.md: -------------------------------------------------------------------------------- 1 | # Cross-site request forgery (CSRF) Protection 2 | 3 | ([cross-site request forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery)) 4 | 5 | > CSRF exploits the trust that a site has in a user's browser 6 | 7 | If a user visits a malicious site, that site attempt to make unwanted requests to another origin. This is known as a cross-site request forgery. 8 | 9 | An HTTP request to a server sends cookies. With same-origin CORS requests, cookies are only sent with credentials requests. However, other types of requests work without CORS validation. For example, the malicious site might use an `` tag's `src` element to make a request to another site. 10 | 11 | Cross-site request forgery takes advantage of vulnerable resources. This can include form submissions and requests that trigger other actions. 12 | 13 | CSRF prevention typically involves setting a unique token per response. When a client submits a request, it should include the token from the server's response. 14 | 15 | There are various methods for attaching a token to a request. For form submissions, the token may be included in the serialized form data (e.g. part of a `POST` request's body). Alternatively, a header field (`X-CSRF-Token`) may be passed with the token. 16 | -------------------------------------------------------------------------------- /babel/jest.md: -------------------------------------------------------------------------------- 1 | # Jest + Babel 2 | 3 | ## `babel-jest` 4 | 5 | With Babel 7, modules in `node_modules/` will no longer "inherit" the Babel config from the source of the `node_modules/`. 6 | 7 | In the below example, if `pkg/module.js` needs to be transformed using `babel-jest`, it **will not** use `project/.babelrc.js`. 8 | 9 | ``` 10 | project/ 11 | src/ 12 | index.js 13 | node_modules/ 14 | pkg/ 15 | module.js 16 | .babelrc.js 17 | ``` 18 | 19 | There are two ways to "fix" this. 20 | 21 | ### Custom Transformer 22 | 23 | Instead of passing `babel-jest` in the Jest configuration, a custom transformer can be created, to which you would pass the desired Babel configuration options. 24 | 25 | ```js 26 | // transformer.js 27 | const config = require("./.babelrc.js"); 28 | module.exports = require("babel-jest").createTransformer(config); 29 | ``` 30 | 31 | ```js 32 | // jest.config.js 33 | module.exports = { 34 | transform: { 35 | "\\.js$": "./transformer" 36 | } 37 | } 38 | ``` 39 | 40 | ### Root Config 41 | 42 | Instead of using a `.babelrc` or `.babelrc.js` file, you can use the `babel.config.js` file. This acts as a global configuration, so files in `node_modules/` will inherit its configuration. 43 | 44 | ```js 45 | // babel.config.js 46 | module.exports = { 47 | presets: [ 48 | ["env", { 49 | modules: "cjs" 50 | }] 51 | ] 52 | }; 53 | ``` 54 | -------------------------------------------------------------------------------- /http/cookies.md: -------------------------------------------------------------------------------- 1 | # Cookies 2 | 3 | [mdn](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) 4 | 5 | Cookies are data. 6 | 7 | A server can set cookies and send them to the client through header fields on a response. 8 | 9 | A client can interact with cookies and update their values. 10 | 11 | When the client sends another request to the server, the cookies will be attached to the request. 12 | 13 | ## `Document.cookie` 14 | 15 | On the client, the cookie string can be accessed using through the Document using `document.cookie`. This can be used for both reading and writing. 16 | 17 | ## Header Fields 18 | 19 | ### `Set-Cookie` 20 | 21 | A response header field specifying the key-value pair for a cookie. Multiple `Set-Cookie` headers are used for multiple pairs. 22 | 23 | ```bash 24 | Set-Cookie: street=sesame 25 | Set-Cookie: color=blue 26 | ``` 27 | 28 | #### Expiration 29 | 30 | A cookie without a specified expiration will theoretically expire when a session ends, although the browser may persist them. 31 | 32 | An `Expires` date can be attached to a cookie to specify when it should expire. 33 | 34 | ```bash 35 | Set-Cookie: auth=j90faw; Expires=; 36 | ``` 37 | 38 | #### Secure 39 | 40 | Secure cookies only get sent with HTTPS requests. 41 | 42 | ```bash 43 | Set-Cookie: auth=afj30; Secure; 44 | ``` 45 | 46 | #### HTTP Only 47 | 48 | HTTP only cookies cannot be read using `Document.cookie` 49 | -------------------------------------------------------------------------------- /typescript/assertions-and-guards.md: -------------------------------------------------------------------------------- 1 | # Type Assertions and Guards 2 | 3 | ## Type Assertions 4 | 5 | TypeScript can be forced to treat a variable as a certain type. There are two syntaxes for this. 6 | 7 | ```ts 8 | const thing = { 9 | title: "The Cat in the Hat", 10 | author: "Dr. Seuss" 11 | }; 12 | (thing).title 13 | // or 14 | (thing as Book).author 15 | ``` 16 | 17 | ## Type Guards 18 | 19 | Unions are convenient, but sometimes it is useful to narrow down the type. 20 | 21 | ```ts 22 | interface One { 23 | shape: string; 24 | size: number 25 | } 26 | 27 | interface Two { 28 | shape: string; 29 | color: string; 30 | } 31 | 32 | type OneOrTwo = One | Two; 33 | 34 | const x: OneOrTwo = { shape: "square", size: 2 }; 35 | ``` 36 | 37 | In the above code, we can see that `x` is a `One` because it has a `size` property. If we attempt to access `x.size`, TypeScript won't know for sure that `x` has a `size` property because it might be a `Two`. Type assertions can be used to safely access a property. 38 | 39 | ```ts 40 | const size: number = (x as One).size; 41 | ``` 42 | 43 | Type guards are functions that assert that a variable is a certain type. When the below function returns `true`, TypeScript will treat the variable in the scope where the function as called as a `One` (and a `Two` if it returns `false`). 44 | 45 | ```ts 46 | function isOne(v: OneOrTwo): v is One { 47 | return (v as One).size !== undefined; 48 | } 49 | 50 | const x: OneOrTwo = { shape: "square", size: 2 }; 51 | if (isOne(x)) { 52 | // no assertion necessary 53 | console.log(x.size); 54 | } else { 55 | console.log(x.color); 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /http/origins.md: -------------------------------------------------------------------------------- 1 | # Origins 2 | 3 | Resources may make requests for other resources. For example, an HTML document may include an `` tag to display an image. 4 | 5 | These requested resources may come from the same origin or from another origin. 6 | 7 | Browsers add security restrictions for resource requests to other origins. This is the "same-origin policy". 8 | 9 | ## Same-origin policy 10 | 11 | ([same-origin policy](https://en.wikipedia.org/wiki/Same-origin_policy)) 12 | 13 | An origin is specified by a location's `protocol`, `hostname` and `port`. 14 | 15 | A script on one page can only access data from another if they share the same origin. 16 | 17 | This restriction only applies to some types of data, while others can be freely used across origins. Examples of freely used resources are images (``), stylesheets (``), scripts (` 30 | 31 | 32 |
33 | ``` 34 | 35 | Data access across resources can be managed using [cross-origin resource sharing](./cors.md). 36 | 37 | Same-origin policy and CORS isn't a silver bullet against all different origin attacks. Resource requests that aren't restricted by same-origin policy can also be used to make malicious requests. This is known as [cross-site request forgery](./csrf.md). 38 | -------------------------------------------------------------------------------- /svelte/testing.md: -------------------------------------------------------------------------------- 1 | # Testing Svelte 2 | 3 | ## Jest Setup 4 | 5 | Testing Svelte components with Jest requires you to setup a Jest transformer. This is a module that exports a `process()` function. `process()` should either return a string of code or an object with a `code` property (whose value is a string of code). 6 | 7 | ```js 8 | // scripts/svelteCompile.js 9 | const svelte = require("svelte"); 10 | 11 | exports.process = function process(src) { 12 | const result = svelte.compile(src, { 13 | format: "cjs" 14 | }); 15 | return result.js.code; 16 | }; 17 | ``` 18 | 19 | Jest also needs to be setup to know what files to transform. This can be done by adding `html` to the known file extensions and telling Jest to use the transformer for those files. A JavaScript transformer should also be specified (e.g. `babel-jest`). 20 | 21 | ```js 22 | // jest.config.js 23 | module.exports = { 24 | moduleFileExtensions: ["js", "html"], 25 | transform: { 26 | "\\.js$": "babel-jest", 27 | "\\.html$": "./scripts/svelteCompile" 28 | }, 29 | transformIgnorePatterns: ["node_modules/(?!(svelte)/)"] 30 | }; 31 | ``` 32 | 33 | If the app is using Svelte's store (`svelte/store`), that will also need to be compiled. Jest typically ignores files in `node_modules/`, but files can be whitelisted. `(?!(svelte)\/)` will skip (i.e. _not_ ignore) any filenames in the `svelte` package. 34 | 35 | ## Jest Testing 36 | 37 | Testing a component is done by importing it and creating an instance. Jest comes with jsdom built-in, which makes mounting the instance simple. The (fake) DOM can then be queried and asserted against. 38 | 39 | ```html 40 | 41 |
{value}
42 | ``` 43 | 44 | 45 | ```js 46 | import MyComponent from "../src/MyComponent.html"; 47 | 48 | describe("", () => { 49 | it("does something", () => { 50 | const node = document.createElement("div"); 51 | const Cmp = new MyComponent({ 52 | target: node, 53 | data: { 54 | value: "hi!" 55 | } 56 | }); 57 | const div = document.querySelector("div"); 58 | expect(div.textContent).toBe("hi!"); 59 | }); 60 | }); 61 | ``` 62 | 63 | ### Events 64 | 65 | [`simulant`](https://github.com/Rich-Harris/simulant) makes testing events fairly simple. 66 | 67 | ```js 68 | const a = node.querySelector("a"); 69 | const event = simulant("click"); 70 | simulant.fire(a, event); 71 | ``` 72 | -------------------------------------------------------------------------------- /http/http.md: -------------------------------------------------------------------------------- 1 | # HTTP (Hypertext Transfer Protocol) 2 | 3 | A "request-response" protocol for transferring data between a client and a server. 4 | 5 | ## Resources 6 | 7 | Resources are identified using uniform resource indicators (URI) with a protocol of either `http` or `https`. 8 | 9 | ## Session 10 | 11 | 1. Client makes [TCP](#TCP) connection to a port on a server 12 | 2. Connection is established, server listens for request 13 | 3. Client sends request 14 | 4. Server sends [response](https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html) 15 | 16 | ### Request 17 | 18 | ```bash 19 | GET /some-page HTTP/1.1 # request line 20 | Host: www.example.com # request header fields 21 | 22 | # message body (optional) 23 | ``` 24 | 25 | #### Methods 26 | 27 | * `GET` - Request a resource from the server 28 | * `HEAD` - A `GET`-like response without the body 29 | * `POST` - Request that the server accepts body attached to the request 30 | * `PUT` - Request that attached body is stored at given URI (modify or create) 31 | * `PATCH` - Request partial modification of the resource 32 | * `DELETE` - Request the specified resource (URI) is deleted 33 | * `TRACE` - Request that the server echos the request 34 | * `OPTIONS` - Request the list of support HTTP methods 35 | 36 | ### Response 37 | 38 | ```bash 39 | HTTP/1.1 200 OK # status line 40 | Content-Type: text/html; charset=UTF-8 # response header fields 41 | Content-Encoding: gzip 42 | 43 | # message body (optional) 44 | 45 | ``` 46 | 47 | ## Transmission Control Protocol (TCP) 48 | 49 | [wiki](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) 50 | 51 | A server binds itself to a port and listens ("passive open"). An "active open" happens when a client establishes a connection with the server. 52 | 53 | ### Establishing a connection 54 | 55 | 1. `SYN` - Client sends random sequence number to the server (`X`). 56 | 2. `SYN-ACK` - Server responds with `X + 1` and its own random number `Y`. 57 | 3. `ACK` - Client acknowledges by return `Y + 1` (the acknowledgement number). Client stores `X + 1` as the sequence number. 58 | 59 | ### Terminating a connection 60 | 61 | Either the client or server can terminate a connection. 62 | 63 | 1. `FIN` - Client or server sends `FIN` packet to the other. 64 | 2. `ACK` - The other acknowledges by responding with an `ACK`. 65 | 3. `FIN` - The other sends its own `FIN` packet. 66 | 4. `ACK` - Original `FIN` sender sends `ACK` to the other and waits for some amount of time before closing the connection (to prevent in-transit packets from being used in future connections). 67 | -------------------------------------------------------------------------------- /d3/intro.md: -------------------------------------------------------------------------------- 1 | # D3 2 | 3 | D3, which stands for data driven documents, is made up a number of JavaScript modules that aid in making data visualizations. 4 | 5 | **Note:** The word data is the plural of datum. When data is used, it is referring to an array of datum. 6 | 7 | D3's modules have three main functionalities: 8 | 9 | ## Preparation 10 | 11 | D3 can analyze your data and add properties to it in order to prepare it to be rendered. 12 | 13 | For example, layouts are used to add properties to each datum. A pie layout will take a data array and return a new array where each datum will contain start and end angle information that can be used to draw the arcs for a pie chart. 14 | 15 | ```js 16 | const data = [{value: 1}, {value: 3}, {value: 2}, {value: 7}]; 17 | const pieData = pie(data); 18 | ``` 19 | 20 | ## Transformation 21 | 22 | D3 provides a number of modules that add support for rendering. 23 | 24 | Scale functions help you transform properties of your data into values used as attributes or text for DOM elements. 25 | 26 | ```js 27 | const scale = d3.scaleLinear() 28 | .domain([0, 10]) 29 | .range([0, 100]) 30 | //scale(1) === 10 31 | ``` 32 | 33 | Shape generators assist in creating the paths used to draw elements. 34 | 35 | ```js 36 | const line = d3.line(); 37 | .x(d => xScale(d.x)) 38 | .y(d => yScale(d.y)) 39 | .curve(d3.curveCardinal); 40 | ``` 41 | 42 | ## DOM Manipulation 43 | 44 | Using something called selections, D3 can work with the DOM to insert elements into a page, update them, and remove them. Selections are made by binding your data to an array of DOM elements. Selections can use transitions to animate DOM changes the bound data is updated. 45 | 46 | ```js 47 | const data = ['one', 'two', 'three']; 48 | d3.select('#root').selectAll('div.thing') 49 | .data(data) 50 | .enter().append('div') 51 | .classed('thing', true) 52 | .text(d => d) 53 | ``` 54 | 55 | The preparation and transformation methods do not care if you are using D3's DOM manipulation methods. You can interact with the DOM any way that you like, whether that is with D3 selections, React or any other of a number of libraries, or manually creating elements. This decoupling of functionality is what makes D3's splitting into multiple modules in version 4 great. You only need to include the parts of D3 that are necessary to your project, which reduces the amount of data that users of your project need to download. 56 | 57 | 58 | While you can use any DOM elements with D3, `` elements and the `` provide the most flexibility in creating visualizations. Using canvases and svg elements, you are unconstrained by the CSS box model. 59 | 60 | If you are unfamiliar with either the `` or ``, check out the [svg](svg.md) and [canvas](canvas.md) overviews. 61 | -------------------------------------------------------------------------------- /d3/terminology.md: -------------------------------------------------------------------------------- 1 | # D3 Terminology 2 | 3 | * `datum` - an individual unit of information 4 | ```js 5 | const datum = {x: 10, y: 5}; 6 | ``` 7 | * `data` - a collection of datum 8 | ```js 9 | const data = [{x: 10, y: 5}, {x: 7, y: 7}, {x: 1, y: 9}]; 10 | ``` 11 | * `selection` - an array of DOM elements. A selection has an array of data bound to it. Each item in the array is bound to an element. When there are fewer elements that items, new elements are made. When there are more elements than items, unmatched elements are removed from the DOM. 12 | ```js 13 | const selection = d3.select('svg').selectAll('circle'); 14 | ``` 15 | * `extent` - A two element array containing the lower and upper bounds for a set of values. 16 | ```js 17 | const values = [1,7,3,6,5,8,2]; 18 | const extent = d3.extent(values); 19 | // extent === [1, 8] 20 | ``` 21 | * `scale` - A function used to map data from an input domain to an output range. In most cases, the default domain and range are both [0, 1]. 22 | * `domain` - Upper and lower limits for input data for a scale. The lower limit will be mapped to the lower limit of the range and the upper limit will be mapped to the upper limit of the range. Values outside of the domain can be provided to a scale, but these typically will appear outside of the svg if the range is the width of the svg. 23 | ```js 24 | const line = d3.scale.linear() 25 | .domain(0, 100); 26 | const min = line(0); // === 0 27 | const max = line(100); // === 1 28 | const outside = line(200); // === 2 29 | ``` 30 | * `range` - Upper and lower limits for input domain to be mapped to in a scale. The lower limit of the domain maps to the lower limit of the range and the upper domain limit maps to the upper range limit. 31 | ```js 32 | const line = d3.scale.linear() 33 | .range([10, 20]); 34 | const min = line(0); // 10 35 | const max = line(1); // 20 36 | const outside = line(2); // 30 37 | ``` 38 | * `interpolate` - To map data from [0,1] (representing a percent, from 0% to 100%) to an output range, based on the type of the interpolator. Different types include numbers, colors, and objects. 39 | ```js 40 | // interpolate from black to white 41 | const grayscale = d3.interpolateRgb('#000', '#fff'); 42 | // get the color halfway between black and white 43 | const gray = grayscale(0.5); 44 | // gray === '#808080' 45 | ``` 46 | * `continuous` - Given a lower and an upper boundary, a continuous set includes every possible number between (and including) the boundaries. For example, the continuous set with a lower boundary of 0 and an upper boundary of 10, the set includes 0, 0.00001, 1, 3.14, 7, 10, and every other number that is equal to or larger than 0 and also less than or equal to 10. A continuous set is always quantitative. 47 | * `discrete` - A discrete set of data is an explicit set of values. This can be quantitative (the set of whole numbers with boundaries 0 and 5 is {0,1,2,3,4,5}) or categorical (the set of months is {January, February, March, April, May, June, July, August, September, October, November, December}). 48 | -------------------------------------------------------------------------------- /graphql/prisma.md: -------------------------------------------------------------------------------- 1 | # Prisma 2 | 3 | ## Packages 4 | 5 | For local development, the [`prisma`](http://npmjs.com/package/prisma) package should be installed. 6 | 7 | ```bash 8 | npm i -g prisma 9 | ``` 10 | 11 | Additionally, the [`graphql-cli`](https://www.npmjs.com/package/graphql-cli) package is useful for bootstrapping a project. 12 | 13 | ```bash 14 | npm i -g graphql-cli 15 | ``` 16 | 17 | ## Bootstrapping 18 | 19 | The `graphql-cli`'s `create` command is used to bootstrap a project using one of a number of prepared setups. 20 | 21 | ```bash 22 | graphql create 23 | ``` 24 | 25 | The file structure will look something like this (but varies based on which preset you use): 26 | 27 | ```bash 28 | ./ 29 | database/ 30 | datamodel.graphql 31 | prisma.yml 32 | seed.graphql 33 | src/ 34 | generated/ 35 | prisma.graphql 36 | resolvers/ 37 | Mutations/ 38 | auth.js 39 | post.js 40 | AuthPayload.js 41 | index.js 42 | Query.js 43 | Subscription.js 44 | index.js 45 | schema.graphql 46 | utils.js 47 | .env 48 | .graphqlconfig.yml 49 | package.json 50 | README.md 51 | ``` 52 | 53 | #### Default Service 54 | 55 | This initiates with a "public" Prisma service (as opposed to one linked to your Prisma account). It also automatically deploys to Prisma, which isn't necessarily ideal. `prisma delete` can be used to delete the default service. 56 | 57 | ```bash 58 | prisma delete 59 | ``` 60 | 61 | #### Prisma Secret 62 | 63 | You may need to include the Prisma secret in your `prisma.yml`. `graphql create` creates a generic secret in the `.env` file, so you can import it in the `prisma.yml`, but you should also change it to something more secure (random). 64 | 65 | When using a secret, the `GraphQlServer` should also include the secret. 66 | 67 | ```js 68 | const server = new GraphQLServer({ 69 | typeDefs: './src/schema.graphql', 70 | resolvers, 71 | context: req => ({ 72 | ...req, 73 | db: new Prisma({ 74 | endpoint: process.env.PRISMA_ENDPOINT, 75 | debug: true, 76 | secret: process.env.PRISMA_SECRET, // !!!! 77 | }), 78 | }), 79 | }); 80 | ``` 81 | 82 | #### TypeScript 83 | 84 | For TypeScript projects, a `graphql codegen` call should be added to the post-deploy hooks so that the TypeScript definitions are correctly generated after a deploy. 85 | 86 | ```bash 87 | # prisma.yml 88 | endpoint: ${env:PRISMA_ENDPOINT} 89 | 90 | datamodel: database/datamodel.graphql 91 | 92 | secret: ${env:PRISMA_SECRET} 93 | 94 | hooks: 95 | post-deploy: 96 | - graphql get-schema --project database 97 | - graphql codegen 98 | ``` 99 | 100 | #### Private Service 101 | 102 | A new service can be generated by calling `prisma deploy --new`. However, this will overwrite the endpoint in `prisma.yml` with a hard-coded string of the new service. You can either keep that as is, or (preferably) add the new service's location to the `.env` and restore the `PRISMA_ENDPOINT` import. 103 | -------------------------------------------------------------------------------- /http/cors.md: -------------------------------------------------------------------------------- 1 | # Cross-origin resource sharing (CORS) 2 | 3 | [Wiki](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) 4 | [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) 5 | 6 | CORS is used to manage resource usage across domains to prevent one site from making unwanted data requests to another. This is particularly valuable for sites that use request credentials (e.g. cookies) to authenticate requests. 7 | 8 | CORS is managed by the browser, not the client. 9 | 10 | ## Request Methods 11 | 12 | There are two types of CORS requests: "safe" and "unsafe". 13 | 14 | Safe requests (`GET`, `HEAD` and some `POST` requests) can be made directly. These requests are considered safe because they do not have an affect on the server. 15 | 16 | Requests that might result in changes on the server must be "preflighted" with an `OPTIONS` request to validate that the request is allowed. If the request is allowed, then the browser will send the actual request to the server. 17 | 18 | ## Headers 19 | 20 | Validation information for a cross-site request is passed between the browser and the server using header fields. 21 | 22 | ### Request Header Fields 23 | 24 | #### `Origin` 25 | 26 | The origin of the CORS request 27 | 28 | #### `Access-Control-Request-Method` 29 | 30 | A preflight header that specifies the (non-safe) method of the desired request. 31 | 32 | #### `Access-Control-Request-Headers` 33 | 34 | A preflight header that is a comma separated list of non-safe header fields that will be sent with the request. 35 | 36 | ### Response Header Fields 37 | 38 | #### `Access-Control-Allow-Origin` 39 | 40 | If a server wants to make a resource accessible to other origins, it can set a `Access-Control-Allow-Origin` header. The header can either be a wildcard (`*`) to allow any other origin to access the resource or be a list of one or more allowed origins. 41 | 42 | ```bash 43 | # request 44 | Origin: http://www.example.com 45 | 46 | # response 47 | # wildcard for any origin 48 | Access-Control-Allow-Origin: * 49 | # or specify a specific origin 50 | Access-Control-Allow-Origin: http://www.example.com 51 | ``` 52 | 53 | **Note:** A server can support multiple origins. It would compare the requests's origin to its valid origins and echo it in the `Access-Control-Allow-Origin` header. 54 | 55 | #### `Access-Control-Allow-Credentials` 56 | 57 | Cross-site requests made using `fetch()` or `XMLHTTPRequest` don't send credentials by default. They can be configured to, but if the response doesn't have an `Access-Control-Allow-Credentials` header set to `true`, the response will be rejected. 58 | 59 | Credentialed requests must have an origin-specific `Access-Control-Allow-Origin` header, wildcard headers will be rejected. 60 | 61 | #### `Access-Control-Allow-Methods` 62 | 63 | A header field for the response to a preflight `OPTIONS` request. This is a comma separated list of acceptable HTTP request methods. 64 | 65 | #### `Access-Control-Allow-Headers` 66 | 67 | A header field for the response to a preflight `OPTIONS` request. This is a comma separated list of acceptable request header fields. 68 | -------------------------------------------------------------------------------- /css/animations.md: -------------------------------------------------------------------------------- 1 | # CSS Animations 2 | 3 | ## Transitions 4 | 5 | Basic animation of CSS properties can be done using the `transition` property. The animation occurs as a result of a CSS change, such as hovering over an element or adding/removing a class. 6 | 7 | ```css 8 | .element { 9 | opacity: 0.5; 10 | transition: opacity 0.5s; 11 | } 12 | 13 | .element:hover { 14 | opacity: 1; 15 | } 16 | ``` 17 | 18 | The first value passed to `transition` is the property to animate. Not all CSS properties are animatable. The `all` keyword can be used to animate all animatable properties. The second value is the duration of the animation. The third value is the timing function which specifies how the animated value is interpolated at a given point in time; this value is optional. The fourth value is a delay and is also optional. 19 | 20 | Multiple animated properties can be provided in one transition; a comma is used to separate them. 21 | 22 | ```css 23 | transition: opacity 0.5s; 24 | transition: opacity 0.5s linear; 25 | transition: opacity 0.5s linear 0.5s; 26 | transition: opacity 0.5s 0.5s; 27 | transition: all 1s; 28 | transition: opacity 0.5s, color 1s; 29 | ``` 30 | 31 | ## Advanced 32 | 33 | Advanced CSS animations run automatically (as opposed to the CSS property change required by transitions). They are configured with an `animation` CSS property and a `@keyframes` rule. 34 | 35 | An animation's name corresponds to a keyframe's name. 36 | 37 | ```css 38 | animation-name: test 39 | 40 | @keyframes test {} 41 | ``` 42 | 43 | An animation's duration specifies how long one cycle of the animation lasts. 44 | 45 | ```css 46 | animation-duration: 2s; 47 | ``` 48 | 49 | How properties are interpolated at any X given time in the cycle are specified using a timing function. 50 | 51 | ```css 52 | animation-timing-function: linear; 53 | ``` 54 | 55 | An animation can be delayed. 56 | 57 | ```css 58 | animation-delay: 0.5s; 59 | ``` 60 | 61 | An animation can be run for a set number of cycles or continue infinitely. 62 | 63 | ```css 64 | animation-iteration-count: 5; 65 | animation-iteration-count: infinite; 66 | ``` 67 | 68 | An animation can start over every cycle or run in reverse. 69 | 70 | ```css 71 | animation-direction: alternate; 72 | ``` 73 | 74 | An animation can be paused or running. 75 | 76 | ```css 77 | animation-play-state: running; 78 | animation-play-state: paused; 79 | ``` 80 | 81 | The `@keyframes` rule defines the state of a property at a percentage of time in the animation. 0% is also aliased to `from` while 100% is aliased to `to`. 82 | 83 | ```css 84 | @keyframes example { 85 | from { 86 | opacity: 0; 87 | } 88 | 89 | 50% { 90 | opacity: 0.1; 91 | } 92 | 93 | to { 94 | opacity: 1; 95 | } 96 | } 97 | ``` 98 | 99 | ## Resources 100 | 101 | * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions 102 | * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations 103 | * https://www.kirupa.com/html5/css3_animations_vs_transitions.htm 104 | -------------------------------------------------------------------------------- /d3/canvas.md: -------------------------------------------------------------------------------- 1 | # `` Overview 2 | 3 | Just like a physical canvas, the HTML `` element is made to be drawn on. The drawing on a `` is done using a context object, unlike an ``, which uses nested elements. Still, the `` does not use a self-closing tag. This allows for any text or elements placed inside of the canvas element to be rendered when the browser cannot render the canvas. 4 | 5 | ```html 6 | This only displays if the browser cannot render a canvas 7 | ``` 8 | 9 | In order to draw on a canvas, you need a context object. You get a context by calling the `getContext` method on the `` element. The context that you will probably want is `'2d'`, but a `'webgl'` context also exists for three dimensional drawing. A context object has a number of methods that determine where and how to draw pixels on the canvas. It has also style values that can be set to change what the drawn pixels look like (for both its fill and stroke) and transformation values that affect the placement of the shapes. 10 | 11 | ```js 12 | const canvas = document.querySelector('canvas'); 13 | const context = canvas.getContext('2d'); 14 | 15 | context.fillStyle = 'red'; 16 | ``` 17 | 18 | **Note:** For a full list of the 2d context's methods, check out its documentation on MDN. The path methods are used to draw paths similarly to how the SVG path is drawn, but with methods instead of a string. 19 | 20 | Whenever the context draws to the canvas, it uses the style values it currently has set on it. Similarly, transformations can be made on the context to alter where items are drawn. The context has `save` and `restore` methods, which allow you to safely alter and restore the style and transformation values. 21 | 22 | ```js 23 | context.strokeStyle = 'blue'; 24 | context.fillStyle = 'orange'; 25 | ``` 26 | 27 | Whereas the `` element of the `` was defined using a configuration string, for a ``, a path is defined using a series of context method calls. 28 | 29 | ```js 30 | // a path is defined using a configuration string 31 | const path = document.createElement('path'); 32 | path.setAttribute('d', 'M50,50 L25,75'); 33 | 34 | // a path is defined using method calls 35 | const canvas = document.createElement('canvas'); 36 | const context = canvas.getContext('2d'); 37 | context.beginPath(); 38 | context.moveTo(50, 50); 39 | context.lineTo(25, 75); 40 | // ... 41 | ``` 42 | 43 | After you have finished defining a path, you will need to call the context's `stroke` and/or `fill` methods to draw the stroke and/or fill for the path. 44 | 45 | ```js 46 | // ... 47 | context.stroke(); 48 | ``` 49 | 50 | Unlike an ``, you are not creating elements that can be modified and removed. Any time that you want to remove or update something that you have drawn to the canvas, the whole thing will need to be cleared and redrawn. While this might seem slow, the canvas is actually very fast. In fact, people use the canvas to render games that need to redraw many times per second. 51 | 52 | ```js 53 | context.clearRect(0, 0, width, height); 54 | ``` 55 | -------------------------------------------------------------------------------- /d3/formatting.md: -------------------------------------------------------------------------------- 1 | # D3 Formatting 2 | 3 | When you want to output values in your data as strings, D3's formatting functions are your friends. These help you to control how numbers and dates appear. With formatting functions, you no longer have to worry about your numbers output with a dozen decimal places. 4 | 5 | ## Usage 6 | 7 | D3's formatting functions are the in `d3-format` and `d3-time-format` modules. 8 | 9 | ```bash 10 | npm install d3-format d3-time-format 11 | ``` 12 | 13 | ## Formatting Strings 14 | 15 | `format` takes a specifier string and returns a function that will format numbers. Below are a few examples of useful formatting string specifiers. For more specific formatting rules, check out the `d3-format` documentation. 16 | 17 | ```js 18 | import { format } from 'd3-format'; 19 | ``` 20 | 21 | #### Thousands separator 22 | 23 | ```js 24 | // Use a comma as a thousands separator 25 | const commas = format(','); 26 | const millions = commas(1234567); 27 | // millions = '1,234,567' 28 | ``` 29 | 30 | #### Positive/Negative 31 | 32 | ```js 33 | // Use a plus sign to show a +/- in front of positive/negative numbers 34 | const signed = format('+'); 35 | const pos = signed(100); 36 | // pos = '+100' 37 | 38 | const neg = signed(-23); 39 | // neg = '-23' 40 | ``` 41 | 42 | #### Fixed number of digits 43 | 44 | ```js 45 | // Number after period for fixed length mantissa 46 | const twoCharacters = format('2f'); 47 | const oneTwo = twoCharacters(1); 48 | // oneTwo === ' 1' 49 | 50 | const threeDigits = format('.3f'); 51 | const pi = threeDigits(3.14159); 52 | // pi === '3.142' 53 | ``` 54 | 55 | #### String length 56 | 57 | ```js 58 | // Number before period specifies how many characters the returned string should be 59 | const five = format('5f'); 60 | const output = five(23); 61 | // output.length = 5 62 | // output === ' 23' 63 | ``` 64 | 65 | #### Integer 66 | 67 | ```js 68 | // Use a zero after the decimal point to specify that output should 69 | // be an integer. This will round the number up or down. 70 | const integer = format('.0f'); 71 | const pi = integer(Math.PI); 72 | // pi === '3' 73 | ``` 74 | 75 | #### Round 76 | 77 | ```js 78 | import { precisionRound } from 'd3-format'; 79 | // precisionRound rounds a number to the given number of decimal places. 80 | 81 | const pi2 = d3.precisionRound(3.14159, 2); 82 | // pi2 === '3.14' 83 | 84 | // round defaults to 0 decimal places 85 | const pi3 = d3.precisionRound(3.14159); 86 | // pi3 === 3 87 | ``` 88 | 89 | ## Formatting Time 90 | 91 | **Note:** For more specific time formatting rules, check out the `d3-time-format` documentation. 92 | 93 | ```js 94 | import { timeFormat } from 'd3-time-format'; 95 | const date = new Date(1950, 0, 17); 96 | // %Y - return year in format XXXX 97 | const year = timeFormat('%Y'); 98 | const y = year(date); 99 | // y === '1950' 100 | ``` 101 | 102 | 103 | #### parse 104 | 105 | A time formatter can work in reverse to return a date 106 | 107 | ```js 108 | const year = timeFormat('%Y'); 109 | const newYears = year.parse('1990'); 110 | // newYears returns the same value as call to new Date(1990, 0, 1) 111 | ``` 112 | -------------------------------------------------------------------------------- /typescript/types.md: -------------------------------------------------------------------------------- 1 | # Type Overview 2 | 3 | ## Basic Types 4 | 5 | [TypeScript Basic Types](https://www.typescriptlang.org/docs/handbook/basic-types.html) 6 | 7 | The primitive types are `string`, `number` (for both ints and floats), and `boolean`. 8 | 9 | ```ts 10 | const x: string = "hi!"; 11 | const y: number = 5; 12 | const z: boolean = true; 13 | ``` 14 | 15 | A type can be either `undefined` or `null`. These are valid for any variable unless the `strictNullChecks` flag is used. 16 | 17 | ```ts 18 | const a: number; // currently undefined 19 | ``` 20 | 21 | The `void` type is useful for functions that don't return anything. Only `undefined` and `null` are valid `void` values. 22 | 23 | ```ts 24 | function log(msg): void { 25 | console.log(msg); 26 | } 27 | ``` 28 | 29 | The `any` type is a catch all for everything. It is useful when a type is variable or unknown, but should be used sparingly. 30 | 31 | ```ts 32 | const something: any; 33 | ``` 34 | 35 | ## Arrays 36 | 37 | The values in an array should be typed. There are two syntaxes for describing this: 38 | 39 | ```ts 40 | const one: Array = ['one', 'two', 'three']; 41 | const two: string[] = ['uno', 'dos', 'tres']; 42 | ``` 43 | 44 | The first uses TypeScript's generics while the second is a special syntax. 45 | 46 | ## Functions 47 | 48 | The arguments passed to a function and a function's return value should have types. 49 | 50 | ```ts 51 | function power(n: number, p: number): number{ 52 | return Math.pow(n, p); 53 | } 54 | ``` 55 | 56 | ## Interface 57 | 58 | An object's structure is described through an `interface`. The `interface` consists of property names and their respective types. 59 | 60 | A question mark after the property name designates the proeprty as optional. 61 | 62 | ```ts 63 | interface Book { 64 | title: string; 65 | author: string; 66 | pageCount?: number; // optional 67 | } 68 | ``` 69 | 70 | Function properties can be written two ways: 71 | 72 | ```ts 73 | interface API { 74 | one(): boolean; 75 | two: () => boolean; 76 | } 77 | ``` 78 | 79 | ### Extend 80 | 81 | An interface can extend another interface. This means that the interface inherits the properties from the interface that it extends. 82 | 83 | ```ts 84 | interface Parent { 85 | name: string; 86 | color: string; 87 | } 88 | 89 | interface Child extends Parent { 90 | shape: string; 91 | } 92 | 93 | const c: Child = { 94 | name: "test", 95 | color: "red", 96 | shape: "trapezoid 97 | }; 98 | ``` 99 | 100 | ## Multiple Types 101 | 102 | ### Intersection 103 | 104 | If a variable can be a combination of types (interfaces/classes), it is desribed as an intersection of those types. 105 | 106 | ```ts 107 | interface A { 108 | one: string; 109 | } 110 | 111 | interface B { 112 | two: string; 113 | } 114 | 115 | const c: A & B { 116 | one: "one", 117 | two: "two" 118 | }; 119 | ``` 120 | 121 | ### Unions 122 | 123 | If a variable can be one of a number of types, it is described as a union of those types. 124 | 125 | ```ts 126 | const x: number | string = "1"; // ;) 127 | ``` 128 | 129 | Unions are useful when using strict null checks to specify that a variable can also be either `undefined` or `null`. 130 | 131 | ```ts 132 | let n : number | undefined; 133 | ``` 134 | 135 | ## Type 136 | 137 | The `type` specifier can be used to describe complex types or alias other types. 138 | 139 | ```ts 140 | type Union = number | string; 141 | const x: Union = 2; 142 | 143 | type Intersection = A & B; 144 | const y: Intersection = { 145 | one: "uno", 146 | two: "dos" 147 | }; 148 | ``` 149 | -------------------------------------------------------------------------------- /css/flex.md: -------------------------------------------------------------------------------- 1 | # Flexbox 2 | 3 | https://css-tricks.com/snippets/css/a-guide-to-flexbox/ 4 | 5 | CSS rules for flexbox are divided between container properties (the element with `display: flex;`) and item properties (the direct descendant elements of the container). 6 | 7 | ## Container Rules 8 | 9 | ### display: flex; 10 | 11 | Sets an element as a flexbox. 12 | 13 | This can also be `inline-flex` for inline containers. 14 | 15 | ### flex-direction 16 | 17 | `row` (`row-reverse`) or `column` (`column-reverse`). 18 | 19 | ### flex-wrap 20 | 21 | `nowrap` (default), `wrap`, or `wrap-reverse`. 22 | 23 | ### flex-flow 24 | 25 | A combination of `flex-direction` and `flex-wrap`. 26 | 27 | ### justify-content 28 | 29 | Alignment of items along the flex direction axis. For `flex-direction: row`, this will align items along the x-axis. 30 | 31 | `flex-start` - content starts at beginning of axis 32 | `flex-end` - content ends at end of axis 33 | `center` - center content 34 | `space-between` - first item at beginning of axis, last item at end of axis, items spaced evenly 35 | `space-around` - each item has the same spacing before and after it; this means that the space before the first item and after the last item is half of the space between adjacent items 36 | `space-evenly` - even spacing around all items (including before first and after last items) 37 | 38 | ### align-items 39 | 40 | Alignment of items and the axis opposite of the flex direction. For `flex-direction: row`, this will align items along the y-axis. 41 | 42 | `flex-start` - items begin at beginning of axis 43 | `flex-end` - items end at end of axis 44 | `center` - items centered on center of axis 45 | `stretch` - items stretch to fill full axis (unless other properties specify a more specific size) 46 | `baseline` - items aligned along their baselines 47 | 48 | ### align-content 49 | 50 | Controls alignment of wrapped lines 51 | 52 | `flex-start` 53 | `flex-end` 54 | `center` 55 | `space-between` 56 | `space-around` 57 | `stretch` 58 | 59 | ## Items 60 | 61 | ### order 62 | 63 | Control the order that the item is displayed in. Defaults to `0` but can be a positive or negative integer. 64 | 65 | ### flex-grow 66 | 67 | Control how the item expand along its `flex-direction` axis. Each item in a line will contribute to the determined size. The default value `order` is 0 and the order must be positive. 68 | 69 | If there are three items, the first with `order: 1;`, the second with `order: 2;` and the third with `order: 3;`, the third's width will be 50% (3/6), the second will be 33% (2/6), and the first will be ~17% (1/6). 70 | 71 | Order accumulates on top of hard-coded sizing, like a `width`. 72 | 73 | ### flex-shrink 74 | 75 | Control how an item shrinks to fit into a line. This defaults to `1`. 76 | 77 | ### flex-basis 78 | 79 | Define the base size of an item (e.g. `50px` or `5em`). 80 | 81 | If this is `auto`, the value will be determined by the `width` or `height` (depending on its container's `flex-direction`). 82 | 83 | ### flex 84 | 85 | A combination of `flex-grow`, `flex-shrink`, and `flex-basis`. Defaults to `0 1 auto`. 86 | 87 | Only one argument is required; which rule this specifies is determined by the input. 88 | 89 | ```css 90 | flex: 50px; /* flex-basis */ 91 | flex: 1; /* flex-grow */ 92 | flex: 50px 3; /* flex-basis, flex-grow */ 93 | flex: 3 4; /* flex-grow, flex-shrink */ 94 | ``` 95 | 96 | ### align-self 97 | 98 | Controls the items alignment on the axis opposite the `flex-direction`; this overrides the `align-items` value. 99 | 100 | ## Resources 101 | 102 | * https://mastery.games/p/flexbox-zombies 103 | -------------------------------------------------------------------------------- /db/mongo.md: -------------------------------------------------------------------------------- 1 | # Mongo 2 | 3 | Mongo stores "documents", which are similar to JavaScript objects, but stored in binary (`BSON`). 4 | 5 | A database has "collections", which are groupings of "documents". The documents in a collection do not have to have the same structure. 6 | 7 | ## Server 8 | 9 | ```bash 10 | # start 11 | sudo service mongod start 12 | 13 | # stop 14 | sudo service mongod stop 15 | 16 | # restart 17 | sudo service mongod restart 18 | 19 | # open mongo shell (once db is running) 20 | mongo 21 | # can provide custom host/port 22 | mongo --host localhost:12345 23 | ``` 24 | 25 | ## Shell 26 | 27 | ```bash 28 | # list current database 29 | db 30 | 31 | # list available databases 32 | show dbs 33 | 34 | # switch to a database 35 | # you can switch to a non-existent, but it will not 36 | # be created until you create a new collection in it 37 | use 38 | 39 | # reference a collection through the db 40 | db.someCollection. 41 | ``` 42 | 43 | ## Collections 44 | 45 | ```bash 46 | # collection.insertOne will create a new collection 47 | # it will also create the database 48 | db.petCollection.insertOne({ type: 'dog' }) 49 | 50 | # createIndex also will create a collection/database 51 | db.petCollection.createIndex(...) 52 | 53 | # db.createCollection can also be used 54 | # this is useful for providing options for the collection 55 | db.createCollection('veterinarians', {...}) 56 | 57 | # for example, a collection can use validation 58 | # to enforce that its documents structure 59 | # https://docs.mongodb.com/manual/core/schema-validation/ 60 | db.createCollection('pets', { 61 | validator: { 62 | $jsonSchema: { 63 | bsonType: 'object', 64 | required: ['type'], 65 | properties: { 66 | type: { 67 | bsonType: 'string' 68 | } 69 | } 70 | } 71 | } 72 | }) 73 | 74 | # collections can be referenced directly 75 | # or using getCollection() 76 | db.pets 77 | db.getCollection('pets') 78 | ``` 79 | 80 | ## Documents 81 | 82 | ```bash 83 | { 84 | # a document's primary key 85 | # if this isn't provided, it will be 86 | # automatically generated 87 | _id: ObjectID(...) 88 | } 89 | 90 | # insertOne is used to insert a single document 91 | # into a collection 92 | db.pets.insertOne({ type: 'cat' }) 93 | 94 | # insertMany inserts an array of documents 95 | db.pets.insertMany([ 96 | { type: 'dog' }, 97 | { type: 'cat' }, 98 | { type: 'turtle' } 99 | ]) 100 | 101 | # find finds documents 102 | db.pets.find({ type: 'dog' }) 103 | 104 | # an empty query will find all 105 | db.pets.find({}) 106 | 107 | # $in matches if a property exists in the given array 108 | db.pets.find({ 109 | type: { $in: ['dog', 'cat'] } 110 | }) 111 | 112 | # multiple query conditions is similar to 113 | # a SQL AND 114 | db.pets.find({ 115 | type: 'dog', 116 | age: 3 117 | }) 118 | 119 | # $or is similar to a SQL OR 120 | db.pets.find({ 121 | $or: [ 122 | { type: 'dog' }, 123 | { age: 5 } 124 | ] 125 | }) 126 | 127 | # documents can be updated 128 | # https://docs.mongodb.com/manual/reference/operator/update/ 129 | 130 | # updateOne will update the first match 131 | db.pets.updateOne( 132 | { type: 'dog' }, 133 | { $set: { name: 'Hank' }} 134 | ) 135 | 136 | # updateMany will update all matches 137 | db.pets.updateMany( 138 | { type: 'dog' }, 139 | { $set: { noise: 'bark' }} 140 | ) 141 | 142 | # replaceOne will replace all fields 143 | # but the _id 144 | db.pets.replaceOne( 145 | { name: 'Hank' }, 146 | { type: 'dog', name: 'Henry' } 147 | ) 148 | 149 | # documents can be removed using 150 | # deleteOne and deleteMany 151 | db.pets.deleteOne({ name: 'Henry' }) 152 | db.pets.deleteMany({ type: 'iguana' }) 153 | ``` 154 | 155 | ## Indexes 156 | 157 | Indexes allow for more efficient querying. 158 | 159 | ```bash 160 | # an index is created using a field name as a key 161 | # and the index type (sort order) as the value 162 | # where an index of 1 is ascending and 163 | # an index of -1 is descending 164 | db.pets.createIndex({ 165 | age: 1 166 | }) 167 | 168 | # an index can be created on multiple fields 169 | # the index will be created in the order the 170 | # fields are provided 171 | db.pets.createIndex({ 172 | type: 1, 173 | age: -1 174 | }) 175 | ``` -------------------------------------------------------------------------------- /d3/path.md: -------------------------------------------------------------------------------- 1 | # D3 Path 2 | 3 | ## About 4 | 5 | The `d3-path` module is used to define how shapes are drawn inside of a `` element. It has one main method, `path`, which returns an object that has methods for defining how to render the path. 6 | 7 | ```bash 8 | npm install d3-path 9 | ``` 10 | 11 | ## Path Holders 12 | 13 | Before we look at what the `d3-path` module does, it is important to understand the HTML elements that can have paths rendered in them. Both the `` and the `` contain similar ideas about how to define shapes using lines and curves. 14 | 15 | ### Canvas 16 | 17 | In order to render a path to a `` element, you need a context. The context contains a number of methods for drawing a path. When you begin to draw a path, you must start with moving to a certain pixel, which is done by calling the context's `moveTo` method. Then, you call a method to define how to move to another point and if a line or curve should be rendered between the two. You continue to call context methods until the path has been completed. Because we can programmatically define a path in JavaScript, we don't need to create a context when drawing a path inside of a canvas. 18 | 19 | ### SVG 20 | 21 | Rendering a path inside of a `` element is done using its `d` attribute. This attribute is a string of commands concatenated together to define how the shape should be drawn. Each command starts with a letter and then a series of numbers. For example, `M 75,25` specifies that the path should move to the mixel with coordinates `<75,25>`. The SVG's rendering engine will parse this string to determine how to render the path. Manually creating the `d` attribute string would involve lots of string formatting and concatenation. `d3-path` exists to do this work for us, while using the same API as the canvas context. 22 | 23 | ## Path 24 | 25 | The `path` method creates a new path object. This object acts as a context and has the same methods for drawing a path as the canvas's context. Because this object replicates the canvas context's method, we can write code that will render to either and svg or a canvas depending on the context. 26 | 27 | ```js 28 | import { path } from 'd3-path'; 29 | 30 | const context = path(); 31 | context.moveTo(20,20); 32 | context.lineTo(30,20); 33 | // ... 34 | ``` 35 | 36 | The context object returned by the `path` method contains an array. Every time one of the object's rendering methods is called, the values representing how to render that step are added to the context object's array. Once every step needed to describe the path has been called, we can call the context object's `toString` method. This will concatenate the results together into a string that we then can use as the `d` attribute to a `` element. 37 | 38 | ```js 39 | // ... 40 | const d = context.toString(); 41 | // d === 'M20,20L30,20' 42 | ``` 43 | 44 | ## Context Agnostic Code 45 | 46 | As mentioned above, the context object created by `d3-path` replicates the path rendering methods of a canvas context. That means that we can write code that takes a generic context object and it will render our path correctly regardless of whether it is to a canvas or an svg. 47 | 48 | When using a canvas, we get a context object using the canvas's `getContext` method. When using an svg, we use `d3-path`'s `path` method. 49 | 50 | ```js 51 | // given a canvas and svg element: 52 | const canvas = document.querySelector('canvas'); 53 | const svg = document.querySelector('svg'); 54 | const path = svg.querySelector('path'); 55 | 56 | const canvasContext = canvas.getContext('2d'); 57 | const svgContext = path(); 58 | 59 | // we can then write element agnostic code 60 | // to define how to draw the path 61 | function drawSquare(context) { 62 | context.moveTo(10,10); 63 | context.lineTo(40,10); 64 | context.lineTo(40,40); 65 | context.lineTo(10,40); 66 | context.closePath(); 67 | } 68 | ``` 69 | 70 | This doesn't contain any magic that gets rid of other rendering related code that differs between the two types. For canvas elements, we will still need to call the context's `beginPath` method to begin the drawing and either its `stroke` or `fill` method to finish it. For svg elements, the context will need to be output as a string and set as the `d` attribute. Still, all of the steps in between can be shared. 71 | 72 | ```js 73 | // render to the canvas 74 | canvasContext.beginPath(); 75 | drawSquare(canvasContext); 76 | canvasContext.stroke(); 77 | 78 | // render to the svg 79 | drawSquare(svgContext); 80 | path.setAttribute('d', svgContext.toString()); 81 | ``` 82 | -------------------------------------------------------------------------------- /docker/Dockerfile.md: -------------------------------------------------------------------------------- 1 | # Dockerfile 2 | 3 | Defines the container environment. 4 | 5 | ## Commands 6 | 7 | https://docs.docker.com/engine/reference/builder/ 8 | 9 | ### FROM 10 | 11 | https://docs.docker.com/engine/reference/builder/#from 12 | 13 | A base image 14 | 15 | > a valid Dockerfile must start with a `FROM` instruction 16 | 17 | ```bash 18 | FROM ubuntu 19 | ``` 20 | 21 | ### USER 22 | 23 | https://docs.docker.com/engine/reference/builder/#user 24 | 25 | Set the user (and possibly the group) 26 | 27 | ```bash 28 | USER username 29 | USER username:group 30 | USER UID 31 | USER UID:GID 32 | ``` 33 | 34 | ### WORKDIR 35 | 36 | https://docs.docker.com/engine/reference/builder/#workdir 37 | 38 | Sets the working directory. This will be used by any subsequent `RUN`, `CMD`, `ENTRYPOINT`, `COPY`, and `ADD` commands. 39 | 40 | Multiple `WORKDIR`s can be specified; relative `WORKDIR`s will be on the previous `WORKDIR` path. 41 | 42 | ```bash 43 | WORKDIR /test 44 | WORKDIT ing # /test/ing 45 | ``` 46 | 47 | ### ENV 48 | 49 | https://docs.docker.com/engine/reference/builder/#env 50 | 51 | Set an environment variable 52 | 53 | ```bash 54 | ENV key value # one variable 55 | ENV key=value another=value # multiple variables, requires equals sign 56 | ``` 57 | 58 | ### ADD 59 | 60 | https://docs.docker.com/engine/reference/builder/#add 61 | 62 | Copy files, directories, and URLs from source to destination. 63 | 64 | If the source is a recognized archive format, `ADD` will unpack it. 65 | 66 | ```bash 67 | ADD source destination # UID & GID = 0 68 | ADD --chown=UID:GID source destination 69 | ADD --chown=UID source destination # GID = UID 70 | ``` 71 | 72 | Source interpreted relative to build's source context. 73 | 74 | Destination is either absolute or relative to the `WORKDIR` 75 | 76 | If `--chown` is not provided, files/directories created with UID & GID of 0. 77 | 78 | ### COPY 79 | 80 | https://docs.docker.com/engine/reference/builder/#copy 81 | 82 | Copy files/directories from source to destination. `COPY` is like `ADD`, but doesn't support URLs and does not unpack archives. 83 | 84 | ```bash 85 | COPY source destination 86 | COPY ["source with spaces", "destination location"] 87 | COPY --chown=user:group source destination 88 | ``` 89 | 90 | ### CMD 91 | 92 | https://docs.docker.com/engine/reference/builder/#cmd 93 | 94 | Run a command, primarily used for provide defaults for executing container. 95 | 96 | Only one `CMD` is allowed per Dockerfile. If there are multiple, the last one will be used. 97 | 98 | ```bash 99 | CMD ["executable", "param", "another"] 100 | CMD command param another 101 | ``` 102 | 103 | ### RUN 104 | 105 | https://docs.docker.com/engine/reference/builder/#run 106 | 107 | Run a command and create a new image. Use case: install a package on top of the OS. 108 | 109 | The command can either be provided in shell form or exec form. 110 | 111 | ```bash 112 | RUN command # shell form 113 | RUN ["sequence", "of", "values"] # exec form 114 | ``` 115 | 116 | ### ARG 117 | 118 | https://docs.docker.com/engine/reference/builder/#arg 119 | 120 | A build-time variable, with optional default value. 121 | 122 | ```bash 123 | ARG name 124 | ARG other=default 125 | ``` 126 | 127 | Docker comes with some [built-in args](https://docs.docker.com/engine/reference/builder/#predefined-args). 128 | 129 | ### LABEL 130 | 131 | https://docs.docker.com/engine/reference/builder/#label 132 | 133 | Used for adding metadata to an image with key value pairs. 134 | 135 | ```bash 136 | LABEL one="two" 137 | LABEL three="four" five="six" 138 | LABEL seven="eight" \ 139 | nine="ten" \ 140 | "eleven twelve"="thirteen" 141 | ``` 142 | 143 | An image's labels can be viewed using `docker inspect`. 144 | 145 | ### EXPOSE 146 | 147 | https://docs.docker.com/engine/reference/builder/#expose 148 | 149 | Tell docker to listen to specified port. TCP or UDP (TCP is default if not specified) 150 | 151 | ```bash 152 | EXPOSE 80/tcp 153 | EXPOSE 123 # tcp 154 | EXPOSE 456/udp 155 | ``` 156 | 157 | These can be overriden at runtime with the `-p` flag. 158 | 159 | ```bash 160 | docker run -p 80:80/tcp 161 | ``` 162 | 163 | ### ENTRYPOINT 164 | 165 | https://docs.docker.com/engine/reference/builder/#entrypoint 166 | 167 | > configure a container that will run as an executable 168 | 169 | ```bash 170 | ENTRYPOINT ["executable", "one", "two"] # exec form 171 | ENTRYPOINT command one two # shell form 172 | ``` 173 | 174 | ### VOLUME 175 | 176 | https://docs.docker.com/engine/reference/builder/#volume 177 | 178 | Create a mount point -------------------------------------------------------------------------------- /django/basics.md: -------------------------------------------------------------------------------- 1 | # Django Basics 2 | 3 | **Note:** This tutorial was originally written using Python 3.5 and Django 1.9. 4 | 5 | ## Setup 6 | 7 | ### Virtual Environment 8 | 9 | Often times when developing you will have multiple Django projects with different requirements. For example, when you start a new project, you will most likely be using the latest version of Django. For older projects, they might be using an older version of Django. Even for projects that use the same version of Django, they might use different versions of other packages. To avoid these conflicts, you should make use of virtual environments. Each environment has its own Python executable as well as packages. 10 | 11 | ```bash 12 | pyvenv 13 | // windows 14 | python -m venv 15 | ``` 16 | 17 | Once you have created a virtual environment, you need to activate it. When the virtual environment is not activated, your global Python will be used and packages will be installed to it. When the virtual environment is activated, its Python executable will be used and any packages that you install (e.g. through pip) will be installed in the virtual environment. 18 | 19 | ```bash 20 | /bin/activate 21 | // windows 22 | /Scripts/activate 23 | ``` 24 | 25 | ### Pip Install 26 | 27 | After you have your environment setup to how you would like, you are ready to install Django. 28 | 29 | ```bash 30 | pip install django 31 | ``` 32 | 33 | ## Django Projects 34 | 35 | When you install Django, a `django-admin.py` file will be created (if you use a virtual environment, it will be located in the `/Scripts` directory). To create a new Django site, all you have to do is call the django-admin script with the startproject command. 36 | 37 | 38 | ```bash 39 | django-admin startproject 40 | ``` 41 | 42 | This will create a project directory, containing the base necessary files for your Django project, as well as a manage.py file which you will use to interact with your project. 43 | 44 | ``` 45 | 46 | | - manage.py 47 | + - 48 | | - __init__.py 49 | | - settings.py 50 | | - urls.py 51 | + - wsgi.py 52 | ``` 53 | 54 | At this point you can run your server locally, and you will get a "Congratulations" page, but nothing particularly interesting. The site will be accessible at `http://localhost:8000`. 55 | 56 | ```bash 57 | python manage.py runserver 58 | ``` 59 | 60 | ## Settings 61 | 62 | Django gets relevant information for a project from a settings module. By default, Django creates a `settings.py` file in your project directory when you create a project. The location of the settings module that Django uses is determined from the environment variable `DJANGO_SETTINGS_MODULE`. You can access the settings for a project by importing them from Django's `conf` module. 63 | 64 | ```python 65 | from django.conf import settings 66 | ``` 67 | 68 | **Note:** In order for a variable in a settings module to be accessible by Django, the variable name must be in all capital letters. `FOO_BAR` will work, but `baz_quux` will not. 69 | 70 | ### Multiple Settings Modules 71 | 72 | When you create a project using the `startproject` command, a `settings.py` file is created. This is good enough for some simple projects, but you will quickly run into issues once a project becomes complicated. For example, the database that you run in development is not (should not be) the same as the database that is run in production. Also, while you may want to leave debugging on in development, you never want it on in production because of the risk of it leaking information. For this reason, it is convenient to create a `settings` folder that contains a number of settings modules for different situations. 73 | 74 | ``` 75 | // default 76 | settings.py 77 | 78 | // better 79 | settings 80 | | - __init__.py 81 | | - base.py 82 | | - dev.py 83 | + - production.py 84 | ``` 85 | 86 | Any settings that should be shared across environments can be kept in the `base.py` module. Then, in your `dev/production` modules, you can import the base settings (`from .base import *`) and specify other settings that are only relevant to that environment. 87 | 88 | When developing locally, you can either specify an environment variable to indicate that the dev settings module should be used or edit `manage.py` to hardcode the dev settings module as the default settings module. 89 | 90 | ```python 91 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', '.settings.dev') 92 | ``` 93 | 94 | In production, you should specify the correct settings module using the `DJANGO_SETTINGS_MODULE` environment variable. 95 | 96 | ## Django Apps 97 | 98 | Django projects are made up of apps. Apps provide a way to group related objects, and are where you will define objects using models that will have corresponding tables in your database. An app's views are used to render responses to HTTP requests related to the app. Apps are created by calling `manage.py` with the startapp command. 99 | 100 | 101 | ```bash 102 | python manage.py startapp 103 | ``` 104 | 105 | This will create a directory for the app with some files that you might find useful for your app (but are not necessarily required). 106 | 107 | ``` 108 | 109 | | - manage.py 110 | | - 111 | + - 112 | | - migrations 113 | | - __init__.py 114 | | - admin.py 115 | | - apps.py 116 | | - models.py 117 | | - tests.py 118 | + - views.py 119 | ``` 120 | 121 | Django does not automatically detect that an app exists. Instead it has to be registered by adding its name to the list of `INSTALLED_APPS` in your settings. 122 | 123 | ```python 124 | INSTALLED_APPS = [ 125 | # ... 126 | 'app_name' 127 | ] 128 | ``` 129 | 130 | For more information on the various files in an app's directory, check out these tutorials on [models](./models.md), [views](./views.md), [urls](./urls.md), and [admin](./admin.md). 131 | -------------------------------------------------------------------------------- /d3/geo.md: -------------------------------------------------------------------------------- 1 | # D3 Geo 2 | 3 | ## About 4 | 5 | The `d3-geo` module is used to draw GeoJSON and TopoJSON features. It contains a path generator to create the path that outlines a geographic element and projection functions that control how coordinates in the GeoJSON feature map to pixels in an `` or `` element. The module also has sphere related methods, which can be helpful when projecting to a globe, and graticule methods, which draw lines representing latitudes and longitudes. 6 | 7 | ```bash 8 | npm install d3-geo 9 | ``` 10 | 11 | ## GeoJSON & TopoJSON 12 | 13 | A common way to store geographic information is using the GeoJSON format. GeoJSON files describe 'features', which are made up of polygons, points, and lines. For example, a GeoJSON object that describes how to render all of the states in the United States would contain a feature for every state. The feature for a state would be a polygon made up of a series of coordinates which define the border of the state. 14 | 15 | One problem with GeoJSON is that it can contain a lot of redundant data. For example, most states in the United States share borders. In GeoJSON, each of these shared borders would be replicated for each state that contains it. TopoJSON removes this redundancy by creating arcs (arrays of coordinates). A polygon is made up of arcs, so states with a common border will both contain the same arc. 16 | 17 | ## Path Generator 18 | 19 | The `geoPath` method returns a path generator. This generator will be passed feature data (from a GeoJSON or TopoJSON object) to output directions on how to render a path. 20 | 21 | ```js 22 | import { geoPath } from 'd3-path'; 23 | const path = geoPath(); 24 | svg.select('svg').append('path') 25 | .datum(featureData) 26 | .attr('d', path); 27 | ``` 28 | 29 | ### Projections 30 | 31 | There are a number of projection functions to render geographic elements differently. The default projection used by the `geoPath` generator is null, which simply maps geographic features using the provided values. 32 | 33 | Among the included projections are Mercator, Albers, and Orthographic projections. The projections can be configured to change how they render the path. The Albers USA projection is a pre-configured Albers projection that draws a map of the continental 48 states with Alaska and Hawaii placed in the lower left corner. 34 | 35 | ```js 36 | import { geoAlbersUsa } from 'd3-geo'; 37 | const path = geoPath() 38 | .projection(geoAlbersUsa()); 39 | ``` 40 | 41 | A few of the projection configuration methods are listed below. For a complete list, check out the projection documentation. 42 | 43 | The `clipExtent` projection method takes an array of two coordinates. The coordinates make up a rectangle, with the first being the top left corner and the second the bottom right corner. Any parts of the path that are outside of this rectangle will be cut off. 44 | 45 | ```js 46 | import { geoAlbers } from 'd3-geo'; 47 | const projection = geoAlbers() 48 | .clipExtent([0,0], [200,200]); 49 | ``` 50 | 51 | The `scale` method allows you to control the scaling for converting coordinates to pixels. Each projection has its own default scale. 52 | 53 | ```js 54 | const projection = geoAlbers() 55 | .scale(500); 56 | ``` 57 | 58 | The `translate` method takes an array with two values. The projection's output path will be horizontally translated by the first value and vertically translated by the second. 59 | 60 | ```js 61 | const projection = geoAlbers() 62 | .translate([10, 10]); 63 | ``` 64 | 65 | The projection's `fitExtent` method takes a bounding rectangle and a feature object and determines the projection's scale and translation for you. The `fitSize` method is nearly the same, but instead of tale the corners of a bounding rectangle, it expects the width and height of the rectangle. 66 | 67 | ```js 68 | // given a GeoJSON feature called "feature" 69 | const projection = geoAlbers() 70 | .fitExtent([[10,10], [190,190]], feature); 71 | ``` 72 | 73 | ### Context 74 | 75 | The context of the path generator is used to generate the path. If you do not provide a context, this will output an svg `` string (the value for the `d` attribute). Otherwise, you can pass it a canvas context to draw the feature to a ``. 76 | 77 | ```js 78 | const canvas = document.querySelector('canvas'); 79 | const context = canvas.getContext('2d'); 80 | 81 | const path = geoPath() 82 | .context(context); 83 | ``` 84 | 85 | ### Point Radius 86 | 87 | When the path has to draw a point, it draws a circle. You can control the radius of this circle with the `pointRadius` method. This can either be a number or a function that will determine a radius based on the feature. The default radius is `4.5`. 88 | 89 | ```js 90 | const path = geoPath() 91 | .pointRadius(6); 92 | ``` 93 | 94 | ## Graticules 95 | 96 | Graticules help visualize relative latitudes and longitudes of points within a projection. 97 | 98 | ```js 99 | import { geoGraticule } from 'd3-geo'; 100 | const graticules = geoGraticule(); 101 | const path = geoPath(); 102 | svg.select('svg').append('path') 103 | .datum(graticules) 104 | .attr('d', path); 105 | ``` 106 | 107 | The `extent` of the graticules can be controlled. This controls the coordinates of northern-, southern-, western, and easternmost points within which graticules should be drawn. These values are provided in degrees. 108 | 109 | ```js 110 | const graticules = geoGraticule() 111 | .extent([[-90, -90], [90, 90]]); 112 | ``` 113 | 114 | The number of degrees separating the graticule lines is defined using line methods. These values are provided in degrees. 115 | 116 | ```js 117 | const graticules = geoGraticule() 118 | .step([45, 30]); 119 | ``` 120 | -------------------------------------------------------------------------------- /d3/axes.md: -------------------------------------------------------------------------------- 1 | # D3 Axes 2 | 3 | ## About Axes 4 | 5 | Axes are useful for displaying the scale of x or y axis. Scales can be quantitative, time based, or ordinal (qualitative such as a set of names). D3 provides methods for creating axes in the `d3-axis` module. 6 | 7 | ```bash 8 | npm install d3-axis 9 | ``` 10 | 11 | ## Create an Axis 12 | 13 | D3 provides four methods, with their names indicating their alignment, for creating an axis generator: `axisTop`, `axisRight`, `axisBottom`, and `axisLeft`. A top aligned axis is horizontal and has ticks drawn above the axis. A bottom aligned axis is horizontal and has ticks drawn below the axis. A left aligned axis is vertical and has ticks aligned to the left of the axis. A right aligned axis is vertical and has ticks aligned to the right of the axis. 14 | 15 | ```js 16 | import { axisBottom, axisLeft } from 'd3-axis'; 17 | 18 | const xAxis = axisBottom(); 19 | const yAxis = axisLeft(); 20 | ``` 21 | 22 | An axis takes a scale function. The scale function is necessary to determine what values in the scale correspond to which pixels in the element that the chart is drawn in. The scale can either be passed to the axis when creating it or through its `scale` method. 23 | 24 | ```js 25 | import { scaleTime } from 'd3-scale'; 26 | 27 | const xScale = scaleTime() 28 | .domain([new Date(1910, 0, 1), (new Date(2010, 0, 1))]) 29 | .range([0, 500]); 30 | 31 | const axis1 = axisBottom(xScale); 32 | // or 33 | const axis2 = axisBottom() 34 | .scale(xScale); 35 | ``` 36 | 37 | Remember that for vertical scales, 0 is the top of the `` so the range on a vertical scale should be reversed in most cases. 38 | 39 | ```js 40 | import { scaleLinear } from 'd3-scale'; 41 | 42 | const yScale = scaleLinear() 43 | .domain([0, 10000]) 44 | .range([250, 0]); 45 | ``` 46 | 47 | ## Drawing Ticks 48 | 49 | In order to know what values exist at points along an axis, ticks are used. These are rendered using a line and a text value. 50 | 51 | The length of the lines drawn for each tick can be controlled. The ticks at the beginning and end of an axis are outer ticks, while all other ticks are inner ticks. Inner and outer ticks can be specified to have different lengths by using the `tickSizeInner` and `tickSizeOuter` methods. If you want both to have the same size, you can just use the `tickSize` method. 52 | 53 | ```js 54 | yAxis.tickSizeInner(5); 55 | yAxis.tickSizeOuter(10); 56 | 57 | // or use tickSize to set both 58 | xAxis.tickSize(5); 59 | ``` 60 | 61 | The axis has a `tickFormat` method that will be called when adding text to ticks. This allows you to modify the text value to something that looks better in the chart. 62 | 63 | ```js 64 | import { format } from 'd3-format'; 65 | import { timeFormat } from 'd3-time-format'; 66 | 67 | xAxis.tickFormat(timeFormat('%Y')); 68 | yAxis.tickFormat(format(',f')); 69 | ``` 70 | 71 | The distance between a tick and the text for the tick can be set using the `tickPadding` method. 72 | 73 | ```js 74 | yAxis.tickPadding(5); 75 | ``` 76 | 77 | ## Tick Values 78 | 79 | If you don't specify how the axis should determine its ticks, this will be done for you. If you want greater control over these values, there are a number of methods that allow you to do so. 80 | 81 | You can control the exact values of the ticks with the `tickValues` method. 82 | 83 | ```js 84 | yAxis.tickValues([0, 75, 150, 1000, 2500, 5000, 10000]); 85 | ``` 86 | 87 | If you want to control how the ticks are determined without provided exact values, you can use the `ticks` method. This will use the axis's scale's `ticks` method to determine the tick values. It can take two arguments. The first argument is either the number of ticks that the axis should have (but not necessarily the number that it _will_ have, depending on how evenly they can be fit) or the time interval between ticks for a time scale. The second argument is a formatting function that will be used to render the tick's text value. 88 | 89 | ```js 90 | yAxis.ticks(5); 91 | ``` 92 | 93 | The `tickArguments` function is similar to `ticks`, but takes the arguments as a single array. 94 | 95 | ```js 96 | yAxis.tickArguments([5]); 97 | ``` 98 | 99 | ## Rendering the Axis 100 | 101 | To draw an axis, you need to create a group element for the axis. The axis doesn't know how to place itself, so you will need to transform the group to move it to the correct position. Then call the group element's `call` method, passing it the axis. 102 | 103 | ```js 104 | improt { select } from 'd3-selection'; 105 | 106 | select('svg').append('g') 107 | .attr('transform', 'translate(50, 500)') 108 | .classed('x axis', true) 109 | .call(xAxis); 110 | 111 | select('svg').append('g') 112 | .attr('transform', 'translate(100, 100)') 113 | .classed('y axis', true) 114 | .call(yAxis); 115 | ``` 116 | 117 | ## Styling Axes 118 | ```css 119 | /* 120 | * use crispEdges for a sharper looking axis 121 | * since these are vertical/horizontal lines 122 | * / 123 | .axis line, .axis path{ 124 | fill: none; 125 | stroke: #000; 126 | shape-rendering: crispEdges; 127 | } 128 | 129 | /* 130 | * align text with a tick 131 | */ 132 | .tick text{ 133 | text-anchor: middle; /* or start or end */ 134 | } 135 | ``` 136 | 137 | ## Full Example Code 138 | 139 | Below is the full code used to render some x and y axes. 140 | 141 | ```js 142 | import { axisBottom, axisLeft } from 'd3-axis'; 143 | import { select } from 'd3-selection'; 144 | import { scaleTime, scaleLinear } from 'd3-scale'; 145 | 146 | const holder = select(holder); 147 | const fullWidth = 600; 148 | const fullHeight = 250; 149 | const margin = { 150 | top: 15, 151 | right: 15, 152 | left: 50, 153 | bottom: 50 154 | }; 155 | const width = fullWidth - margin.left - margin.right; 156 | const height = fullHeight - margin.top - margin.bottom; 157 | const svg = holder.append('svg') 158 | .attr('width', fullWidth) 159 | .attr('height', fullHeight) 160 | .append('g') 161 | .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); 162 | 163 | const xScale = scaleTime() 164 | .domain([new Date(1910, 0, 1), (new Date(2010, 0, 1))]) 165 | .range([0, width]); 166 | 167 | const yScale = scaleLinear() 168 | .domain([0, 10000]) 169 | .range([height, 0]); 170 | 171 | const xAxis = axisBottom(xScale) 172 | .tickSize(5); 173 | const yAxis = axisLeft(yScale) 174 | .tickSizeInner(5) 175 | .tickSizeOuter(10); 176 | 177 | svg.append('g') 178 | .attr('transform', 'translate(0,' + height + ')') 179 | .classed('x axis', true) 180 | .call(xAxis); 181 | 182 | svg.append('g') 183 | .classed('y axis', true) 184 | .call(yAxis); 185 | ``` 186 | -------------------------------------------------------------------------------- /git/git.md: -------------------------------------------------------------------------------- 1 | # Git Notes 2 | 3 | ## Files 4 | 5 | ### `.gitignore` 6 | 7 | List of files/directories that should not be tracked. 8 | 9 | * Each line indicates a file/directory to ignore 10 | * Directories should be specified with a trailing forward slash (`/`) 11 | * Children of directories listed in `.gitignore` will also be ignored 12 | * Globs work 13 | * Comments can be added by beginning a line with a pound sign (`#`) 14 | * Pattern that start with exclamation point (`!`) are negated 15 | 16 | ### `.git/HEAD` 17 | 18 | Stores a reference to the current commit. 19 | 20 | ### `.git/objects/` 21 | 22 | Files in this directory are git objects. These are `blob`s for files and `tree`s for files. Everything is identified by a 40 character SHA-1 hash. The first two characters in the hash identify the folder and the last 38 are the filename. Hashes are generated using a header and the contents of the object to be hashed. 23 | 24 | ### `.git/index` 25 | 26 | Information about the current staging area. 27 | 28 | ### `.git/refs/` 29 | 30 | References to branches and tags (local and remote). These are short strings that are easier to remember than SHA-1 hashes. 31 | 32 | ## Objects 33 | 34 | ### blob 35 | 36 | A file 37 | 38 | ### tree 39 | 40 | A directory 41 | 42 | ### commit 43 | 44 | Like a tree, but the top level is the SHA-1 hash of a tree, information about the author, when the commit was made, and a commit message 45 | 46 | ## Commands 47 | 48 | ### init 49 | 50 | ```bash 51 | git init 52 | ``` 53 | 54 | Create a new git repository. This will add a `.git` folder to the directory. 55 | 56 | ### clone 57 | 58 | ```bash 59 | git clone git://repository-location/repo.git [name] 60 | ``` 61 | 62 | Create a copy of any existing repo. If `name` is provided, the repo will be copied into a directory with the name `name`. Otherwise, the directory will be named using the repository's name (e.g. `repo` from `repo.git`). 63 | 64 | ### status 65 | 66 | ```bash 67 | git status 68 | ``` 69 | 70 | Display the current branch, staged files, modified files (tracked, and modified since last commit, but not staged), and untracked files. 71 | 72 | ### add 73 | 74 | ```bash 75 | git add 76 | ``` 77 | 78 | Stages (and tracks if previously untracked) the provided file(s). Directories are added recursively. 79 | 80 | ### diff 81 | 82 | ```bash 83 | git diff 84 | ``` 85 | 86 | Display the lines in each file that have changed since the last commit. 87 | 88 | `git diff` only shows the diff for files that have not been staged. To see the diff for staged files, pass the `--staged` flag. 89 | 90 | ### commit 91 | 92 | ```bash 93 | git commit 94 | ``` 95 | 96 | Create a new commit object for the files that have been staged. 97 | 98 | Calling `git commit` on its own will launch a text editor for you to write a commit message. 99 | 100 | Alternatively, you can use the `-m` flag to pass a message inline. These can also be chained together. 101 | 102 | ```bash 103 | git commit -m "This is the commit message" -m "This is an extra commit message" 104 | ``` 105 | 106 | The `-a` flag will add any tracked files to the staging area without having to use `git add`. 107 | 108 | ```bash 109 | git commit -a -m "Look ma, no git add" 110 | ``` 111 | 112 | The `--amend` flag allows you to "fix" the last commit. This is useful if you forget to stage a file or need to change the commit message. 113 | 114 | ### rm 115 | 116 | ```bash 117 | git rm 118 | ``` 119 | 120 | Untrack a file/directory and also remove it from the local filesystem. Globs can also be used here. 121 | 122 | The `-f` flag must be used to remove a modified and staged file. 123 | 124 | The `--cached` flag will untrack a file but will not remove it from the filesystem. 125 | 126 | ### mv 127 | 128 | ```bash 129 | git mv 130 | ``` 131 | 132 | Move/rename a file without having to explicitly having to untrack the old name and start tracking the new one. 133 | 134 | ### log 135 | 136 | ```bash 137 | git log 138 | ``` 139 | 140 | Display commits on the current branch. 141 | 142 | * `-p` shows the diff for each commit. 143 | * `--stat` shows file diff stats for each commit 144 | * `--pretty=oneline|short|full|fuller|format:"..."` changes how each commit is displayed 145 | * `--graph` will add add ASCII to display commits as a graph 146 | * `--abbrev-commit` only shows the first 7 SHA-1 hash characters 147 | * `--oneline` combintes `--pretty=oneline` and `--abbrev-commit` 148 | * `-` (where `n` is a number) shows only the last `n` commits 149 | 150 | ### reset 151 | 152 | ```bash 153 | git reset HEAD 154 | ``` 155 | 156 | Unstage a staged file. 157 | 158 | 159 | ### checkout 160 | 161 | ```bash 162 | git checkout -- 163 | ``` 164 | 165 | Resets a file to to its state from the last commit. 166 | 167 | ### remote 168 | 169 | ```bash 170 | git remote 171 | ``` 172 | 173 | Display the name of remote repositories. `-v` flag shows expanded version. 174 | 175 | ```bash 176 | git remote add 177 | ``` 178 | 179 | Add a remote repository with the reference name `name`. When you `git clone`, an `origin` remote will automatically be created. 180 | 181 | ```bash 182 | git remote show 183 | ``` 184 | 185 | Displays information about a remote repository 186 | 187 | ```bash 188 | git remote rename 189 | ``` 190 | 191 | ```bash 192 | git remote rm 193 | ``` 194 | 195 | Removes the reference to a remote repository 196 | 197 | ```bash 198 | git remote prune origin 199 | ``` 200 | 201 | Remove remote branch references 202 | 203 | ### fetch 204 | 205 | ```bash 206 | git fetch 207 | ``` 208 | 209 | Downloads the data from a remote branch. 210 | 211 | ### pull 212 | 213 | ```bash 214 | git pull 215 | ``` 216 | 217 | Fetch and merge a remote repo 218 | 219 | ### push 220 | 221 | ```bash 222 | git push 223 | ``` 224 | 225 | Uploads the provided branch/tag to the remote repository. 226 | 227 | ```bash 228 | git push origin --tags 229 | ``` 230 | 231 | You can also upload all tags using the `--tags` flag. 232 | 233 | ### tag 234 | 235 | ```bash 236 | git tag 237 | ``` 238 | 239 | List available tags. You can also use the `-l` flag to filter tags. 240 | 241 | ```bash 242 | git tag 243 | ``` 244 | 245 | Create a tag which the provided `name`. 246 | 247 | ```bash 248 | git tag -a -m "message" 249 | ``` 250 | 251 | Annotated tags can be created using the `-a` flag. These tags have a message attached using the `-m` flag. 252 | 253 | ```bash 254 | git tag 255 | ``` 256 | 257 | You can add a tag to a previous commit by providing that commit's hash. 258 | -------------------------------------------------------------------------------- /css/grid.md: -------------------------------------------------------------------------------- 1 | # Grid 2 | 3 | * https://css-tricks.com/snippets/css/complete-guide-grid/ 4 | * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout 5 | 6 | Grid is a two dimensional layout system (as opposed to flexbox being one dimensional). 7 | 8 | A grid is made up of horizontal and vertical lines. The spaces between these lines (where content is displayed) are known as tracks. 9 | 10 | Each grid line is numbered, starting with index `1`. Horizontally, for left-to-right languages, 1 is the left-most, while it is the right-most for right-to-left. (Note: verify how switching languages swaps LTR/RTL). Vertically, 1 is the top line. 11 | 12 | Items in the grid can be given an area name. This name is used to place the item in the grid. 13 | 14 | CSS rules for grid are divided between container properties (the element with `display: grid;`) and item properties (the direct descendant elements of the container). 15 | 16 | ## Terminology 17 | 18 | * `track` - the space between lines of the grid 19 | * `cell` - the smallest unit of a grid. multiple items can occupy the same cell 20 | * `area` - a rectangular shape made up of one or more grid cells 21 | * `gutter`/`alley` - space between cells 22 | * `fr` - a measurement unit representing one fraction of the grid's width (for columns) or height (for rows). Fractions are calculated after hard-coded widths. 23 | 24 | ## Container Rules 25 | 26 | ### display: grid 27 | 28 | Sets an element as a grid. 29 | 30 | This can also be an `inline-grid`. 31 | 32 | ### grid-template-columns, grid-template-rows 33 | 34 | **Note:** The following properties apply to both `grid-template-columns` and `grid-template-rows`, but the examples will only refer to `grid-template-columns`. 35 | 36 | A space separated list of track sizes. 37 | 38 | A track can either use standard CSS units, `fr`s, or one of a number of special types. 39 | 40 | ```css 41 | grid-template-columns: 100px 1fr 2fr 1fr; 42 | /* 43 | the first cell will be 100px, the other cells 44 | will be their fraction out of the sum of the fractions (4) 45 | */ 46 | ``` 47 | 48 | Line will automatically be assigned two names: a positive number (based on position) and a negative number (reverse position). The lines can be named using square brackets. A line can be given multiple names by separating them with spaces in the assignment. 49 | 50 | ```css 51 | grid-template-columns: [one-start] 100px [one-end two-start] 100px [two-end]; 52 | ``` 53 | 54 | #### Special Types 55 | 56 | `auto` inherits min/max size. 57 | 58 | `minmax` is used to specify minimum/maximum sizes for a track 59 | 60 | ```css 61 | grid-template-columns: minmax(100px, 1fr) 1fr 1fr; 62 | ``` 63 | 64 | `repeat` is used to define multiple tracks that fit into a pattern 65 | 66 | ```css 67 | grid-template-columns: repeat(1fr); 68 | ``` 69 | 70 | `auto-fill` adds as many columns (or rows) as will fit, including empty columns (or rows). 71 | 72 | `auto-fit` adds as many columns (or rows) as will fit, then collapses empty columns (or rows) and expands filled ones. 73 | 74 | 75 | ### grid-template-areas 76 | 77 | Define a grid template using grid area names. The areas are defined with a string per row and space separated grid area names per column. 78 | 79 | Names can be used multiple times to span multiple cells. 80 | 81 | An empty cell is denoted by a period (`.`). 82 | 83 | ```css 84 | grid-template-areas: 85 | "one one two" 86 | "three three two" 87 | ". . four"; 88 | ``` 89 | 90 | ### grid-template 91 | 92 | A combination of `grid-template-columns`, `grid-template-rows`, and `grid-template-areas`. 93 | 94 | ### gap, row-gap, column-gap 95 | 96 | Define the gutter size between cells. `gap` can be used as shorthand; if provided two values they represent `gap: row-gap column-gap;`. 97 | 98 | **Note:** These properties may need to be prefixed with `grid-` for older browser support. 99 | 100 | ### justify-items / align-items 101 | 102 | `justify-items` aligns items along the row axis (left/right), while `align-items` aligns items along the column axis (top/bottom). 103 | 104 | * `start` - starting edge of the cell 105 | * `end` - ending edge of the cell 106 | * `center` - center of the cell 107 | * `stretch` - fill entire cell (default) 108 | 109 | ### place-items 110 | 111 | A combination of `justify-items` and `align-items`. 112 | 113 | ```css 114 | place-items: align-items justify-items; 115 | ``` 116 | 117 | **Note:** Not supported in (pre-chromium?) Edge. 118 | 119 | ### justify-content / align-content 120 | 121 | Control horizontal/vertical alignment of the grid within the grid container (if it is smaller than the container). 122 | 123 | These have the same properties as [`flexbox`'s `justify-content`](./flex.md#justify-content). 124 | 125 | ### place-content 126 | 127 | A combination of `justify-content` and `align-content`. 128 | 129 | ```css 130 | place-content: align-content justify-content; 131 | ``` 132 | 133 | ### grid-auto-columns / grid-auto-rows 134 | 135 | Control the size of implicit tracks 136 | 137 | ### grid-auto-flow 138 | 139 | Control the placement of items that aren't explicitly placed 140 | 141 | * `row` - fill in each row, adding rows if necessary (default) 142 | * `column` - fill in each column, adding columns if necessary 143 | * `row dense`/`column dense` - fill in holes where possible (probably avoid, can be bad for a11y) 144 | 145 | ### grid 146 | 147 | Shorthand for `grid-template-rows`, `grid-template-columns`, `grid-template-areas`, `grid-auto-rows`, `grid-auto-columns`, and `grid-auto-flow`. 148 | 149 | This seems fairly complex and easy to mess up, so I'll probably avoid it until I am more comfortable with CSS grids. 150 | 151 | ## Item Rules 152 | 153 | ### grid-column-start / grid-column-end / grid-row-start / grid-row-end 154 | 155 | Specify an item's location using line names. 156 | 157 | ```css 158 | grid-column-start: 1; 159 | grid-column-end: 3; 160 | ``` 161 | 162 | `span ` tells the item to span across the named line instead of ending at it. 163 | 164 | `span ` tells the item to span across the provided number of tracks. 165 | 166 | ### grid-column / grid-row 167 | 168 | Shorthand for combining the start and end values. 169 | 170 | ```css 171 | grid-column: start / end; 172 | grid-row: start / end; 173 | ``` 174 | 175 | ### grid-area 176 | 177 | Name an item for use in `grid-template-areas` or a combination of `grid-column` and `grid-row`. 178 | 179 | ```css 180 | grid-area: test; 181 | grid-area: col-start / col-end / row-start / row-end; 182 | ``` 183 | 184 | ### justify-self 185 | 186 | Override value from grid container's `justify-items`. 187 | 188 | ### align-self 189 | 190 | Override value from grid container's `align-items`. 191 | 192 | ### place-self 193 | 194 | Combination of `justify-self` and `align-self`. 195 | 196 | ```css 197 | place-self: align-self justify-self; 198 | ``` 199 | -------------------------------------------------------------------------------- /d3/interpolators.md: -------------------------------------------------------------------------------- 1 | # Interpolators 2 | 3 | ## About Interpolators 4 | 5 | An interpolator takes two arguments, a lower and an upper bounds. These two values are mapped to `0` and `1`. Given a value between and including `0` and `1`, which represents a percentage from 0% to 100%, the interpolator will return its equivalent value between the lower and upper bounds. 6 | 7 | Interpolators are an important part of transitions. A transition on an attribute starts with one value, is constantly updated over a set period of time, and then is given an end value. At each update time, the percent of time that has elapsed is used to determine what percent of the way through the transition we are currently at. That value is passed to an interpolator to determine what the value the attribute should have right now. 8 | 9 | ## Using Interpolators 10 | 11 | D3's interpolators are in the `d3-interpolate` module. 12 | 13 | ```bash 14 | npm install d3-interpolate 15 | ``` 16 | 17 | ## D3 Interpolators 18 | 19 | D3 has a number of interpolators built-in. 20 | 21 | ### Generic Interpolator 22 | 23 | ```js 24 | import { interpolate } from 'd3-interpolate'; 25 | const interpolator = interpolate(0, 100); 26 | ``` 27 | 28 | `interpolate` returns the correct interpolator based on the second argument. In order, it will make the following checks on the value of the second argument: 29 | 30 | 31 | * `null`, `undefined`, `true`, or `false`? The interpolator function will always return the second value. 32 | * Number? `interpolateNumber` 33 | * Color? `interpolateRgb` 34 | * Date? `interpolateDate` 35 | * String? `interpolateString` 36 | * Array? `interpolateArray` 37 | * Can coerce to a number? `interpolateNumber` 38 | * Everything else failed? `interpolateObject` 39 | 40 | ### Interpolate Numbers 41 | 42 | `interpolateNumber` is used to interpolate between two numbers. 43 | 44 | ```js 45 | import { interpolateNumber } from 'd3-interpolate'; 46 | const nums = interpolateNumber(0, 10); 47 | const pi = nums(0.314); 48 | // pi === 3.14 49 | ``` 50 | 51 | It is better to interpolate from 1e-6 than from 0 when the result is used as a string to prevent an interpolated number from appearing in scientific notation. 52 | 53 | ### Interpolate Colors 54 | 55 | `interpolateRgb` takes two colors as its arguments. The colors may either be css colors or rgb hex strings of either 3 digits (eg '#123') or 6 digits (eg '#123DEF'). 56 | 57 | ```js 58 | import { interpolateRgb } from 'd3-interpolate'; 59 | const colors = interpolateRgb('red', '#00FFFF'); 60 | ``` 61 | 62 | A hash table is used to lookup the rgb value of known css colors. 63 | 64 | ```js 65 | import { range } from 'd3-array'; 66 | 67 | const weirdColors = interpolateRgb('chartreuse', 'oldlace'); 68 | const weirds = range(2).map(weirdColors); 69 | // weirdColors(0) === '#7fff00' 70 | // weirdColors(1) === '#fdf5e6'' 71 | ``` 72 | 73 | If a value passed to the interpolator is not a valid color string of rgb hex string, it defaults to #000000. 74 | 75 | ```js 76 | const unknownColor = interpolateRgb('red','some fake color'); 77 | const unknown = unknownColor(1); 78 | // unknown === '#000000' 79 | ``` 80 | 81 | 82 | Colors can also be in HSL (`interpolateHsl`), L*a*b* (`interpolateLab`), or HCL (`interpolateHcl`), but will return an rgb hexadecimal string 83 | ```js 84 | import { interpolateHsl } from 'd3-interpolate'; 85 | const hsl = interpolateHsl('hsl(0, 100%, 50%)',' hsl(255, 100%, 50%)') 86 | const halfHsl = hsl(0.5) 87 | // halfHsl === '#ff00df' 88 | ``` 89 | 90 | ### Interpolate Dates 91 | 92 | `interpolateDate` is used to interpolate between two `Date` objects. 93 | 94 | ```js 95 | import { interpolateDate } from 'd3-interpolate'; 96 | const year = interpolateDate(new Date('01-01-2016'), new Date('01-01-2017')); 97 | ``` 98 | 99 | ### Interpolate Strings 100 | 101 | `interpolateString` finds any numbers in the second argument, and attempts to match it to a number in the first argument. Non-number parts and unmatched numbers in the second argument string are used statically as a template. 102 | 103 | ```js 104 | import { interpolateString } from 'd3-interpolate'; 105 | const strings = interpolateString('I am 0% complete', 'I am 100% complete'); 106 | const halfway = strings(0.5); 107 | // halfway === 'I am 50% complete' 108 | ``` 109 | 110 | In the above example, only the 0 is needed in the first string. 111 | 112 | ```js 113 | const partialStrings = d3.interpolateString('0', 'I am 100% complete'); 114 | const partString = partialStrings(0.5); 115 | // partString === 'I am 50% complete' 116 | ``` 117 | 118 | If there are more numbers in the second string than the first, unmatched numbers will be included as part of the template. 119 | 120 | ```js 121 | const unmatched = d3.interpolateString('0', 'it is 15 minutes until 7 o\'clock'); 122 | const halfmatched = unmatched(0.5); 123 | // halfmatched === 'it is 7.5 minutes until 7 o'clock' 124 | ``` 125 | 126 | 127 | ### Interpolate Array 128 | 129 | `interpolateArray` matches values in the second array to corresponding values in the first. For each value in the array with a corresponding one in the first, a generic interpolator is created. If there is no matching value in the first array, the value is used statically in the template. 130 | 131 | Interpolate array matches based on values in the second array. 132 | 133 | ```js 134 | import { interpolateArray } from 'd3-interpolate'; 135 | const arrays = interpolateArray([1,2,3],[4,5,6]); 136 | const third = arrays(1/3); 137 | // third === [2,3,4] 138 | ``` 139 | 140 | If there is no matching element in the first array to one in the second, that value is used statically 141 | 142 | ```js 143 | const nomatch = interpolateArray([1,2],[3,4,5]); 144 | const halfway = nomatch(0.5); 145 | // halfway = [2,3,5]; 146 | ``` 147 | 148 | Any type of nested elements in the array will work 149 | 150 | ```js 151 | const anytype = d3.interpolateArray([0, {x:10}], ['testing 10', {x:100}]); 152 | const mixedResults = anytype(0.5); 153 | // mixedResults = ['testing 5', {x:55}] 154 | ``` 155 | 156 | ### Interpolate Object 157 | 158 | `interpolateObject` uses all of the properties in the second argument, matching to properties in the first argument. 159 | 160 | ```js 161 | import { interpolateObject } from 'd3-interpolate'; 162 | const obj = interpolateObject({x:0, y: 1}, {x: 50, y: 25}); 163 | const halfway = obj(0.5); 164 | // halfway === {x: 25, y: 13} 165 | ``` 166 | 167 | Unmatched properties are used as static templates. 168 | 169 | ```js 170 | const staticObj = interpolateObject({x: 0}, {x: 10, y: 7}); 171 | const quarter = staticObj(0.25); 172 | // quarter === {x: 2.5, y: 7} 173 | ``` 174 | 175 | Properties of the first argument that don't exist in the second argument are also used as a static template 176 | 177 | ```js 178 | const ignoreObj = interpolateObject({x: 0, y: 10}, {x: 100}); 179 | const threeQuarters = ignoreObj(0.75); 180 | // threeQuarters === {x: 75, y: 10} 181 | ``` 182 | -------------------------------------------------------------------------------- /django/urls.md: -------------------------------------------------------------------------------- 1 | # Django URLs 2 | 3 | **Note:** This tutorial was originally written using Python 3.5 and Django 1.9. 4 | 5 | ## `urls.py` 6 | 7 | When Django receives a request, it will iterate over its `urlpatterns` of your URLconf (URL configuation) to match the URL to a view. 8 | 9 | When you call `startproject`, a `urls.py` file will be put in your project directory with some default values. However, the urls file can go anywhere, you just need to specify the location using the `ROOT_URLCONF` variable in your settings module. 10 | 11 | ### `urlpatterns` 12 | 13 | `urlpatterns` is a list of `url` instances. You need to have a list named `urlpatterns` in your urls file. 14 | 15 | ```python 16 | urlpatterns = [ 17 | url('^about$', views.about), 18 | url('^contact$', views.contact) 19 | ] 20 | ``` 21 | 22 | Multiple lists of urls can be joined together. 23 | 24 | ```python 25 | urlspatterns = [ 26 | url('^about$', views.about), 27 | ] 28 | urlpatterns += [ 29 | url('^profile/', include('profile.urls')) 30 | ] 31 | ``` 32 | 33 | ### `url` 34 | 35 | A `url` is an instance of `django.conf.urls.url`. It requires two arguments, a regular expression and a view function. When a url is matched by the regular expression, its view function will be called. 36 | 37 | ```python 38 | url(regex, view) 39 | ``` 40 | 41 | #### `regex` 42 | 43 | The first argument to the url function is a regular expression to describe the URL. 44 | 45 | ```python 46 | url('^profile/', view) 47 | ``` 48 | 49 | The regular expression can include variables that will be used by the view. These are captured using named groups in the regular expression. For example, a profile might include a username. The view function will be passed any matched variables as `kwargs`. 50 | 51 | ```python 52 | # the url /profile/lee will call view(request, username="lee") 53 | urlpatterns = [ 54 | url('^profile/(?P[a-zA-Z0-9_]+)$', view) 55 | ] 56 | ``` 57 | 58 | #### `view` 59 | 60 | The view function will be called when the url is matched against. It will be passed the request and any extra kwargs from the regular expression or options from the url function. 61 | 62 | #### `include` 63 | 64 | Instead of a view function, you can call the `include` function. It takes either a string, which is the location of a urls module, or a list of url instances. This is used for nesting urls. 65 | 66 | ```python 67 | from django.conf.urls import url, include 68 | 69 | #import views 70 | urlpatterns = [ 71 | url('^profile/', include('profile.urls')) 72 | ] 73 | 74 | # nest views 75 | urlpatterns = [ 76 | url('^(?P[a-zA-Z0-9_]+)/', include([ 77 | url('^$', views.index, name='profile-index'), 78 | url('^settings', views.settings, name='profile-settings') 79 | ])) 80 | ] 81 | ``` 82 | 83 | #### `kwargs` 84 | 85 | You can pass additional options to your view with the kwargs dict. Each key in the kwargs will be used as a keyword argument when the view is called. 86 | 87 | ```python 88 | url('^contact$', views.contact, {foo: 'bar'}) 89 | # when the url /contact is requested, 90 | # views.contact(request, foo='bar') will be called 91 | ``` 92 | 93 | #### `name` 94 | 95 | Naming a view makes it convenient to generate a related url by reversing the name (using the `urlresolvers.reverse` function). For example, if you have a url with a name 'contact', in your template you can reference it and the correct url to your contact view will be inserted. This name can also be used in the `get_absolute_url` method of a Model. 96 | 97 | ```python 98 | # urls.py 99 | urlpatterns = [ 100 | url('^contact$', views.contact, name='contact') 101 | ] 102 | ``` 103 | ```html 104 | 105 | Contact 106 | 107 | Contact 108 | ``` 109 | 110 | #### Namespaces 111 | 112 | If you use simple names for your views in your `url` instances, you risk running into name conflicts. In order to help avoid that, views can be namespaced. 113 | 114 | ```python 115 | # vegetable/urls.py 116 | 117 | """ 118 | In order to add a namespace for a set of views, add an 119 | app_name variable to the urls.py module 120 | """ 121 | app_name = 'vegetable' 122 | urlpatterns = [ 123 | url(r'...', detail_view, name='detail') 124 | ] 125 | ``` 126 | 127 | Now, instead of specifying the name of a view, you will specify the namespace and the view name separated by a colon. `reverse('vegetable:detail')` instead of `reverse('detail')`. 128 | 129 | #### 404 130 | 131 | If no urls match the request's URL, a 404 response is returned. 132 | 133 | ## App URLs 134 | 135 | It can be useful to define your URLs on a per-app basis. The easiest way to do this is to add an `urls.py` file to your app's directory. 136 | 137 | ``` 138 | 139 | | - manage.py 140 | | - 141 | + - 142 | | - __init__.py 143 | | - models.py 144 | + - urls.py 145 | ``` 146 | 147 | In your app's urls module, you define urls similarly to the way your project's urls are organized: inside of a list called `urlpatterns`. Doing this also lets you group all of the app's urls under one base pattern. 148 | 149 | 150 | ```python 151 | # project/urls.py 152 | from django.conf.urls import url, include 153 | 154 | urlpatterns = [ 155 | url('^app/', include('app.urls')) 156 | ] 157 | ``` 158 | 159 | ```python 160 | # app/urls.py 161 | from django.conf.urls import url 162 | from .views import * 163 | 164 | urlpatterns = [ 165 | # /app/ 166 | url('^$', index_view, name='app_index'), 167 | # /app/favorites 168 | url('^favorites', favorites_view, name='app_favorites') 169 | ] 170 | ``` 171 | 172 | ## Admin URLs 173 | 174 | It is simple to add the admin related urls to your urlpatterns. You just need to make sure that `django.contrib.admin` is included in your settings' `INSTALLED_APPS`. 175 | 176 | ```python 177 | from django.contrib import admin 178 | 179 | urlpatterns += [ 180 | url(r'^admin/', admin.site.urls), 181 | ] 182 | ``` 183 | 184 | ## Class-based View URLs 185 | 186 | For class based views, call the view's `as_view` method. 187 | 188 | ```python 189 | from your_app.views import YourClassBasedView 190 | 191 | urlpatterns = [ 192 | url('^some_pattern$', YourClassBasedView.as_view()), 193 | ] 194 | ``` 195 | 196 | You can also use static templates with the `TemplateView`. 197 | 198 | ```python 199 | from django.views.generic import TemplateView 200 | 201 | urlpatterns = [ 202 | url('^$' TemplateView.as_view(template_name='index.html')) 203 | ] 204 | ``` 205 | 206 | ## `urlresolvers` 207 | 208 | [documentation](https://docs.djangoproject.com/en/2.0/ref/urlresolvers/) 209 | 210 | Django provides some url resolving functions that help you work with urls in your project. The one that you're most likely to find useful is reverse. 211 | 212 | #### `reverse` 213 | 214 | `reverse` returns the URL that corresponds to a view. The first argument is be either name of the view (as defined in the `url` instance). It can take any args or kwargs that add any additional variables that are used in the URL. The first argument can also be the view function, but this does not work with namespaced views. 215 | 216 | ```python 217 | from django.core.urlresolvers import reverse 218 | reverse('vegetable', pks={pk: self.pk}) 219 | ``` 220 | -------------------------------------------------------------------------------- /django/admin.md: -------------------------------------------------------------------------------- 1 | # Django Admin 2 | 3 | Django provides an admin interface that allows authorizing users to add/edit/remove content. 4 | 5 | ## Admin Views 6 | 7 | For each app that is registered with the admin site, a few views will be available by default. 8 | 9 | * **List Views** list the rows that exist in the table. 10 | * **Changes Views** show the contents of a row in an editable form. 11 | * **Add Views** provide a form to create a new row in a table. 12 | * **Delete Views** make you confirm that you want to delete a row (or rows) before actually doing so. 13 | 14 | ## Settings 15 | 16 | In order to use the admin site, you need to make sure that the admin app and its dependencies are included in the installed apps 17 | 18 | ```python 19 | INSTALLED_APPS = [ 20 | # ..., 21 | 'django.contrib.auth', 22 | 'django.contrib.contenttypes', 23 | 'django.contrib.messages', 24 | 'django.contrib.sessions', 25 | 'django.contrib.admin' 26 | ] 27 | ``` 28 | 29 | In order to make sure all of the necessary data is available to the templates when rendering the admin site, make the auth and messages context processor available. 30 | 31 | ```python 32 | TEMPLATES = [ 33 | { 34 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 35 | 'DIRS': [#...], 36 | 'APP_DIRS': True 37 | 'OPTIONS': { 38 | 'context_processors': [ 39 | # ..., 40 | 'django.contrib.auth.context_processors.auth', 41 | 'django.contrib.messages.context_processors.messages', 42 | ] 43 | } 44 | } 45 | ] 46 | ``` 47 | 48 | The authentication and messages middleware also need to be included. 49 | 50 | ```python 51 | MIDDLEWARE_CLASSES = [ 52 | # ..., 53 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 54 | 'django.contrib.messages.middleware.MessageMiddleware', 55 | ] 56 | ``` 57 | 58 | ## URLs 59 | 60 | To make sure that you can navigate to the admin site, all that you need to do is to include the admin urls in your urlpatterns. 61 | 62 | ```python 63 | from django.contrib import admin 64 | 65 | urlpatterns += [ 66 | url(r'^admin/', admin.site.urls), 67 | ] 68 | ``` 69 | 70 | Typically the path to these urls will begin with /admin, but you can specify anything you want. If you want to "hide" the admin site, you can use an obscure path. This won't prevent someone from navigating to it, but it won't be as obvious. 71 | 72 | ```python 73 | urlpatterns += [ 74 | url(r'^4dm1n/', admin.site.urls), 75 | ] 76 | ``` 77 | 78 | ## Users 79 | 80 | Only a few users should have access to the admin site. Using the built-in User model, these will be users that are either staff or superusers. 81 | 82 | ```bash 83 | python manage.py createsuperuser 84 | ``` 85 | 86 | The user that `createsuperuser` created will be able to log in to the admin site. The superuser will also be able to edit other users to give them access to the admin site. When giving another user access to the admin site, you should almost always give them staff access (or whatever equivalent your user model has) instead of superuser access. 87 | 88 | Superuser access allows the user to view/edit/delete everything, which most (if not all) users should not be able to do. By using the `PermissionsMixin` with your User model (included with default user model), you will have baked in support for giving staff members view/edit/delete permissions for each model instead of across everything like a superuser has. One precaution you should take in giving a staff member access to edit the user model or any permissions is that they could give themselves and other more access than is intended and remove access for people that should have it. 89 | 90 | ## admin.py 91 | 92 | Each of your apps that you wish to be available in the admin site need to be registered with it. This is most commonly done by adding an admin.py file to each app directory. 93 | 94 | [documentation](https://docs.djangoproject.com/en/2.0/ref/contrib/admin/) 95 | 96 | ```python 97 | from django.contrib import admin 98 | 99 | # import any models that you want to register 100 | from .models import Foo, Bar, Baz 101 | 102 | """ 103 | Models need to be registered with the admin site 104 | """ 105 | admin.site.register(Foo) 106 | ``` 107 | 108 | When you register a model with the admin site, you can include a ModelAdmin class that describes what functionality the admin site should provide and what fields of the model should be shown. 109 | 110 | There are a number of options that you can define on the ModelAdmin. 111 | 112 | ```python 113 | class BarAdmin(admin.ModelAdmin): 114 | 115 | """ 116 | actions 117 | an array of actions that are available in a select element 118 | on the list page for a model. All of the list elements 119 | that have been selected will have the action peformed on them. 120 | There is a default delete_selected action to remove any 121 | select elements from the table. You can write other action 122 | functions yourself. 123 | """ 124 | actions = [] 125 | 126 | """ 127 | exclude 128 | a list of fields that should not be shown on the form page 129 | for the model 130 | """ 131 | exclude = ('date_joined',) 132 | 133 | """ 134 | fields 135 | the fields list defines the layout of the forms in the 136 | add and change views 137 | 138 | the fields list can be nested to provide structure within 139 | the view 140 | """ 141 | fields = ('name', 'height', 'weight') 142 | fields = ('name', ('height', weight')) 143 | 144 | """ 145 | fieldsets 146 | fieldsets provide a more fine tuned way to control layout 147 | than the fields option. Each element in the fieldsets tuple 148 | defines a section of the view. The elements are tuples where 149 | the first value is the name of the section (or None) and the 150 | second is an options dict. 151 | """ 152 | fieldsets = ( 153 | ( 154 | None, 155 | { 156 | 'fields': ('name',) 157 | } 158 | ), 159 | ( 160 | 'Attributes', 161 | { 162 | # include any relevant fields in the fields tuple 163 | 'fields': ('height', 'weight'), 164 | # any classes that should be set on the fieldset 165 | 'classes': ('collapse', 'wide'), 166 | # a description of the fieldset 167 | 'description': 'These things are likely to change.' 168 | } 169 | ) 170 | ) 171 | 172 | """ 173 | form 174 | specify the form to use in the add and change views 175 | """ 176 | form = BarForm 177 | 178 | """ 179 | list_display 180 | specify which fields to show in the list view. These values can 181 | also be attributes or methods of the model. 182 | """ 183 | list_display = ('pk', 'name') 184 | 185 | """ 186 | list_filter 187 | fields that the rows in the list view can be filtered on. All of 188 | the fields should have one of these types: BooleanField, CharField, 189 | DateField, DateTimeField, IntegerField, ForeignKey or ManyToManyField 190 | """ 191 | list_filter = ('is_superuser',) 192 | 193 | """ 194 | ordering 195 | specify the order of the rows in the list view 196 | """ 197 | ordering = ['-height'] 198 | 199 | """ 200 | readonly_fields 201 | fields that should be displayed but not editable 202 | """ 203 | readonly_fields = ['pk',] 204 | 205 | 206 | admin.site.register(Bar, BarAdmin) 207 | ``` 208 | 209 | Django also provides a decorator as a shortcut to registering a model 210 | 211 | ```python 212 | @admin.register(Baz) 213 | class BazAdmin(admin.ModelAdmin): 214 | # ... 215 | ``` 216 | -------------------------------------------------------------------------------- /d3/data-binding.md: -------------------------------------------------------------------------------- 1 | # D3 Data Binding 2 | 3 | ## Data Binding 4 | 5 | ### Data 6 | 7 | An array of data can be joined to a selection by calling the `data` function on it. By default, data is bound to the selection by position in the array. In the example, the first `

` element in the `ps` selection will be bound to the `'David'` datum. 8 | 9 | ```js 10 | const names = ['David', 'Susan', 'Monica', 'Gordon', 'Elizabeth', 'William']; 11 | 12 | // create a paragraph for each name 13 | const ps = d3.select('body').selectAll('p'); 14 | // the selection does not have enter/exit functions 15 | // ps.enter === undefined 16 | 17 | // use the position in the array as the key 18 | ps.data(names); 19 | ``` 20 | 21 | While using the position is good enough for simple data binding, this can break down when new data is bound to a selection. If a new datum was added to the beginning of the data, then each element will end up being bound to a new datum. Instead, it is better to pass in a `key` function to identify datum. Then, when updating the data, elements whose key-bound datum is still in the data array will remain bound to the same datum. 22 | 23 | ```js 24 | const names = [ 25 | {name: 'David', age: 37}, 26 | {name: 'Susan', age: 32}, 27 | {name: 'Monica', age: 27} 28 | ]; 29 | const newNames = names.slice(1); 30 | 31 | let ps = d3.select('body').selectAll('p'); 32 | 33 | // default - use the index as the key 34 | ps = ps.data(names); 35 | /* 36 | * p0 - key=0, data={name: 'David', ...} 37 | * p1 - key=1, data={name: 'Susan', ...} 38 | * p2 - key=2, data={name: 'Monica', ...} 39 | */ 40 | ps = ps.data(newNames); 41 | /* 42 | * the first p now has to update with the Susan's data and the third p 43 | * has to be removed 44 | * p0 - key=0, data={name: 'Susan', ...} 45 | * p1 - key=1, data={name: 'Monica', ...} 46 | */ 47 | 48 | // use the name as the key 49 | ps = ps.data(names, function(d) { 50 | return d; 51 | }); 52 | /* 53 | * p0 - key="David", data={name: 'David', ...} 54 | * p1 - key="Susan", data={name: 'Susan', ...} 55 | * p2 - key="Monica", data={name: 'Monica', ...} 56 | */ 57 | ps = ps.data(newNames, function(d) { 58 | return d; 59 | }); 60 | /* 61 | * the first p will be removed and the second and third 'p's will keep 62 | * their data the same 63 | * p1 - key="Susan", data={name: 'Susan', ...} 64 | * p2 - key="Monica", data={name: 'Monica', ...} 65 | */ 66 | ``` 67 | 68 | ### Enter and Exit 69 | 70 | After the data is bound, the selection has enter and exit methods to handle the fact that the number of elements in your selection and the number of datum in your bound data might not line up. To handle new data, you call `enter()` followed by `append(element)` (where element is the type from the selection). To remove elements that no longer have data bound to them, call `exit()` followed by `remove()`. 71 | 72 | ```js 73 | const names = [ 74 | {name: 'David', age: 37}, 75 | {name: 'Susan', age: 32}, 76 | {name: 'Monica', age: 27} 77 | ]; 78 | 79 | // ps is the selection with bound data 80 | const ps = d3.select('body').selectAll('p') 81 | ps.data(names) 82 | 83 | // create 'p' elements for new data 84 | ps.enter().append('p'); 85 | 86 | // remove elements that have no bound data 87 | // this does nothing here, but is important for data updates 88 | ps.exit().remove(); 89 | ``` 90 | 91 | ### Update 92 | 93 | The data for a selection can be updated with a new array of data. When no key is provided, data is overriden based on array index. Call the exit function on the selection to handle elements that no longer have data bound to them (such as if the length of the new data array is shorter than the previous data array). 94 | 95 | ```js 96 | // set new data for names 97 | const names = ['James', 'George', 'John', 'Barack']; 98 | let paragraphs = d3.select('body').selectAll('p.name') 99 | .data(names, function(d) { return d; }); 100 | 101 | // create a

for each datum in names 102 | paragraphs.enter().append('p') 103 | .classed('name', true) 104 | .text(function(d){ return d; }); 105 | 106 | const newNames = ['James', 'John', 'Dwight']; 107 | paragraphs = paragraphs.data(newNames, function(d) { return d; }); 108 | 109 | // EXIT 'George' and 'Barack' 110 | paragraphs.exit().remove(); 111 | 112 | // ENTER 'Dwight' 113 | paragraphs.enter().append('p') 114 | .classed('name', true) 115 | // MERGE the ENTER with the UPDATE 116 | .merge(paragraphs) 117 | .text(function(d){ return d;}); 118 | ``` 119 | 120 | ### Datum 121 | 122 | A datum can be bound to a single element by calling the datum function. This selection does not contain enter/exit functions. 123 | 124 | ```js 125 | const names = ['David', 'Susan', 'Monica', 'Gordon', 'Elizabeth', 'William']; 126 | 127 | // create a paragraph for each name 128 | d3.select('body').select('div') 129 | .datum(names); 130 | ``` 131 | 132 | ### Nested Data 133 | 134 | Data can be passed down from a parent element with bound data 135 | 136 | ```js 137 | const names = ['David', 'Susan', 'Monica', 'Gordon', 'Elizabeth', 'William']; 138 | 139 | // create a paragraph for each name 140 | const people = d3.select('body').append('div') 141 | .datum(names); 142 | 143 | people.selectAll('p') 144 | .data(function(d){ return d;}) 145 | .enter().append('p') 146 | .text(function(d){ return d;}); 147 | 148 | // if the parent data is not an array, it should be wrapped in brackets 149 | // to create a length one array. Otherwise it might not behave as expected. 150 | // eg. .data('string') will have an element for each character 151 | // ('s', 't', 'r', 'i', 'n', and 'g') whereas .data(['string']) will have 152 | // just one element with data 'string' 153 | const agents = d3.select('body').append('div') 154 | .datum('Agent Smith'); 155 | 156 | agents.selectAll('p') 157 | .data(function(d){ return [d];}) 158 | .enter().append('p') 159 | .text(function(d){ return d;}); 160 | ``` 161 | 162 | ## Working with Bound Data 163 | 164 | Once that data has been bound and elements have been created, we have a selection. This allows us to use the selection's method (attr, text, style, property) to modify each element in the selection. 165 | 166 | ```js 167 | // attributes can be set on selections 168 | const peopleData = [{name: 'Joe', age: 31, 'gender': 'male'}, 169 | {name: 'Doug', age: 42, gender: 'male'}, 170 | {name: 'Jill', age: 37, gender: 'female'}]; 171 | 172 | const people = d3.select('body').selectAll('p.person') 173 | .data(peopleData, d => d.name) 174 | .enter().append('p') 175 | .classed('person', true) 176 | .classed('male', d => d.gender === 'male') 177 | .classed('female', d => d.gender === 'female') 178 | .text((d, i) => `Person ${i} is named ${d.name} and is ${d.age}`); 179 | ``` 180 | 181 | ### Loading Data 182 | 183 | Large datasets will most likely needed to be loaded from an external source. The `d3-request` module provides a number of functions for making these requests. The `request` function makes a generic request that you can configure to your liking. If you know the type that the response should be, there are a number of other functions that are pre-configured to make requests and parse the response for you. 184 | 185 | ```js 186 | d3.json('path.json', funtion(error, data){ 187 | if ( error ) { 188 | // handle the error 189 | } 190 | // do something with the loaded data 191 | }); 192 | 193 | d3.text('path.txt', function(error, data){}); 194 | 195 | d3.xml('path.xml', function(error, data){}); 196 | 197 | d3.html('path.html', function(error, data){}); 198 | 199 | d3.csv('path.csv', function(error, data){}); 200 | 201 | d3.tsv('path.tsv', function(error, data){}); 202 | ``` 203 | 204 | For CSV and TSV data, each row will need to be parsed. A function can be passed to those methods, as the second argument to the `d3.csv` and `d3.tsv` functions, which specifies how to parse each row. If no parse function is provided, the first row is assumed to be a header row, and for every other row in the response an object will be created. The keys in each object will be the values in the header row. The values for each key will be the item in the row at the same index as the header key. 205 | 206 | ```csv 207 | name,age 208 | John,31 209 | Carol,49 210 | ``` 211 | 212 | ```js 213 | d3.csv('data.csv', function(error, data) { 214 | // data is the parsed csv file as an array 215 | // data === [{name: 'John', age: 31}, {name: 'Carol', age: 49}] 216 | }); 217 | ``` -------------------------------------------------------------------------------- /d3/layouts.md: -------------------------------------------------------------------------------- 1 | # D3 Layouts 2 | 3 | D3 has a number of layout functions. Layout functions sets up and modifies data so that it can be rendered in different shapes. The layout functions don't do the drawing of the shapes. 4 | 5 | ## Pie Layout 6 | 7 | The pie layout is a part of the `d3-shape` module. 8 | 9 | ```bash 10 | npm install d3-shape 11 | ``` 12 | 13 | A pie layout transforms data by adding start and end angle values to each item in the data array so that it can be rendered as a pie chart. It is used in conjunction with a `d3.arc` (also part of `d3-shapes`) to draw the pieces of the pie. If the arc function is passed an inner radius, the pie chart can be rendered as a donut chart. 14 | 15 | The pie layout has a number of methods that you can use to control how the start and end angles are determined. 16 | 17 | ```js 18 | import { pie } from 'd3-shape'; 19 | 20 | const pie = d3.pie() 21 | // set how to get the value being charted from each datum 22 | .value(function(d){ return d.count; }) 23 | // set the sort function (or null to leave in original order) 24 | .sort(null) 25 | // set the start angle of the first datum in radians (default 0) 26 | .startAngle(Math.PI/2) 27 | // set the end angle in radians (default 2*Math.PI) 28 | .endAngle((5/2)*Math.PI) 29 | // set padding between arcs in radians (default 0) 30 | .padAngle(0); 31 | ``` 32 | 33 | If you want your pie chart to be a full circle, the difference between the start angle and the end angle should be 2π radians. 34 | 35 | Once your pie layout function has been configured, pass it your data array. This will return an array of objects which have the `data` for the corresponding datum as well as `startAngle` and `endAngle` properties. 36 | 37 | ```js 38 | // mock data 39 | const data = [ 40 | {name: 'US', count: 11}, 41 | {name: 'Germany', count: 5}, 42 | {name: 'United Kingdom', count: 7}, 43 | {name: 'Canada', count: 13}, 44 | {name: 'Norway', count: 4} 45 | ]; 46 | 47 | // transform our data to have relevant properties 48 | // for rendering a pie chart 49 | const pieData = pie(data); 50 | ``` 51 | 52 | The pie chart is made up of arcs which are drawn using an `arc` generator. The arc generator can be configured using a number of methods, but the two most important are `outerRadius` and `innerRadius`. The `outerRadius` method defines the radius of the pie chart. The default inner radius is 0, but you can provide a number larger than that using the `innerRadius` method to create a donut chart. 53 | 54 | ```js 55 | import { arc } from 'd3-shape'; 56 | 57 | // create an arc function to calculate angles 58 | // for arcs in the data 59 | const arc = arc() 60 | .outerRadius(100) 61 | .innerRadius(0); 62 | ``` 63 | 64 | Once our arc generator has been configured, create a selection of `<path>` elements and bind it to the data array returned by the pie layout function. The arc generator function is used to create the `d` attribute of each path. 65 | 66 | ```js 67 | svg.selectAll('path.arc') 68 | .data(pieData) 69 | .enter().append('path') 70 | .classed('arc', true) 71 | .attr('d', arc); 72 | ``` 73 | 74 | ## Tree Layout 75 | 76 | The tree layout is part of the `d3-hierarchy` module. 77 | 78 | ```bash 79 | npm install d3-hierarchy 80 | ``` 81 | 82 | Tree layouts can be useful for displaying nested information. In order to create a tree, you will need to have nested data and also use both the `hierarchy` and `tree` functions. 83 | 84 | ### `hierarchy` function 85 | 86 | The `hierarchy` function takes your nested data, creates a `Node` object for each datum, and returns the root `Node`. It can also take a second argument, which is a function that returns a datum's children. It is only necessary to include this if the child datum aren't in the datum's `children` property. 87 | 88 | Each `Node` created by the `hierarchy` function has properties that will be used by the `tree` function to create the layout: 89 | 90 | * `data` - The datum object from your data that is associated with this node. 91 | * `depth` - The depth of the node. The root node has depth 0, its children have depth 1, and so on and so forth. 92 | * `height` - The height of the node is the longest distance from the node to a leaf node (a node with no children). A leaf node has a height of 0. 93 | * `parent` - A reference to the node's parent node. 94 | * `children` - An array of child nodes for a node. This only exists if the node has child nodes. 95 | 96 | ```js 97 | import { hierarchy } from 'd3-hierarchy'; 98 | 99 | const data = { 100 | name: 'parent', 101 | children: [ 102 | {name: 'child1'}, 103 | {name: 'child2'} 104 | ] 105 | }; 106 | 107 | const root = hierarchy(data); 108 | /* 109 | * root === Node(data={name: 'parent'}, ...) 110 | */ 111 | ``` 112 | 113 | The `Node` object has a number of methods. The most important of these for a tree layout are the `descendants` and `links` methods. The `descendants` method returns an array containing all the node and every descendant node. Calling this on the root node will give you an array of every node. The `links` method creates an object for each connection between a parent and a child node in the tree. In each object, the parent node is the `source` and the child node is the `target`. 114 | 115 | 116 | ```js 117 | const descendants = root.descendants(); 118 | /* 119 | * descendants === [Node(...), Node(...), Node(...)] 120 | */ 121 | const links = root.links(); 122 | /* 123 | * links === [ 124 | * { 125 | * source: Node(data={name: 'parent'}, ...) 126 | * target: Node(data={name: 'child1'}, ...) 127 | * }, ... 128 | * ] 129 | */ 130 | ``` 131 | 132 | ### `tree` function 133 | 134 | The `tree` function takes a `Node` object and calculates the position for it and all of its descendant nodes in the tree. It does this by creating a `TreeNode` for each node and then walking through the tree nodes to determine the positioning of each, adding those values to the nodes. 135 | 136 | The tree layout can be controlled using its `separation`, `size`, and `nodeSize` methods. The `separation` method takes a function which returns the amount of separation there should be between two nodes drawn near each other. `size` takes an array containing the width and height of the tree. For a vertical tree (top-down), the array should be `[width, height]`. For a horizontal tree (left-right), the array should be `[height, width]`. `nodeSize` is used to specify the size of each node using an array containing the width and height of each node. For the `size` and `nodeSize` methods, only one can be active on a tree. If both are called, the second one will be the one that is used. 137 | 138 | ```js 139 | import { tree } from 'd3-hierarchy'; 140 | 141 | const tree = tree() 142 | .size([200, 400]); 143 | tree(root); 144 | ``` 145 | 146 | ### Drawing the Tree 147 | 148 | Now that you have your data setup to render a tree, its time to actually draw it. You will need to draw two things: the nodes and the links between the nodes. 149 | 150 | To draw the nodes, call the `descendants` method of the root node to get an array of all of the nodes. 151 | 152 | ```js 153 | const nodes = root.descendants(); 154 | ``` 155 | 156 | Each node has an `x` and `y` property. You can use these to translate each node to the correct position. The `x` and `y` properties don't know the orientation of your tree. If you are using a vertical tree, you can use them as expected, but for a horizontal tree the values will have to be swapped. 157 | 158 | ```js 159 | svg.selectAll('g.node') 160 | .data(root.descendants()) 161 | .enter().append('g') 162 | .classed('node', true) 163 | // for a horizontal tree, d => `translate(${d.y},${d.x}) 164 | .attr('transform', d => `translate(${d.x},${d.y})) 165 | ``` 166 | 167 | To draw the links, call the `links` method of the root node. This will return an array of objects, each one having a `source` and a `target` node. You can then generate a path between the two nodes. 168 | 169 | ```js 170 | function drawLink(node) { 171 | const context = d3.path(); 172 | const { source, target } = node; 173 | context.moveTo(target.y, target.x); 174 | context.bezierCurveTo( 175 | (target.y + source.y)/2, target.x, 176 | (target.y + source.y)/2, source.x, 177 | source.y, source.x 178 | ); 179 | return context.toString(); 180 | } 181 | 182 | svg.selectAll('path') 183 | .data(root.links()) 184 | .enter().append('path') 185 | .style('fill', 'none') 186 | .style('stroke', '#444') 187 | .attr('d', drawLink); 188 | ``` 189 | -------------------------------------------------------------------------------- /redux/redux.md: -------------------------------------------------------------------------------- 1 | # Redux 2 | 3 | Source code on [GitHub](https://github.com/reactjs/redux), documentation at [http://redux.js.org/](http://redux.js.org/). 4 | 5 | * [Overview](#overview) 6 | * [Installation](#installation) 7 | * [Actions](#actions) 8 | * [Reducers](#reducers) 9 | * [Splitting Reducers](#splitting-reducers) 10 | * [Combining Reducers](#combining-reducers) 11 | * [Store](#store) 12 | * [`createStore`](#createstorereducer-initialstate-enhancer) 13 | * [`subscribe`](#storesubscribecallback) 14 | * [`dispatch`](#storedispatchaction) 15 | * [Enhancers](#enhancers) 16 | * [Middleware](#middleware) 17 | * [Example](#example) 18 | 19 | ## Overview 20 | 21 | Redux manages the state of an app using a single store. To modify the state, an action is dispatched to the store and a reducer updates the store based on the type and other values of the action. In order to use the new state, the store can be subscribed to. Subscribing requires a callback function which is called whenever the store updates. 22 | 23 | ## Installation 24 | 25 | ```bash 26 | npm install --save redux 27 | ``` 28 | 29 | ## Actions 30 | 31 | An action is an object that describes how the store should be updated. Actions require a type, which is used by reducers to only update properties for specific actions. Other properties can be included in the action to pass any relevant data to the store. 32 | 33 | 34 | ```js 35 | { 36 | type: "SET_NAME", 37 | name: "Wilbur" 38 | } 39 | ``` 40 | 41 | ## Reducers 42 | 43 | A reducer updates the state of the store. A reducer takes two arguments, the current state and the action that has been dispatched. The current state is manipulated and returns a new state based on the action. 44 | 45 | ```js 46 | function reducer(state, action) { 47 | switch (action.type) { 48 | case "SET_NAME": 49 | return Object.assign({}, state, { 50 | name: action.name 51 | }); 52 | default: 53 | return state; 54 | } 55 | } 56 | ``` 57 | 58 | 59 | #### State 60 | 61 | The first argument to a reducer function is the current state. The state can be of any type, but when the state is an object and you return a new state, the new state should be a new object, not a modified version of the old state object. This should be done so that a comparison between the objects will identify them as being different. 62 | 63 | ```js 64 | // good 65 | return Object.assign({}, oldState, {name: "foo"}); 66 | 67 | //bad 68 | oldState.name = "foo"; 69 | return oldState; 70 | ``` 71 | 72 | #### Action 73 | 74 | The second argument to a reducer function is the action that was dispatched to the store. The current state should be updated based on the type of the action and any additional properties of the action. The easiest way to handle the various action types is by using a switch statement for the known types, and a default case that returns the current state for unknown types. 75 | 76 | 77 | ### Splitting Reducers 78 | 79 | For simple cases a single reducer function will suffice, but when the code starts to get too complicated, it is useful to split the reducer into multiple reducer functions. Those functions can then be combined to create a root reducer using redux's combineReducers function. Each reducer only cares about actions that affect the part of the state that they maintain, returning their current state for all other actions. 80 | 81 | When splitting the reducer, there should be a function for each base property of the state. For example if your state has a "name" property and an "attrs" property, there should be a name reducer and an attrs reducer. While the first argument to the root reducer function is the current state of the store, the first argument passed to the sub-reducer functions is the current value of that property in the store. 82 | 83 | ```js 84 | /* 85 | * store = { 86 | * name: "", 87 | * attrs: "" 88 | * } 89 | */ 90 | 91 | const initialState = { 92 | name: "foo", 93 | attrs: "bar" 94 | }; 95 | 96 | function rootReducer(state=initialState, action) { 97 | return { 98 | name: nameReducer(state.name, action), 99 | attrs: attrReducer(state.attrs, action) 100 | }; 101 | } 102 | 103 | function nameReducer(state="", action) { 104 | switch (action.type) { 105 | case "SET_NAME": 106 | return action.name; 107 | default: 108 | return state; 109 | } 110 | } 111 | 112 | function attrReducer(state={}, action) { 113 | switch (action.type) { 114 | case "ADD_ATTR": 115 | return Object.assign({}, state, { 116 | [attr.key]: action.value 117 | }); 118 | case "REMOVE_ATTR": 119 | const stateCopy = Object.assign({}, state); 120 | delete stateCopy[action.key]; 121 | return stateCopy; 122 | case "GET_ATTRS": 123 | return state; 124 | default: 125 | return state; 126 | } 127 | } 128 | ``` 129 | 130 | ### Combining Reducers 131 | 132 | Instead of writing your own root reducer, you can combine your property specific reducers using redux's `combineReducers` function. 133 | 134 | ```js 135 | import { combineReducers } from "redux"; 136 | import { nameReducer, attrsReducer } from "./reducers"; 137 | 138 | const rootReducer = combineReducers({ 139 | name: nameReducer, 140 | attrs: attrsReducer 141 | }); 142 | ``` 143 | 144 | ## Store 145 | 146 | A store is created by passing it a reducer function. It can also take an optional initialState value and an enhancer function. 147 | 148 | ### `createStore(reducer, initialState, enhancer)` 149 | 150 | `createStore` creates your store. When the store's dispatch method is called, the action is passed to the reducer to update the state. The `initialState` is an optional way to give start values for the state. The enhancer is a function that is used in the creation of the store, for example when applying middleware. 151 | 152 | 153 | ```js 154 | import { createStore } from "redux"; 155 | 156 | const store = createStore(reducer); 157 | ``` 158 | 159 | ### `store.subscribe(callback)` 160 | 161 | `subscribe` takes a callback function and appends it to a list of listeners. Whenever the store is updated (as a result of a dispatch), all of the subscribed callback functions are called. To get the current state, call `store.getState()` in the `store.subscribe` callback. 162 | 163 | 164 | ```js 165 | store.subscribe(() => { 166 | var state = store.getState(); 167 | // ... 168 | }); 169 | 170 | `store.subscribe` returns a function that can be called to unsubscribe from listening to the store. 171 | 172 | ```js 173 | const unsub = store.subscribe(() => { ... }); 174 | // listening for updates 175 | unsub(); 176 | // no longer listening for updates 177 | ``` 178 | 179 | ### `store.dispatch(action)` 180 | 181 | `dispatch` takes an action object and updates the store. The dispatch function verifies that the action is legitimate (is an object with a "type") and calls the store's reducer function (the one used in `createStore`). The arguments passed to the reducer are the current state of the store and the dispatched action. The result returned by the reducer is set as the new state of the store and any subscribed callbacks are then called. 182 | 183 | ```js 184 | store.dispatch({ 185 | type: "SET_NAME", 186 | name: "Wilma" 187 | }); 188 | ``` 189 | 190 | ## Enhancers 191 | 192 | Enhancers "enhance" the Redux store by adding extra functionality to the store when you call createStore. 193 | 194 | 195 | Enhancers are created by composing functions together and passing composed function the createStore method. Read a brief explantion of function composition [here](https://github.com/pshrmn/notes/tree/master/functional-programming/compose.md). 196 | 197 | 198 | ### Middleware 199 | 200 | Middleware enhances the store by enabling you to interact with dispatched actions before they reach the store. To do this, the store's dispatch function is modified to run the middleware functions before the dispatch function is called. 201 | 202 | #### Creating a store with middleware 203 | 204 | ```js 205 | import { applyMiddleware } from "redux"; 206 | 207 | /* 208 | * The functional way of enhancing a store with middleware 209 | */ 210 | const store = applyMiddleware( 211 | middlewareOne, 212 | middlewareTwo 213 | )(createStore)(reducers, initialState); 214 | 215 | /* 216 | * However, this is fairly awkward JavaScript code, so 217 | * you can instead pass the enhancer function returned 218 | * by applyMiddleware directy to createStore 219 | */ 220 | 221 | const store = createStore( 222 | reducers, 223 | initialState, 224 | applyMiddleware( 225 | middlewareOne, 226 | middlewareTwo 227 | ) 228 | ); 229 | ``` 230 | 231 | ## Example 232 | 233 | ```js 234 | // Action Types: "ADD", "SUBTRACT", and "MULTIPLY" 235 | 236 | function reducer(state, action) { 237 | switch(action.type) { 238 | case "ADD": 239 | return state + action.value; 240 | case "SUBTRACT": 241 | return state - action.value; 242 | case "MULTIPLY": 243 | return state * action.value; 244 | default: 245 | return state; 246 | } 247 | } 248 | 249 | var store = Redux.createStore(reducer, 1); 250 | // store = 1 251 | store.dispatch({ 252 | type: "ADD", 253 | value: 4 254 | }); 255 | // store = 5 256 | store.dispatch({ 257 | type: "MULTIPLY", 258 | value: 3 259 | }); 260 | // store = 15 261 | store.dispatch({ 262 | type: "SUBTRACT", 263 | value: 5 264 | }); 265 | // store = 10 266 | 267 | // for unknown types, the current state is returned 268 | store.dispatch({ 269 | type: "UNKNOWN" 270 | }); 271 | // store = 10 272 | ``` 273 | -------------------------------------------------------------------------------- /graphql/graphql.md: -------------------------------------------------------------------------------- 1 | # GraphQL 2 | 3 | http://graphql.org 4 | 5 | ## Operation Types: 6 | 7 | * [`query`](#query) 8 | * [`mutation`](#mutation) 9 | * [`subscription`](#subscription) 10 | 11 | ## Schemas 12 | 13 | ```bash 14 | # this is the root object 15 | { 16 | 17 | } 18 | 19 | # fields can be selected on this 20 | { 21 | dog 22 | } 23 | 24 | # fields of that field can also be selected 25 | { 26 | dog { 27 | name 28 | } 29 | } 30 | ``` 31 | 32 | ### Types 33 | 34 | #### Query and Mutation 35 | 36 | ```bash 37 | # query and mutation types specify fields that can be queried 38 | type Query { 39 | dog(name: String): Dog 40 | } 41 | 42 | type Mutation { 43 | addFriend(name: String, friend: Dog): Dog 44 | } 45 | ``` 46 | 47 | #### Scalar Types 48 | 49 | ```bash 50 | String 51 | Int 52 | Float 53 | Boolean 54 | ID # a special type of String, unique for each value 55 | 56 | # scalars can be added (although not all 57 | # implementations support this) 58 | scalar Date 59 | ``` 60 | 61 | #### Enums 62 | 63 | ```bash 64 | enum Interval { 65 | YEAR 66 | DOGYEAR 67 | DAY 68 | } 69 | ``` 70 | 71 | #### Null 72 | ```bash 73 | # an exclamation point means a field cannot be null 74 | # if the value is null, an execution error will occur 75 | type Dog { 76 | name: String! 77 | } 78 | 79 | # error response 80 | { 81 | errors: [ 82 | { 83 | message: "...", 84 | locations: [ 85 | { line: 1, column: 2 } 86 | ] 87 | } 88 | ] 89 | } 90 | ``` 91 | 92 | #### Objects 93 | 94 | ```bash 95 | # object types describe objects that can be fetched and their fields 96 | type Dog { 97 | name: String! 98 | breed: String! 99 | # fields describe functions. The default is a function with zero 100 | # arguments, which doesn't need to be specified. Default values can be 101 | # provided to make arguments optional. 102 | age(unit: Interval = YEAR): Float! 103 | } 104 | ``` 105 | 106 | #### Lists 107 | 108 | ```bash 109 | type Dog { 110 | # arrays are specified with square brackets 111 | friends: [Dog] 112 | } 113 | 114 | # array can be null, but dogs cannot 115 | friends: [Dog!] 116 | # array cannot be null (will return empty array if no matches) 117 | friends: [Dog]! 118 | ``` 119 | 120 | #### Interface 121 | 122 | ```bash 123 | # interfaces define required fields 124 | interface Animal { 125 | id: ID! 126 | name: String! 127 | } 128 | 129 | # types can implement an interface 130 | type Dog implements Animal { 131 | id: ID! 132 | name: String! 133 | age: Float! 134 | } 135 | 136 | type Cat implements Animal { 137 | id: ID! 138 | name: String! 139 | lives: Int! 140 | } 141 | 142 | # interfaces can be the type for a field 143 | type Query { 144 | GetAnimal($name: String!): Animal 145 | } 146 | 147 | # however, you can only query on fields of the interface 148 | query GetAnimal($name: String!) { 149 | # this will cause an error 150 | age 151 | } 152 | # inline fragments allow you to query type specific fields 153 | ``` 154 | 155 | #### Union 156 | 157 | ```bash 158 | # a union groups types (not interfaces!), but without common fields 159 | union Thing = Dog | Cat | Tree 160 | # this can be useful for tasks that can return multiple types 161 | ``` 162 | 163 | #### Input Types 164 | 165 | ```bash 166 | # input types look like regular types, but are specified 167 | # with the input keyword 168 | input DogInput { 169 | name: String! 170 | breed: String! 171 | } 172 | # input types are passed to mutations 173 | ``` 174 | 175 | ### Resolvers 176 | 177 | ```bash 178 | # resolvers are functions associated with a field 179 | # if a resolver returns a scalar, then it stops. For other 180 | # types, it goes deeper (to that type's fields) 181 | { 182 | dog { 183 | name: String!, # string, stops 184 | friends: [Dog]! # object, so keeps going 185 | } 186 | } 187 | ``` 188 | 189 | ```js 190 | // resolvers receive four arguments: 191 | // 1. obj is the previous object (one level up, not old) 192 | // 2. args are arguments provided in the field's query 193 | // 3. context extra, useful data 194 | // 4. info about query's execution state (use rarely) 195 | { 196 | Query: { 197 | dog(obj, args, context, info) { 198 | return api.getDog(args.id).then(data => { 199 | return new Dog(data); 200 | }); 201 | } 202 | }, 203 | Dog: { 204 | name(obj, args.context) { 205 | return obj.name 206 | } 207 | } 208 | } 209 | ``` 210 | 211 | ## Introspection 212 | 213 | Useful for exploring the GraphQL structure. 214 | 215 | http://graphql.org/learn/introspection/ 216 | 217 | 218 | ## Query 219 | 220 | ```bash 221 | # the query operation type indicates that some gql is a query 222 | query { 223 | ... 224 | } 225 | # this isn't required, but is useful for clarity 226 | ``` 227 | 228 | ```bash 229 | # a query gets data 230 | # the query specifies the shape of the data it wants 231 | query { 232 | dog { 233 | breed 234 | } 235 | } 236 | # the returned object has properties of the same shape 237 | # as the query 238 | { 239 | data: { 240 | dog: { 241 | breed: "corgi" 242 | } 243 | } 244 | } 245 | 246 | query { 247 | # you can also insert comments into a query 248 | dog 249 | } 250 | ``` 251 | 252 | ```bash 253 | # subquery with nested properties 254 | query { 255 | dog: { 256 | name, 257 | friends: { 258 | name 259 | } 260 | } 261 | } 262 | # returns 263 | { 264 | data: { 265 | name: 'Ralph', 266 | friends: [ 267 | { name: 'Spot' }, 268 | { name: 'Fido' } 269 | ] 270 | } 271 | } 272 | ``` 273 | 274 | ### Arguments 275 | 276 | ```bash 277 | query { 278 | dog(id: "k9") { 279 | name, 280 | breed 281 | } 282 | } 283 | # returns dog that matches the id 284 | { 285 | data: { 286 | dog: { 287 | name: 'Sahara' 288 | } 289 | } 290 | } 291 | ``` 292 | 293 | ```bash 294 | # sub-properties can also be queried 295 | query { 296 | dog(id: "k9") { 297 | weight(unit: KG) 298 | } 299 | } 300 | 301 | { 302 | data: [ 303 | dog: { 304 | weight: 23 305 | } 306 | ] 307 | } 308 | ``` 309 | 310 | ### Aliases 311 | 312 | ```bash 313 | # properties can be aliased, which is helpful with duplicates 314 | query { 315 | shortDog: dog(breed: "dachsund") { 316 | name 317 | }, 318 | tallDog: dog(breed: "great dane") { 319 | name 320 | } 321 | } 322 | 323 | { 324 | data: { 325 | shortDog: { 326 | name: 'Goliath' 327 | }, 328 | tallDog: { 329 | name: 'Tiny' 330 | } 331 | } 332 | } 333 | ``` 334 | 335 | ### Fragments 336 | 337 | ```bash 338 | # fragments let you define partial queries, which can 339 | # be included as parts of a larger query 340 | query { 341 | shortDog: dog(breed: 'chihuahua') { 342 | ...quantitativeFields 343 | } 344 | } 345 | 346 | fragment quantitativeFields on Dog { 347 | height 348 | weight 349 | age 350 | } 351 | ``` 352 | 353 | ```bash 354 | # inline fragments can be used to specify properties 355 | # based on a type, which is useful for subtypes 356 | query { 357 | animal { 358 | name 359 | ... on Dog { 360 | age 361 | } 362 | ... on Cat { 363 | lives 364 | } 365 | } 366 | } 367 | 368 | # these can be combined with named fragments, 369 | # which already include an "on" 370 | query { 371 | animal { 372 | name 373 | ...dogProperties 374 | ...catProperties 375 | } 376 | } 377 | 378 | fragment dogProperties on Dog { 379 | age 380 | } 381 | fragment catPropeties on Cat { 382 | lives 383 | } 384 | ``` 385 | 386 | ### Operation Name and Variables 387 | 388 | ```bash 389 | # an operation name is like a function name 390 | query DogData { 391 | dog { 392 | name 393 | breed 394 | age 395 | } 396 | } 397 | 398 | # operations must be named to pass dynamic variables 399 | # variables start with $. 400 | # The type of the variable must be provided. 401 | # The exclamation point indicates this variable is required 402 | query DogData($name: String!) { 403 | dog(name: $name) { 404 | name 405 | breed 406 | age 407 | } 408 | } 409 | 410 | # default variables can be provided 411 | query DogData($name: String = "Terra") { 412 | dog(name: $name) { 413 | ... 414 | } 415 | } 416 | ``` 417 | 418 | ### Meta 419 | 420 | ```bash 421 | query { 422 | dog { 423 | # __typename returns an object's type 424 | # this is useful for queries that can return 425 | # multiple types 426 | __typename 427 | } 428 | } 429 | ``` 430 | 431 | ### Directives 432 | 433 | ```bash 434 | # directives can be used to control whether 435 | # part of a query is included 436 | query DogData($name: String!, $andFriends: Boolean!, $withAge: Boolean!) { 437 | dog(name: $name) { 438 | name 439 | breed 440 | # only @include friends when andFriends is true 441 | friends @include(if: $andFriends) { 442 | name 443 | breed 444 | } 445 | # you can also $skip fields 446 | age @skip(if: $withAge) 447 | } 448 | } 449 | ``` 450 | 451 | #### Custom Directives 452 | 453 | While GraphQL includes the `@skip` and `@include` directives, it is possible to write your own as well. 454 | 455 | The exact implementation varies by GraphQL framework. 456 | 457 | When defining a directive in a schema, it requires a name and what it can be added to (fields, types, etc.). The directive can also take arguments. 458 | 459 | ```bash 460 | directive @yo( 461 | arg: String = "default value" 462 | ) on FIELD_DEFINTION 463 | 464 | query { 465 | dog { 466 | name @yo 467 | } 468 | } 469 | ``` 470 | 471 | 472 | ## Mutations 473 | 474 | ```bash 475 | # while queries read data, 476 | # mutations are used for setting/modifying data 477 | mutation AddFriend($name: String!, $friend: String!) { 478 | addFriend(name: $name, friend: $friend) { 479 | # you can return the results of the mutation 480 | name 481 | friends { 482 | name 483 | } 484 | } 485 | } 486 | 487 | # an operation can contains multiple mutations 488 | # they will be run consecutively, not at the same time 489 | ``` 490 | -------------------------------------------------------------------------------- /django/views.md: -------------------------------------------------------------------------------- 1 | # Django Views 2 | 3 | **Note:** This tutorial was originally written using Python 3.5 and Django 1.9. 4 | 5 | **Note:** If you want to test any of the code out in a Python REPL, make sure to call `python manage.py shell` instead of opening a regular Python REPL so that you know your project's settings have been configured. 6 | 7 | ## About Views 8 | 9 | A view takes an HTTP request and returns a response. 10 | 11 | ```python 12 | from django.http import HttpResponse 13 | 14 | """ 15 | the first argument to a view function is a request object 16 | """ 17 | def view(request): 18 | return HttpResponse("Roger.") 19 | 20 | """ 21 | other arguments can also be passed. This is useful for 22 | any keyword args that are added from the matching url 23 | in your URLconf 24 | """ 25 | 26 | # urls.py 27 | urlpatterns = [ 28 | url('^/car/(?P[0-9]{4,6}$', car_view), 29 | url('^/cars$', cars_view, {'foo': 'bar'}) 30 | ] 31 | 32 | # views.py 33 | 34 | """ 35 | You can match additional arguments directly by name 36 | """ 37 | def car_view(request, pk): 38 | # handle request 39 | 40 | """ 41 | or generically by kwargs 42 | """ 43 | def cars_view(request, **kwargs): 44 | # handle request 45 | ``` 46 | 47 | ## Requests 48 | 49 | [documentation](https://docs.djangoproject.com/en/2.0/ref/request-response/#httprequest-objects") 50 | 51 | A request object has a variety data available as attributes that are useful in creating a response. 52 | 53 | ```python 54 | def view(request): 55 | """ 56 | You can respond to requests based on its method. 57 | The method will always be in all capital letters. 58 | """ 59 | if request.method == 'GET': 60 | # handle the get request 61 | elif request.method == 'POST': 62 | # handle the post request 63 | 64 | """ 65 | Any query parameters will be in a GET QueryDict 66 | https://docs.djangoproject.com/en/2.0/ref/request-response/#querydict-objects 67 | """ 68 | get_params = request.GET 69 | 70 | """ 71 | And any POST parameters (from a POST request) 72 | will be in a POST QueryDict 73 | """ 74 | post_params = request.POST 75 | # the post data can be used to fill in forms 76 | form_data = YourForm(request.POST) 77 | 78 | """ 79 | If the request sent any cookies, they will be 80 | available as a dict. Modifying any cookies has 81 | to be done using the response's set_cookie method 82 | """ 83 | cookies = request.COOKIES 84 | 85 | """ 86 | The headers sent with the request are also 87 | available as a dict 88 | """ 89 | headers = request.META 90 | 91 | """ 92 | Middleware will also add attributes to the request. 93 | """ 94 | 95 | """ 96 | If you are using the SessionMiddleware, 97 | there will be a session attribute dict, which 98 | you can modify to update. 99 | """ 100 | session_id = request.session['id'] 101 | request.session['hakuna'] = 'matata' 102 | 103 | """ 104 | If you are using the AuthenticationMiddleware, 105 | there will be a user attribute. The type of the user 106 | is determined by settings.AUTH_USER_MODEL 107 | """ 108 | user = request.user 109 | # check if the user is logged in using is_authenticated 110 | logged_in = user.is_authenticated() 111 | ``` 112 | 113 | ## Responses 114 | 115 | Your view should return a response to its request. 116 | 117 | ```python 118 | from django.http import HttpResponse 119 | 120 | def view(request): 121 | """ 122 | The most basic way of creating a response is to create an 123 | HttpResponse, passing it a string of the content of the response. 124 | """ 125 | response = HttpResponse("This is my response.") 126 | 127 | 128 | # Headers can be set on a response like keys on a dict. 129 | response['header-field'] = 'header-value' 130 | 131 | """ 132 | Cookies are set using the response's set_cookie method 133 | set_cookie's main arguments are a key and value 134 | https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.HttpResponse.set_cookie 135 | """ 136 | response.set_cookie('best_cookie', 'orange-cranberry') 137 | # you can also delete any cookies by key 138 | response.delete_cookie('worst_cookie') 139 | 140 | return response 141 | ``` 142 | 143 | ### Classes 144 | 145 | Django provides a variety of response classes for handling different types of requests. 146 | 147 | ```python 148 | """ 149 | The most common response is an HttpResponse. It has a status code 150 | of 200 and a content-type derived from settings.DEFAULT_CONTENT_TYPE 151 | It takes a string argument which it will encode to bytes. 152 | """ 153 | http_resp = HttpResponse(';)') 154 | 155 | """ 156 | If you want to respond with JSON, use a JsonResponse 157 | """ 158 | resp = { 159 | 'foo': 'bar' 160 | } 161 | json_resp = JsonResponse(resp) 162 | # the content-type of of the response will be set to application/json 163 | json_resp._headers['content-type'] == ('Content-Type', 'application/json') 164 | ``` 165 | 166 | ### Status Codes 167 | 168 | There are a number of HttpResponse subclasses that are used to handle different response statuses. 169 | 170 | ```python 171 | """ 172 | A regular HttpResponse has a status code of 200. 173 | """ 174 | http_resp = HttpResponse('...') 175 | http_resp.status_code == 200 176 | 177 | """ 178 | Subclasses handle other situations 179 | """ 180 | redirect_resp = HttpResponseRedirect('looks like it\'s over there') 181 | redirect_resp.status_code == 302 182 | 183 | four_oh_four = HttpResponseNotFound('something went wrong') 184 | four_oh_four.status_code == 404 185 | internal_error = HttpResponseServerError('uh oh') 186 | internal_error.status_code == 500 187 | 188 | """ 189 | If something goes wrong in your view and you need to send a 404 response, 190 | you can raise Http404 and Django will handle returning a 404 response for you. 191 | """ 192 | from django.http import Http404 193 | 194 | def failure_view(request): 195 | raise Http404 196 | ``` 197 | 198 | ## Template Responses 199 | 200 | While writing the text to output to an `HttpResponse` is fine for simple responses, it quickly becomes painful when rendering more complex responses. To deal with this, Django provides two classes: `SimpleTemplateResponse` and `TemplateResponse`. 201 | 202 | #### `SimpleTemplateResponse` 203 | 204 | ```python 205 | """ 206 | A SimpleTemplateResponse is a subclass of HttpResponse 207 | """ 208 | from django.template.response import SimpleTemplateResponse 209 | 210 | def view(request) 211 | """ 212 | The first argument is a template object or a string of the 213 | path to the template. 214 | """ 215 | template_path = "path/to/template.html" 216 | """ 217 | It can also take a context dict with the data to be used in 218 | rendering the template. The context is where you would put 219 | any model objects that you have fetched from your database. 220 | """ 221 | context = { 222 | 'method': request.method 223 | } 224 | resp = SimpleTemplateResponse(template_path, context) 225 | return resp.render() 226 | ``` 227 | ```html 228 | 229 | 230 | 231 | You made a {{ method }} request. 232 | 233 | 234 | ``` 235 | 236 | #### `TemplateResponse` 237 | ```python 238 | """ 239 | TemplateResponse is a subclass of SimpleTemplateResponse 240 | that takes a request as its first argument. This will add 241 | request related properties to the context (as configured 242 | by the context_processors of the TEMPLATES variable in 243 | your settings module) 244 | """ 245 | 246 | from django.template.response import TemplateResponse 247 | 248 | def view(request) 249 | return TemplateResponse(request, "path/to/template.html", {}) 250 | ``` 251 | 252 | 253 | ## Shortcuts 254 | 255 | [documentation](https://docs.djangoproject.com/en/2.0/topics/http/shortcuts/) 256 | 257 | Django provides shortcut functions for common tasks related to requests and responses. 258 | 259 | ```python 260 | """ 261 | render takes the request, the location of the template, and an optional 262 | context dict and returns an HttpResponse. 263 | """ 264 | from django.shortcuts import render 265 | 266 | def view(request): 267 | return render(request, 'path/to/template.html', {'context': 'variables'}) 268 | 269 | 270 | """ 271 | redirect returns an HttpResponseRedirect to a different url. 272 | The different url is determined based on the to argument. 273 | """ 274 | from django.shortcuts import redirect 275 | 276 | def from_view(request): 277 | # if to is a model, it uses the model's get_absolute_url method to 278 | # determine the path to redirect to 279 | model_redirect_resp = redirect(to=FooModel) 280 | # if to is a view name, path determined by urlresolver.reverse function 281 | view_redirect_resp = redirect(to='to-view') 282 | # and if to is a string, it simply uses that 283 | str_redirect_resp = redirect('/some/path') 284 | 285 | # passing permanent=True will return an HttpResponsePermanentRedirect 286 | # this response will have a status code of 301 287 | perm_redirect = redirect('/perm/path', permanent=True) 288 | 289 | """ 290 | get_object_or_404 will raise a 404 error if the object you attempt to 291 | get from the database doesn't exist. 292 | """ 293 | from django.shortcuts import get_object_or_404 294 | 295 | from .models import Car 296 | 297 | def car_view(request, car_id): 298 | car = get_object_or_404(Car, car_id) 299 | # an error was raised if a Car with car_id didn't exist 300 | # if you get to here, the car does exist, so proceed 301 | return render(request, 'cars.html', {'car': car}) 302 | 303 | """ 304 | get_list_or_404 is the list equivalent of get_object_or_404 305 | It filters the model based on field lookups and raises an Http404 error 306 | if the returned list is empty 307 | """ 308 | def cars_view(request): 309 | fast_cars = get_list_or_404(Car, top_speed__gte=120) 310 | return render(request, 'cars/cars.html', {'fast_cars': fast_cars}) 311 | ``` 312 | -------------------------------------------------------------------------------- /react-native/react-native.md: -------------------------------------------------------------------------------- 1 | # React Native 2 | 3 | ## Usage 4 | 5 | **Remember to wrap text in a ``** 6 | 7 | ### Styles 8 | 9 | * [view styles](https://facebook.github.io/react-native/docs/view-style-props.html) (``, etc.) 10 | * [text styles](https://facebook.github.io/react-native/docs/text-style-props.html) 11 | * [image styles](https://facebook.github.io/react-native/docs/image-style-props.html) 12 | * [layout props](https://facebook.github.io/react-native/docs/layout-props.html) 13 | * [shadow props](https://facebook.github.io/react-native/docs/shadow-props.html) 14 | 15 | Everything has `relative` position by default. This means that `absolute` positioning will not render an element above its siblings. Instead, any elements that should appear on top of others should be rendered after their siblings. 16 | 17 | ### Networking 18 | 19 | For local networking (when attached to device via USB), use `adb` to let the device access `localhost`. 20 | ```bash 21 | adb reverse tcp:{PORT} tcp:{PORT} 22 | ``` 23 | 24 | ## Components 25 | 26 | ### General 27 | 28 | #### `` 29 | 30 | https://facebook.github.io/react-native/docs/view.html 31 | 32 | The "default" component, like an HTML `

`. 33 | 34 | #### `` 35 | 36 | https://facebook.github.io/react-native/docs/text.html 37 | 38 | All text needs to be wrapped in a ``. 39 | 40 | #### `` 41 | 42 | https://facebook.github.io/react-native/docs/scrollview.html 43 | 44 | A component that makes it easy to scroll through its content. 45 | 46 | #### `` 47 | 48 | https://facebook.github.io/react-native/docs/image.html 49 | 50 | Used to display images, which are provided through the `source` prop. This can be an object with a `uri` property or an import (using `require()`). 51 | 52 | ```jsx 53 | 54 | 55 | ``` 56 | 57 | ### Lists 58 | 59 | #### `` 60 | 61 | https://facebook.github.io/react-native/docs/flatlist.html 62 | 63 | Render a list of items. Setup is a bit convoluted. An array of data is provided through the `data` prop. This will only render components as they are needed (when they should be rendered on screen or are near for scrolling). 64 | 65 | ```jsx 66 | 67 | ``` 68 | 69 | Each item in the array is expected to have a `key` property. If they don't, a `keyExtractor` prop function can be passed to return the key for each item in the array. 70 | 71 | ```jsx 72 | item.id} 75 | /> 76 | ``` 77 | 78 | The `renderItem` prop is a function that returns a React element for item datum. 79 | 80 | ```jsx 81 | {item.value}} 84 | /> 85 | ``` 86 | 87 | #### `` 88 | 89 | https://facebook.github.io/react-native/docs/sectionlist.html 90 | 91 | This is like a ``, but breaks the data into sections, each of which has a title. 92 | 93 | ```jsx 94 | 100 | ``` 101 | 102 | #### `` 103 | 104 | https://facebook.github.io/react-native/docs/refreshcontrol.html 105 | 106 | Used inside of a list (i.e. ``) to load new data. 107 | 108 | ### Input 109 | 110 | ### 111 | 112 | https://facebook.github.io/react-native/docs/textinput.html 113 | 114 | Used to get user input. Use the `onChangeText` to update state when the user types. 115 | 116 | 117 | #### `` 118 | 119 | https://facebook.github.io/react-native/docs/picker.html 120 | 121 | Useful for picking an item from a list, but style customization is minimal. 122 | 123 | #### `` 124 | 125 | https://facebook.github.io/react-native/docs/slider.html 126 | 127 | Pick a value from a range. 128 | 129 | #### `` 130 | 131 | https://facebook.github.io/react-native/docs/switch.html 132 | 133 | Toggle choices 134 | 135 | ### Buttons 136 | 137 | #### ` 369 | 370 | ``` -------------------------------------------------------------------------------- /react-native/animated.md: -------------------------------------------------------------------------------- 1 | # Animated 2 | 3 | * https://facebook.github.io/react-native/docs/animations.html 4 | * https://facebook.github.io/react-native/docs/animated.html#configuring-animations 5 | * https://facebook.github.io/react-native/docs/gesture-responder-system.html 6 | * https://facebook.github.io/react-native/docs/panresponder.html 7 | 8 | ## Values 9 | 10 | Animated values are created using `Animated.value` and `Animated.valueXY` (for vectors). 11 | 12 | ```js 13 | const value = new Animated.value(0); 14 | const vector = new Animated.valueXY({ x: 0, y: 0 }); 15 | ``` 16 | 17 | ### Updating the value 18 | 19 | There are three ways that the value is updated: 20 | 21 | 1. The `value.animate()` method. This method is called internally by the `spring`, `timing`, and `decay` methods to transition between values. It gets passed an `Animation`, which it starts. The `Animation` receives an `onUpdate` callback, which will update the `value`'s value. `onUpdate` is only called for JS animations; native animations will handle updates internally. 22 | 2. The `value.setValue()` method. This can be used to set a value at any time, but is especially convenient for setting a starting value before beginning an animation. 23 | 3. Through a native event emitted listening for `onAnimatedValueUpdate` events. 24 | 25 | ### `value.interpolate()` 26 | 27 | The "real" value of an `Animated.Value` might not be the same as what you want to render. `value.interpolate()` will map a value from an input range to an output range. 28 | 29 | ```js 30 | const v = Animated.value(7); 31 | v.interpolate({ 32 | inputRange: [0, 100], 33 | outputRange: ['0deg', '360deg'] 34 | }); 35 | ``` 36 | 37 | ### Detecting Value Changes 38 | 39 | Animate values have an `addListener` method that can be used to call a function when the value changes. 40 | 41 | ```js 42 | value.addListener(e => this.setState({ x: e.value })); 43 | ``` 44 | 45 | ## Animations 46 | 47 | Animations start with an initial value (a number) and animate to something. This is usually to another value (i.e. to an `Animated.value`), but can also be velocity based. 48 | 49 | Animations can be started and stopped. Once an animation has been stopped, it cannot be restarted. 50 | 51 | **Note: Don't forget to call the `animation.start()`!** 52 | 53 | ### Types 54 | 55 | #### Timing 56 | 57 | `Animated.timing` animates between two values for a given duration (default is `500ms`). 58 | 59 | ```js 60 | Animated.timing(value, { 61 | toValue: 200, 62 | duration: 1000 63 | }).start(); // don't forget to start 64 | ``` 65 | 66 | #### Spring 67 | 68 | `Animated.spring` will overshoot its `toValue` and "spring" back to it (using a [harmonic oscillator](https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator)) 69 | 70 | ```js 71 | Animated.spring(value, { 72 | toValue: 76 73 | }).start(); 74 | ``` 75 | 76 | #### Decay 77 | 78 | `Animated.decay` will animate a value based on a velocity, starting with an initial velocity the animated value keeps changing until the velocity "decays" to zero. 79 | 80 | ```js 81 | Animated.decay(value, { 82 | velocity: { x: 3, y: 2 } // required 83 | }); 84 | ``` 85 | 86 | ## Combining Animations 87 | 88 | * `Animated.sequence` is used to run animations in sequence. 89 | * `Animated.parallel` is used to run multiple animations at the same time. 90 | * `Animated.delay` will start an animation after a delay. 91 | * `Animated.stagger` run in parallel, but staggers the starts. 92 | 93 | These methods will automatically call `start()` and `stop()` on their nested animated. 94 | 95 | ## Components 96 | 97 | Animations are frequently controlled through a component's `style` prop, although other props can be animated too. 98 | 99 | ```jsx 100 | class Bouncer extends React.Component { 101 | constructor(props) { 102 | super(props); 103 | 104 | this.value = Animated.value(1); 105 | } 106 | render() { 107 | const transform = { 108 | scaleX: this.value, 109 | scaleY: this.value 110 | }; 111 | 112 | return ( 113 | 119 | ) 120 | } 121 | } 122 | ``` 123 | 124 | Only components that are setup for animation can be animated. The `Animated` object provides `Animated.View`, `Animated.Text`, `Animated.Image`, and `Animated.ScrollView` components. `Animated.createAnimatedComponent` can be used to create a animatable component (this is how the four provided components are created). 125 | 126 | The above example won't actually animate yet; the animation has to be started. This can be done once a component has mounted, in response to an event, etc. 127 | 128 | ```jsx 129 | class Bouncer extends React.Component { 130 | constructor(props) { 131 | super(props); 132 | 133 | this.value = Animated.value(1); 134 | } 135 | 136 | componentDidMount() { 137 | // scale the value to 3x its original size over 2 seconds 138 | Animated.timing(this.value, { 139 | toValue: 3, 140 | duration: 2000 141 | }).start(); 142 | } 143 | 144 | render() { 145 | const transform = { 146 | scaleX: this.value, 147 | scaleY: this.value 148 | }; 149 | 150 | return ( 151 | 157 | ) 158 | } 159 | } 160 | ``` 161 | 162 | A component created by `Animated.createAnimatedComponent` does a few things to animate. 163 | 164 | **Note:** This is covering JS rendering, not native. 165 | 166 | Before the component mounts and receives new props, the component will create an `AnimatedProps`, which iterates over all of the props and attaches itself to any that are an animated node (i.e. `Animated.value`). When a component updates, any old `AnimatedProps` attached to an animated node are removed. 167 | 168 | Native components have a [`setNativeProps`](https://facebook.github.io/react-native/docs/direct-manipulation.html) method that is used for setting native properties without re-rendering. When a component created with `Animated.createAnimatedComponent` renders, it will use a React `ref` to store a reference to the underlying component (i.e. ``). 169 | 170 | When a value node is updated (i.e. by an animation), it receives a `flush` value. If this is `true`, then the node will call the `update` method of all of its attached children. The update method will call a `AnimatedProps`'s callback method. The behavior of this callback method varies, but for JS rendering, it will call the `ref` component's `setNativeProps` method with the new values. 171 | 172 | ## Native vs JS Animations 173 | 174 | https://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html#caveats 175 | 176 | ## PanResponder 177 | 178 | https://facebook.github.io/react-native/docs/panresponder.html 179 | 180 | The `PanResponder` is a responder that lets you react to streams of events (gestures). (The `` components implement responders, but without gestures.) 181 | 182 | A pan responder is created using `PanResponder.create()`. It receives an object with configuration functions. 183 | 184 | ### Configuration functions 185 | 186 | 187 | ```js 188 | PanResponder.create({ 189 | /* 190 | * There can be multiple pan responders in a page, so a component that implements a 191 | * pan responder needs to specify when it should be active. This may either be done at 192 | * the start of a touch or when a touch moves onto a component (letting it "take over" 193 | * the gesture). 194 | * 195 | * These methods can either be called during an event's capture phase: 196 | */ 197 | onStartShouldSetResponderCapture: () => true, 198 | onMoveShouldSetResponderCapture: () => true, 199 | /* 200 | * 201 | * or during its bubble phase 202 | */ 203 | onStartShouldSetResponder: () => true, 204 | onMoveShouldSetResponder: () => true, 205 | /* 206 | * Typically, you would use the bubble functions, but the capture functions are useful 207 | * if a parent wants to ensure it becomes the pan responder before any children 208 | * can claim the role. 209 | */ 210 | 211 | /* 212 | * While a component may try to become the active pan responder, some other component may 213 | * get the role instead. 214 | */ 215 | 216 | // called when a component successfully becomes the pan responder 217 | onPanResponderGrant: () => {}, 218 | // called when the component doesn't not become the pan responder 219 | onPanResponderReject: () => {}, 220 | 221 | /* 222 | * Once a component becomes a pan responder, there are a few functions that it may call. 223 | */ 224 | 225 | // called at the start of a gesture event 226 | onPanResponderStart: () => {}, 227 | // called every time the gesture moves 228 | onPanResponderMove: () => {}, 229 | // called when the gesture ends (finger leaves devices) 230 | onPanResponderRelease: () => {}, 231 | // called when another component becomes the pan responder. 232 | onPanResponderTerminate: () => {}, 233 | // A component can also allow/prevent itself to be removed as the pan responder 234 | // where returnin gtrue allows and false prevents 235 | onPanResponderTerminationRequest: () => true 236 | }); 237 | ``` 238 | 239 | All of the method properties passed to `PanResponder.create()` will receive two arguments. The first is a React Native event, which provides information about the latest event. The second is a gesture state, which provides information about the accumulated gesture (how far the gesture has moved, the velocity of the gesture, the current position and where the gesture started). 240 | 241 | `onPanResponderMove` can be paired with `Animated.event` to move a component while a gesture is taking place. `Animated.event` will call `setValue` for `Animated.Value`s using event/gesture state values. However, I find this to be a bit convoluted and doing this manually is simple. 242 | 243 | ```js 244 | onPanResponderMove: Animated.event([ 245 | // set values based on the event 246 | { 247 | nativeEvent: { 248 | // keys are Animated.Values 249 | locationX: this.xValue 250 | } 251 | }, 252 | // set values based on the gesture state 253 | { 254 | vx: this.xVelocity 255 | } 256 | ]) 257 | 258 | onPanResponderMove: (event, gesture) { 259 | this.xValue.setValue(event.locationX); 260 | this.xVelocity.setValue(gesture.vx); 261 | } 262 | ``` 263 | -------------------------------------------------------------------------------- /redux/react-redux.md: -------------------------------------------------------------------------------- 1 | # React Redux 2 | 3 | Source code on [GitHub](https://github.com/reactjs/react-redux) 4 | 5 | * [Overview](#overview) 6 | * [Installation](#installation) 7 | * [React](#react) 8 | * [Smart Components](#smart-components) 9 | * [Dumb Components](#dumb-components) 10 | * [React Redux](#react-redux) 11 | * [`Provider`](#provider) 12 | * [`connect`](#connect) 13 | * [Dispatching Actions](#dispatching-actions) 14 | * [Example](#example) 15 | 16 | ## Overview 17 | 18 | React Redux provides a way to use the Redux store with a React app. Select components are wrapped using React Redux to create smart components, which are provided props that correspond to the state of the store as well as a dispatch prop to send actions to the store. 19 | 20 | ## Installation 21 | 22 | ```bash 23 | npm install --save react-redux 24 | ``` 25 | 26 | ## React 27 | 28 | When using Redux with React, your app should have two types of components, smart and dumb. Smart components are aware of Redux and dumb ones are not. 29 | 30 | ### Smart Components 31 | 32 | Smart components are connected to the Redux store. They have access to the state of the store and are able to dispatch actions to the store. 33 | 34 | ```jsx 35 | this.props.dispatch({type: "LOG_CLICK"})}> 36 | {/* child elements */} 37 | 38 | ``` 39 | 40 | ### Dumb Components 41 | 42 | Dumb components are regular React components. Any values from the store and any action dispatching functions have to be passed down to them as props. 43 | 44 | 45 | ```jsx 46 | 47 | {this.props.text} 48 | 49 | ``` 50 | 51 | ## React Redux 52 | 53 | There are two main components that react-redux uses to connect your components to the redux store. They are a Provider component and a connect function which returns a component. 54 | 55 | 56 | ### `Provider` 57 | 58 | ```jsx 59 | 60 | {/* ... */} 61 | 62 | ``` 63 | 64 | The Provider is the root of your components and is reponsible for giving your other components access to the redux store. With that in mind, the Provider requires a store prop be passed to it. The Provider uses the context to make the store available to other components. 65 | 66 | ### `connect` 67 | 68 | ```js 69 | class Component extends React.Component {...} 70 | 71 | export default connect( 72 | mapStateToProps, 73 | mapDispatchToProps, 74 | mergeProps, 75 | options 76 | )(Component); 77 | ``` 78 | 79 | `connect` connects your components to the redux store. It has four optional arguments and returns another function. The returned function takes a component that you want to give access to (specific parts of) the redux store. 80 | 81 | #### `mapStateToProps` 82 | 83 | `mapStateToProps` takes the current state of your store returns an object. The object maps store values to values that will be available as props in your component. 84 | 85 | ```js 86 | connect( 87 | store => { 88 | return { 89 | name: store.name, 90 | url: store.url 91 | }; 92 | } 93 | )(Component); 94 | ``` 95 | 96 | #### `mapDispatchToProps` 97 | 98 | `mapDispatchToProps` gives you a shortcut to dispatching actions from your component to the store. This can either be an object or a function that returns an object. When this is provided to the connect function, the wrapped component won't be provided with a dispatch prop. 99 | 100 | ```js 101 | // your actions 102 | import * as actions from "../actions"; 103 | 104 | // as an object 105 | connect( 106 | null, 107 | { 108 | foo: actions.foo, 109 | bar: actions.bar 110 | } 111 | )(Component); 112 | 113 | // as a function 114 | import { bindActionCreators } from "redux"; 115 | 116 | connect( 117 | null, 118 | dispatch => bindActionCreators(actions, dispatch) 119 | } 120 | )(Component); 121 | ``` 122 | 123 | #### `mergeProps` 124 | 125 | `mergeProps` takes the object returned by `mapStateToProps`, the object returned by `mapDispatchToProps`, and the `props` objected passed to your component, and lets you reconcile values to a final object which will be passed to your component as its props. 126 | 127 | #### `options` 128 | 129 | `options` gives you an opportunity to affect how connect works. The `pure` property (default `true`) adds a shallow comparison to `shouldComponentUpdate` to prevent unnecessary re-renders. The `withRef` property (default `false`) adds a `ref` to the component. 130 | 131 | ### Dispatching Actions 132 | 133 | In order to update the store, you need to dispatch an action to it. Typically you will create functions that return an action object with a type and any other necessary properties. You then need to dispatch the result of those functions to the store. 134 | 135 | Smart components are given the `dispatch` prop which allows them to send these action objects to the Redux store. 136 | 137 | ```js 138 | // the action function 139 | function addNumber(number) { 140 | return { 141 | type: "ADD_NUMBER", 142 | number: number 143 | } 144 | } 145 | 146 | class SmartComponent extends React.Component { 147 | handeEvent(event){ 148 | const number = parseInt(event.target.value, 10); 149 | const action = addNumber(number); 150 | this.props.dispatch(action); 151 | } 152 | 153 | render() { 154 | // ... 155 | } 156 | } 157 | ``` 158 | 159 | #### `bindActionCreators` 160 | 161 | Redux provides a shortcut function called `bindActionCreators` to simplify dispatching actions. `bindActionCreators` maps action functions to an object using the names of the action functions. These functions automatically dispatch the action to the store when the function is called. This is especially useful for passing action functions to dumb components. 162 | 163 | ```jsx 164 | // from "actions" module 165 | const ActionFns = { 166 | addNumber: function(number) { 167 | return { 168 | type: "ADD_NUMBER", 169 | number: number 170 | } 171 | }; 172 | 173 | class SmartComponent extends React.Component { 174 | constructor(props) { 175 | super(props); 176 | this.actions = bindActionCreators(ActionFns, props.dispatch); 177 | } 178 | 179 | render() { 180 | return ( 181 | 182 | 183 | 184 | ); 185 | } 186 | } 187 | 188 | class DumbComponent extend React.Component { 189 | handleEvent(event) { 190 | const number = parseInt(event.target.value, 10); 191 | // 192 | this.props.add(number); 193 | } 194 | 195 | render() { /*... */} 196 | } 197 | ``` 198 | 199 | ## Example 200 | 201 | ### File Layout 202 | 203 | ``` 204 | actions // functions that return actions 205 | +-- index.js 206 | | 207 | components // dumb components 208 | +-- parent.js 209 | +-- child.js 210 | | 211 | constants // reference values, such as the types of actions 212 | +-- ActionTypes.js 213 | | 214 | containers // smart components 215 | +-- app.js 216 | | 217 | reducers // reducers for the store 218 | +-- index.js 219 | ``` 220 | 221 | ### Code 222 | 223 | ```js 224 | // constants/actionTypes.js 225 | export const ADD_ONE = "ADD_ONE"; 226 | export const SUBTRACT_ONE = "SUBTRACT_ONE"; 227 | export const DOUBLE_VALUE = "DOUBLE_VALUE"; 228 | ``` 229 | 230 | ```js 231 | // actions/index.js 232 | import * as types from "../constants/actionTypes"; 233 | 234 | export function addOne() { 235 | return { 236 | type: types.ADD_ONE 237 | }; 238 | } 239 | 240 | export function subtractOne() { 241 | return { 242 | type: types.SUBTRACT_ONE 243 | }; 244 | } 245 | 246 | export function doubleValue() { 247 | return { 248 | type: types.DOUBLE_VALUE 249 | }; 250 | } 251 | ``` 252 | 253 | ```js 254 | // reducers/index.js 255 | import * as types from "../constants/actionTypes"; 256 | 257 | export default function(state, action) { 258 | switch (action.type) { 259 | case types.ADD_ONE: 260 | return state + 1; 261 | case types.SUBTRACT_ONE: 262 | return state - 1; 263 | case types.DOUBLE_VALUE: 264 | return state * 2; 265 | default: 266 | return state; 267 | } 268 | } 269 | ``` 270 | 271 | ```js 272 | // containers/app.js 273 | import React from "react"; 274 | import { bindActionCreators } from "redux"; 275 | import { connect } from "react-redux"; 276 | import * as MathActions from "../actions"; 277 | import Calculator from "../components/calculator" 278 | 279 | class App extends React.Component { 280 | constructor(props) { 281 | super(props); 282 | // bind the action creators to automatically dispatch the actions 283 | this.actions = bindActionCreators(MathActions, props.dispatch); 284 | } 285 | 286 | render() { 287 | const { value } = this.props; 288 | return ( 289 | 290 | ); 291 | } 292 | } 293 | 294 | export default connect( 295 | state => ({ value: state}), 296 | )(App); 297 | ``` 298 | 299 | ```jsx 300 | // components/calculator.js 301 | import React from "react"; 302 | 303 | export default class Calculator extends React.Component { 304 | render() { 305 | const { actions } = this.props; 306 | return ( 307 |
308 |

{this.props.value}

309 | 310 | 311 | 312 |
313 | ); 314 | } 315 | } 316 | ``` 317 | 318 | ```jsx 319 | // index.js 320 | import React from "react"; 321 | import { createStore } from "redux"; 322 | import { Provider } from "react-redux"; 323 | import App from "./containers/app"; 324 | import reducer from './reducers'; 325 | 326 | const store = createStore(reducer, 1); 327 | 328 | React.render( 329 | 330 | 331 | , 332 | document.getElementById("content") 333 | ); 334 | ``` 335 | 336 | The above files can be bundled using webpack 337 | 338 | ```js 339 | // webpack.config.js 340 | module.exports = { 341 | context: __dirname + "/", 342 | entry: "./index.js", 343 | resolve: { 344 | extensions: ["", ".js", ".jsx"] 345 | }, 346 | externals: { 347 | "react": "React" 348 | }, 349 | output: { 350 | path: __dirname + "/public/static/js/", 351 | filename: "bundle.js", 352 | }, 353 | module: { 354 | loaders: [ 355 | { 356 | test: /\.jsx?$/, 357 | exclude: /node_modules/, 358 | loader: "babel-loader" 359 | } 360 | ] 361 | } 362 | } 363 | ``` 364 | 365 | ```bash 366 | # .babelrc 367 | { 368 | "presets": ["es2015", "react"] 369 | } 370 | ``` 371 | -------------------------------------------------------------------------------- /ast/nodes.md: -------------------------------------------------------------------------------- 1 | # Big List of AST Node Types 2 | 3 | These are Acorn node types, since that is what Rollup uses. 4 | 5 | ## Types 6 | 7 | ### ArrayPattern 8 | 9 | #### Example 10 | 11 | ```js 12 | // the array param 13 | function thing([a, b, c]) {} 14 | ``` 15 | 16 | #### Properties 17 | 18 | * elements - array of `Identifier`s and `AssignmentPattern`s 19 | 20 | ### ArrowFunctionExpression 21 | 22 | ##### Example 23 | 24 | ```js 25 | () => {} 26 | ``` 27 | 28 | ##### Properties 29 | 30 | * params - array of `Identifier`s or patterns 31 | * body - `BlockStatement`, expression, or `Literal` 32 | 33 | ### AssignmentExpression 34 | 35 | #### Example 36 | 37 | ```js 38 | x = 5 39 | ``` 40 | 41 | #### Properties 42 | 43 | * left - `Identifier` or pattern 44 | * right - a `Literal` or expression 45 | * operator - `=`, `+=`, etc. 46 | 47 | ### BinaryExpression 48 | 49 | #### Example 50 | 51 | ```js 52 | variable === 24 53 | ``` 54 | 55 | #### Properties 56 | 57 | * left - `Literal` or expression 58 | * right - `Literal` or expression 59 | * operator - `==`, `+`, etc. 60 | 61 | ### BlockStatement 62 | 63 | #### Example 64 | 65 | ```js 66 | { 67 | const x = 'hello'; 68 | console.log(x); 69 | } 70 | ``` 71 | 72 | #### Properties 73 | 74 | * body - array of statements and declarations 75 | 76 | ### CallExpression 77 | 78 | #### Example 79 | 80 | ```js 81 | fn(one, two) 82 | ``` 83 | 84 | #### Properties 85 | 86 | * callee - `Identifier` or `MemberExpression` 87 | * arguments - array of `Literal`s and expressions 88 | 89 | ### CatchClause 90 | 91 | #### Example 92 | 93 | ```js 94 | catch (e) { 95 | ... 96 | } 97 | ``` 98 | 99 | #### Properties 100 | 101 | * param - an `Identifier` 102 | * body - a `BlockStatement` 103 | 104 | ### ClassDeclaration 105 | 106 | #### Example 107 | 108 | ```js 109 | class Thing {} 110 | class AnotherThing extends Thing {} 111 | // the class part of: 112 | export default class {} 113 | ``` 114 | 115 | #### Properties 116 | 117 | * id - an `Identifier` 118 | * superClass - an `Identifier` or null 119 | * body - a `ClassBody` 120 | 121 | ### ClassExpression 122 | 123 | #### Example 124 | 125 | ```js 126 | // the right node of 127 | var x = class Thing {}; 128 | ``` 129 | 130 | #### Properties 131 | 132 | * id - an `Identifier` (optional) 133 | * superClass - an `Identifier` or null 134 | * body - a `ClassBody` 135 | 136 | ### ConditionalExpression 137 | 138 | #### Example 139 | 140 | ```js 141 | test ? consequent : alternate 142 | ``` 143 | 144 | #### Properties 145 | 146 | * test - an expression or `Identifier` 147 | * consequent - an expression or `Literal` 148 | * alternate - an expression or `Literal` 149 | 150 | ### EmptyStatement 151 | 152 | #### Example 153 | 154 | ```js 155 | ; 156 | ``` 157 | 158 | ### ExportAllDeclaration 159 | 160 | #### Example 161 | 162 | ```js 163 | export * from 'another-module'; 164 | ``` 165 | 166 | #### Properties 167 | 168 | * source - a `Literal` string 169 | 170 | ### ExportDefaultDeclaration 171 | 172 | #### Example 173 | 174 | ```js 175 | export default function() {...} 176 | ``` 177 | 178 | #### Properties 179 | 180 | * declaration 181 | 182 | ### ExportNamedDeclaration 183 | 184 | #### Example 185 | 186 | ```js 187 | export const x = 'Exit'; // declaration 188 | 189 | const y = 'Why'; 190 | export { y } // specifiers 191 | ``` 192 | 193 | #### Properties 194 | 195 | * declaration 196 | * specifiers - an array of export specifiers 197 | 198 | **Note:** This is a one or the other type of situation 199 | 200 | ### ExpressionStatement 201 | 202 | #### Example 203 | 204 | ```js 205 | variable = value; 206 | fn(); 207 | ``` 208 | 209 | #### Properties 210 | 211 | * expression 212 | 213 | ### ForInStatement 214 | 215 | #### Example 216 | 217 | ```js 218 | for (let key in obj) { 219 | ... 220 | } 221 | ``` 222 | 223 | #### Properties 224 | 225 | * left - a `VariableDeclaration` 226 | * right - an `Identifier` or expression 227 | * body - a `BlockStatement` 228 | 229 | ### ForOfStatement 230 | 231 | #### Example 232 | 233 | ```js 234 | for (let key of iterable) { 235 | ... 236 | } 237 | ``` 238 | 239 | #### Properties 240 | 241 | * left - a `VariableDeclaration` 242 | * right - an `Identifier` or expression 243 | * body - a `BlockStatement` 244 | 245 | ### ForStatement 246 | 247 | #### Example 248 | 249 | ```js 250 | for (init; test; update) { 251 | ... 252 | } 253 | ``` 254 | 255 | #### Properties 256 | 257 | * init - a `VariableDeclaration` or null 258 | * test - an expression 259 | * update - an expression 260 | * body - a `BlockStatement` or expression 261 | 262 | ### FunctionDeclaration 263 | 264 | #### Example 265 | 266 | ```js 267 | function name(param1, param2) { 268 | ... 269 | } 270 | ``` 271 | 272 | #### Properties 273 | * id - `Identifier` 274 | * generator - boolean 275 | * expression - boolean (???) 276 | * params - an array of `Identifier`s or patterns 277 | * body - a `BlockStatement` 278 | 279 | ### FunctionExpression 280 | 281 | #### Example 282 | 283 | ```js 284 | // the right part of: 285 | let fn = function() {} 286 | ``` 287 | 288 | #### Properties 289 | 290 | * id - `Identifier` or null 291 | * generator - boolean 292 | * expression - boolean (???) 293 | * params - an array of `Identifier`s or patterns 294 | * body - a `BlockStatement` 295 | 296 | ### Identifier 297 | 298 | #### Example 299 | 300 | ```js 301 | // x in: 302 | const x = 'hello'; 303 | ``` 304 | 305 | #### Properties 306 | 307 | * name - a string 308 | 309 | ### IfStatement 310 | 311 | #### Example 312 | 313 | ```js 314 | if (condition) { 315 | ... 316 | } else { 317 | ... 318 | } 319 | ``` 320 | 321 | #### Properties 322 | 323 | * test - an `Identifier` or expression 324 | * consequent - a `BlockStatement` 325 | * alternate - An `IfStatement` or `BlockStatement` 326 | 327 | ### ImportDeclaration 328 | 329 | #### Example 330 | 331 | ```js 332 | import Name from 'module'; 333 | import { One, Two } from 'module'; 334 | import * as Grouped from 'module'; 335 | ``` 336 | 337 | #### Properties 338 | 339 | * specifiers - array of specifiers 340 | * source - `Literal` 341 | 342 | ### Literal 343 | 344 | #### Example 345 | 346 | ```js 347 | // the string in 348 | const x = 'test'; 349 | ``` 350 | 351 | #### Properties 352 | 353 | * value - the literal value 354 | * raw - the value as a string 355 | 356 | ### LogicalExpression 357 | 358 | #### Example 359 | 360 | ```js 361 | thing && thing.property 362 | ``` 363 | 364 | #### Properties 365 | 366 | * left - an `Identifier`, `Literal`, or expression 367 | * operator - '&&' or '||' 368 | * right - an `Identifier`, `Literal`, or expression 369 | 370 | ### MemberExpression 371 | 372 | #### Example 373 | 374 | ```js 375 | object.property 376 | object['property'] 377 | ``` 378 | 379 | #### Properties 380 | 381 | * object - an `Identifier` or expression 382 | * property - an `Identifier` or `Literal` 383 | * computed - boolean 384 | 385 | ### NewExpression 386 | 387 | #### Example 388 | 389 | ```js 390 | new Thing(arg1, arg2) 391 | ``` 392 | 393 | #### Properties 394 | 395 | * callee - `Identifier` or expression 396 | * arguments - an arry of `Identifier`s or expressions 397 | 398 | ### ObjectPattern 399 | 400 | #### Example 401 | 402 | ```js 403 | { one: 1, two: 2 } 404 | ``` 405 | 406 | #### Properties 407 | 408 | * properties - an array of `Property` nodes 409 | 410 | ### Property 411 | 412 | #### Example 413 | 414 | ``` 415 | // any of the lines below (a,b,c, d) 416 | { 417 | a: 'Ayy', 418 | b() {...}, 419 | c, 420 | [d]: 'Dee' 421 | } 422 | ``` 423 | 424 | #### Properties 425 | 426 | * method - true if if `key()` format 427 | * shorthand - true if in `{ key }` format 428 | * computed - true if in `{ [key]: ... }` format 429 | * key - an `Identifier` 430 | * value - a `Literal`, pattern, or expression 431 | * kind - "init"?? 432 | 433 | ### RestElement 434 | 435 | #### Example 436 | 437 | ```js 438 | // the "...rest" element 439 | const [first, ...rest] = [1,2,3,4]; 440 | ``` 441 | 442 | #### Properties 443 | 444 | * argument - an `Identifier` 445 | 446 | ### ReturnStatement 447 | 448 | #### Example 449 | 450 | ```js 451 | return something; 452 | ``` 453 | 454 | #### Properties 455 | 456 | * argument - an `Identifier`, `Literal`, or expression 457 | 458 | ### SwitchStatement 459 | 460 | #### Example 461 | 462 | ```js 463 | switch (discriminant) { 464 | case 1: 465 | ... 466 | break; 467 | case 2: 468 | ... 469 | break; 470 | default: 471 | ... 472 | break; 473 | } 474 | ``` 475 | 476 | #### Properties 477 | 478 | * discriminant - an `Identifier` or expression 479 | * cases - an array of `SwitchCase` nodes 480 | 481 | ### TaggedTemplateExpression 482 | 483 | #### Example 484 | 485 | ```js 486 | tag\`template string\` 487 | ``` 488 | 489 | #### Properties 490 | 491 | * tag - an `Identifier` (possibly a function expression?) 492 | * quasi - a `TemplateLiteral` 493 | 494 | ### TemplateLiteral 495 | 496 | #### Example 497 | 498 | ```js 499 | `I am a template literal` 500 | `Name: ${obj.name}\nAge: ${obj.age}` 501 | ``` 502 | 503 | #### Properties 504 | 505 | * expressions - an array of `Identifier`s or expressions 506 | * quasis - an array of `TemplateElement`s 507 | 508 | ### ThisExpression 509 | 510 | #### Example 511 | 512 | ```js 513 | // just the "this" part of the following lines 514 | this.value = arg => { console.log(arg); }; 515 | this.value('hi!'); 516 | ``` 517 | 518 | ### ThrowStatement 519 | 520 | #### Example 521 | 522 | ```js 523 | throw new Error(); 524 | ``` 525 | 526 | #### Properties 527 | 528 | * argument - an `Identifier` or expression 529 | 530 | ### UnaryExpression 531 | 532 | #### Example 533 | 534 | ```js 535 | +plus 536 | !not 537 | ~flipBits 538 | typeof joke 539 | ``` 540 | 541 | #### Properties 542 | 543 | * operator - `+`, `-`, `!`, `~`, `typeof`, `void`, `delete` 544 | * prefix - true 545 | * argument - an `Identifier` or expression 546 | 547 | ### UpdateExpression 548 | 549 | #### Example 550 | 551 | ```js 552 | variable++ 553 | ``` 554 | 555 | #### Properties 556 | 557 | * operator - '++' or '--' 558 | * prefix - false 559 | * argument - an `Identifier` or expression 560 | 561 | ### VariableDeclaration 562 | 563 | #### Example 564 | 565 | ```js 566 | var one = 1; 567 | let two = 2; 568 | const three = 3, four = 4; 569 | ``` 570 | 571 | #### Properties 572 | 573 | * kind - 'var', 'let', or 'const' 574 | * declarations - an array of `VariableDeclarator`s 575 | 576 | ### VariableDeclarator 577 | 578 | #### Example 579 | 580 | ```js 581 | x = 'exit' 582 | { y, z } = obj 583 | [ a, b ] = arr 584 | ``` 585 | 586 | #### Properties 587 | 588 | * id - an `Identifier` or pattern 589 | * init - a `Literal`, `Identifier`, or expression -------------------------------------------------------------------------------- /d3/svg.md: -------------------------------------------------------------------------------- 1 | # `` Overview 2 | 3 | While D3 can use any type of HTML elements, one of the most common use cases is SVG elements. SVG elements (alongside the `canvas`) are used to make a majority of the D3 chart visualizations. 4 | 5 | **Note:** There are a number of examples in this tutorial that should sample code and an SVG with the rendered contents. However, the sample code is not always the full code used to render, but just includes information being described. You can inspect the SVG using developer tools (right click on the SVG and select Inspect/Inspect Element) to see the full code used to render the SVG. 6 | 7 | ## What is SVG? 8 | 9 | The SVG language is an XML-like markup language, meaning that it defines elements using tags, which can have attributes set for them as well as child elements. These elements are then rendered to create an image. 10 | 11 | The G in SVG is Graphics. SVGs are used to create things that are meant to be rendered as images. In D3, this is often used to make charts. Graphics that need to be scaled to many different sizes, such as logos, are often created using SVGs. 12 | 13 | The V in SVG is Vector. In SVG, everything is defined mathematically. 14 | 15 | For example, you might want to create a graphic with a line segment. There are multiple ways to draw this with SVGs, but the simplest would be to use a `` element. The line segment is defined using two points, for example `<0, 0>` and `<50, 50>`. When the SVG is rendered, a line segment is drawn extending from the first to the second point. 16 | 17 | ```html 18 | 19 | 20 | 21 | ``` 22 | 23 | **Note:** The origin `<0, 0>` for an SVG is in the top left corner. The point at the bottom right corner is ``, based on the width and height of the SVG. 24 | 25 | The S in SVG is Scalable, which references the fact that you can transform SVGs (such as scaling them) without a loss in quality. Because each element in the SVG is defined using numbers, we can use math to modify the elements using transformations. In fact, these can be chained together to create more complex transformations. 26 | 27 | If we want to double the size of the line in our image, we just scale our line segment by multiplying our points by two. We then end up with the new points `<0*2, 0*2> = <0, 0>` and `<50*2, 50*2> = <100, 100>` 28 | 29 | ```html 30 | 31 | 32 | 33 | ``` 34 | 35 | ### Comparison with Raster Graphics 36 | 37 | Raster graphics are graphics where a color value is assigned to every pixel in the graphic. When you take a picture, that is creating a raster graphic. Raster graphics are great for many things, but they don't lend themselves to being transformed like vector graphics do. 38 | 39 | Imagine our line graphic above. In the raster version of the graphic, most of the pixels would be mapped to the white value, but the ones where the line is located would be assigned the black value. What happens when we want to scale the size of the line in the image? A new image would be created and every pixel in the new image would need to be assigned a value based on a corresponding value in the original image, then we would crop the image back down to its original size, which would then contain the properly scaled line. 40 | 41 | This is relatively simple, but what if the image contains a line and a circle and we only want to transform the circle. This is simple using SVGs but would require lots of manual editing in raster graphics. 42 | 43 | ## Defining Elements 44 | 45 | The way that elements should be rendered is defined via attributes. The majority of attributes can be split into two categories: those that define how to render the element geometrically and those that define how to render the element graphically. Given a ``, the geometric attributes would be the location of its center and its radius, while its graphic attributes could describe what its `fill` color is and how thick its `stroke-width` is. Mozilla provides a good reference to which attributes are used to style different elements. 46 | 47 | Below are examples of a few commonly used attributes. 48 | 49 | ### Geometric Attributes: 50 | 51 | ##### `width` 52 | 53 | The width of an element. 54 | ```html 55 | 56 | ``` 57 | 58 | ##### `height` 59 | 60 | The height of an element. 61 | 62 | ```html 63 | 64 | ``` 65 | 66 | ##### `transform` 67 | 68 | The transformations to apply to an element. When chained together, these will be executed from right to left. 69 | 70 | ```html 71 | 72 | ``` 73 | 74 | ##### `x`, `cx`, `x1`, `x2` 75 | 76 | A location on the x-axis. 77 | 78 | ```html 79 | 80 | 81 | 82 | ``` 83 | 84 | ##### `y`, `cy`, `y1`, `y2` 85 | 86 | A location on the y-axis. 87 | 88 | ```html 89 | 90 | 91 | 92 | ``` 93 | 94 | ##### `d` 95 | 96 | A description of how to draw a path. Basically, the string is made up of commands concatenated together. Each command starts with a letter, which specifies the type of the command and then a series of numbers that are used by the command. The numbers are usually either coordinates or lengths, but sometimes also describe other attributes for the command. The command letter can either be upper or lowercase. When uppercase, numbers are coordinates, and when lowercase, numbers are lengths from the current position. For a full explanation of how this works, read the documentation on Mozilla Developer Network. 97 | 98 | ```html 99 | 100 | ``` 101 | 102 | ### Graphic Attributes: 103 | 104 | When drawing an element, the interior of the element is styled by the `fill` and the border of the element is styled by the `stroke`. 105 | 106 | ##### `fill` 107 | 108 | The color that an element should be filled with. This can also be a gradient or a pattern. 109 | 110 | ```html 111 | 112 | ``` 113 | 114 | ##### `stroke` 115 | 116 | The color that should be used on the border of the element. This can also be a gradient or a pattern. 117 | 118 | ```html 119 | 120 | ``` 121 | 122 | ##### `stroke-width` 123 | 124 | How thick a stroke should be. When an element is transformed, the thickness will also be tranformed. SVG 1.2 adds a `vector-effect="non-scaling-stroke"` value which prevents this. 125 | 126 | ```html 127 | 128 | ``` 129 | 130 | ##### `text-anchor` 131 | 132 | The text anchor determines how `` is placed in respect to the element's origin (the coordinates where the text is placed in the SVG). To picture how this is work, imagine a rectangle used to bound the text. When text-anchor is `start`, the left edge of the rectangle is placed at the origin. For `middle`, the rectangle is centered on the origin, with an equal length to the left and right of the point. For `end`, the right edge of the rectangle is placed at the origin. 133 | 134 | ```html 135 | start 136 | middle 137 | end 138 | ``` 139 | 140 | ##### `shape-rendering` 141 | 142 | When an SVG is being rendered, the rendering engine makes decisions about how the pixels for an elemente are mapped to pixels in the image. Sometimes you will want to provide hints to the engine about how certain elements are rendered. The `shape-rendering` attribute lets you do that, either for the entire graphic by adding it to the `` element or for individual elements. 143 | 144 | When the rendering engine is rendering elements, a pixel from an element might not directly align with a single pixel in the image, but instead is split between two pixels. This is anti-aliasing and works well for curves and diagonal lines. However, for vertical and horizontal edges, this can result in a blurry appearance. The `shape-rendering="crispEdges"` value helps combat this because it tells the rendering engine to forces elements to be aligned with a pixel. This should not be used for curved shapes unless you want really ugly shapes. 145 | 146 | ```html 147 | 148 | 149 | ``` 150 | The other possible values for `shape-rendering` are: `auto` (default) which lets the rendering engine do what it thinks is best, `optimizeSpeed` which tells the rendering engine to render as fast as possible, and `geometricPrecision` which tells the rendering engine to make the image as accurate as possible. 151 | 152 | ## Common SVG Elements 153 | 154 | #### `` 155 | 156 | When creating an SVG, the root element is ``. 157 | 158 | ```html 159 | 160 | ``` 161 | 162 | The size of the SVG is controlled using the `width` and `height` attributes. This has to be done through attributes, CSS will not affect the SVG. 163 | 164 | ```html 165 | 166 | ``` 167 | #### `` 168 | 169 | A `` element is used to create a group. The `` element isn't rendered visually, it is just there for grouping/placing its child elements. A `` element can be transformed so that all of its children are rendered based on its location. You can also set style attributes on the `` that will be inherited by its child elements. 170 | 171 | ```html 172 | 173 | 174 | 175 | 176 | ``` 177 | 178 | #### `` 179 | 180 | A `` is a line segment made by connecting two points. 181 | 182 | ```html 183 | 184 | ``` 185 | 186 | #### `` 187 | 188 | A `` draws a rectangle given the coordinates for its top left corner, its width, and its length. 189 | 190 | ```html 191 | 192 | ``` 193 | 194 | #### `` 195 | 196 | A `` is drawn using the coordinates of its center and its radius. 197 | 198 | ```html 199 | 200 | ``` 201 | 202 | #### `` 203 | 204 | Text is added to an SVG using the `` element. 205 | 206 | ```html 207 | This is the text 208 | ``` 209 | 210 | #### `` 211 | 212 | A `` element is used to draw any shape that you want. The shape is defined using the `d` attribute. 213 | 214 | ```html 215 | 216 | ``` 217 | --------------------------------------------------------------------------------