Skip to content

Commit d271ca1

Browse files
authored
Merge pull request #30 from kethinov/1.2.0
1.2.0
2 parents 0ea15de + d29f0ca commit d271ca1

27 files changed

+560
-249
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@
44

55
- Put your changes here...
66

7+
## 1.2.0
8+
9+
- Added view transition support in the default render method.
10+
- Added support for multiple DOM update targets in the default render method.
11+
- Added `req.backButtonPressed` and `req.forwardButtonPressed` to `app`.
12+
- Added classes `backButtonPressed` and `forwardButtonPressed` which will populate on the `<html>` element if either button was pressed.
13+
- Added `[data-page-title]` to the top of the list of accepted query selectors for sourcing content to announce to screen readers when a new page is rendered.
14+
- Added new params to the `res.beforeRender(params)`, `beforeEveryRender(params)`, `res.afterRender(params)`, and `afterEveryRender(params)` methods:
15+
- It now supplies an object with:
16+
- `model`: The data model supplied to the template to be rendered.
17+
- `doc`: The document object created from the template after it is rendered.
18+
- `markup`: The HTML string that will be written to the page.
19+
- `targets`: The list of DOM nodes that will be updated.
20+
- Fixed a bug that caused `postRenderCallbacks` not to function properly.
21+
- Fixed a bug related to script tags from the rendered page being executed unnecessarily.
22+
- Fixed a bug causing unnecessary outlines to appear on page transitions in Safari.
23+
- Updated dependencies.
24+
725
## 1.1.1
826

927
- Fixed crash related to unfinished HTML validation feature.

README.md

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
[![Build Status](https://github.com/rooseveltframework/single-page-express/workflows/CI/badge.svg
44
)](https://github.com/rooseveltframework/single-page-express/actions?query=workflow%3ACI) [![npm](https://img.shields.io/npm/v/single-page-express.svg)](https://www.npmjs.com/package/single-page-express)
55

6-
A client-side implementation of the [Express](http://expressjs.com) route API. It works by hijacking links and form submits, then providing a direct imitation of the Express route API to handle "requests" (click or submit events) and issue "responses" in the form of DOM updates. It will update the browser history to match the route accordingly, update the scroll position appropriately, and there are hooks available for setting animations as well.
6+
A client-side implementation of the [Express](http://expressjs.com) route API. It works by hijacking links and form submits, then providing a direct imitation of the Express route API to handle "requests" (click or submit events) and issue "responses" in the form of DOM updates.
7+
8+
When a `single-page-express` route is triggered, it will update the browser history state to match the route accordingly, update the scroll position appropriately, set focus appropriately, will start a [view transition](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) to animate the DOM updates, and there are hooks available to customize the animations as well. If view transitions are not supported in the browser, the page will transition, but it will not animate unless you set a custom animation using another animation technique.
79

810
This allows you to write isomorphic (aka universal, [amphibious](https://twitter.com/kethinov/status/566896168324825088), etc) router code that can be shared verbatim on the client and the server in your Express application.
911

@@ -46,8 +48,8 @@ The package is distributed with the following builds available:
4648
Then, in your frontend code:
4749

4850
```javascript
49-
const templatingEngine = // define which templating engine to use here
50-
const templates = // load some templates here
51+
const templatingEngine = require('') // define which templating engine to use here
52+
const templates = {} // load some templates here
5153
```
5254

5355
For `templatingEngine`, use something like [teddy](https://github.com/rooseveltframework/teddy), [mustache](https://github.com/janl/mustache.js/), or any other templating system that supports Express and works in the browser.
@@ -191,7 +193,7 @@ There are 3 sample apps you can run to see demos of how `single-page-express` ca
191193
The default render method will handle both full page renders as well as rendering partials:
192194

193195
- If you set `res.title`, the page's title will be updated with its contents. Alternatively, if the template render output contains a `<title>` tag, the page's title will be updated with its contents.
194-
- When the new page is rendered, it will be announced to screen readers. The content to read to screen readers will be sourced from one of the following querySelectors: `h1[aria-label]`, `h1`, or `title` in that order.
196+
- When the new page is rendered, it will be announced to screen readers. The content to read to screen readers will be sourced from one of the following querySelectors: `[data-page-title]`, `h1[aria-label]`, `h1`, or `title` in that order.
195197
- If the template render contains an `<html>` or `<head>` tag and there are new attributes on the `<html>` or `<head>` tags that aren't present in the current document, those attributes will be set on the current document. This behavior is additive or replacement-level only. Attributes cannot be removed simply by omitting them in the template render. If you want to remove an attribute, do it with JavaScript, or set it to a different value in your template render.
196198
- If there are any new children for the `<head>` in the template render, they will be inserted into the current document's `<head>` tag if they are not present already.
197199
- If any of the new tags are `<link>` or `<script>` tags, the DOM update will be delayed until those external files load to prevent a [flash of unstyled content](https://en.wikipedia.org/wiki/Flash_of_unstyled_content).
@@ -204,8 +206,10 @@ The default render method will handle both full page renders as well as renderin
204206
- If you set `res.removeHeadTags`, all tags except `<title>` will be removed from the `<head>` before adding any new ones.
205207
- If you set `res.target`, the DOM will be updated at that spot. `res.target` is a query selector, so an example value you could give it would be `#my-container`. That would replace the contents of the element with the id "my-container" with the output of your rendered template.
206208
- If the output of your rendered template also has an element matching the same query selector, then the contents of that portion of the output will be all that is used to replace the target.
207-
- If you do not set `res.target`, the contents of the `<body>` tag will be replaced with the output of your rendered template.
208-
- If you set `res.focus`, the browser's focus will be set to that element after the page is rendered. If you do not set `res.focus`, then the browser's focus will be set to the first non-inert element in the DOM with the `autofocus` attribute, or, if none are present, it will be set to whatever the target element was set to for the DOM update.
209+
- If you do not set `res.target` and neither `app.defaultTarget` nor `app.defaultTargets` is set, then the contents of the `<body>` tag will be replaced with the output of your rendered template.
210+
- You can also supply an array of query selectors to `res.target`. Elements found matching the query selectors in the array will be replaced with the corresponding query selectors from the rendered template.
211+
- If you set `res.appendTargets = true`, any new target(s) you add will be in addition to whatever is set by `app.defaultTarget` or `app.defaultTargets`.
212+
- If you set `res.focus`, the browser's focus will be set to that element after the page is rendered. If you do not set `res.focus`, then the browser's focus will be set to the first non-inert element in the DOM with the `autofocus` attribute, or, if none are present, it will be set to whatever the target element was set to for the DOM update. If there are multiple targets, the first target on the list will be what is selected.
209213
- There are also hooks for setting animations as well. See "Hooks for setting animations" below.
210214

211215
If this DOM manipulation behavior is undesirable to you, you can supply your own render method instead and do whatever you like. To supply your own render method, see the constructor parameter documentation below.
@@ -229,18 +233,27 @@ These constructor params are only relevant if you're not supplying a custom rend
229233

230234
##### Pre-render
231235

232-
- `beforeEveryRender(model)`: Optionally supply a function to execute just before your template is rendered and written to the DOM. Useful for beginning a CSS transition.
233-
- You can also set `res.beforeRender(model)` on a per request basis.
236+
- `beforeEveryRender(params)`: Optionally supply a function to execute just before your template is rendered and written to the DOM. Useful for beginning a CSS transition.
237+
- You can also set `res.beforeRender(params)` on a per request basis.
238+
- The `params` argument contains:
239+
- `model`: The data model supplied to the template to be rendered.
240+
- `doc`: The document object created from the template after it is rendered.
241+
- `markup`: The HTML string that will be written to the page.
242+
- `targets`: The list of DOM nodes that will be updated.
234243
- `defaultTarget`: Query string representing the default element to target if one is not supplied by `res.target`. Defaults to the `<body>` tag if neither `res.target` or `app.defaultTarget` is supplied.
244+
- `defaultTargets`: Array of query strings representing elements to target for replacement if such an array is not supplied by `res.target`. Elements found matching the query strings in the array will be replaced with the corresponding query string from the rendered template.
235245
- `updateDelay`: How long to wait in milliseconds between rendering the template and writing its contents to the DOM. This is useful to give your animations time to animate if you're using animations. Default: `0`
236246
- You can also set `res.updateDelay` on a per request basis.
237247

238248
##### Post-render
239249

240-
- `afterEveryRender(model)`: Optionally supply a function to execute just after your template is rendered and written to the DOM. Useful for finishing a CSS transition.
241-
242-
- You can also set `res.afterRender(model)` on a per request basis.
243-
250+
- `afterEveryRender(params)`: Optionally supply a function to execute just after your template is rendered and written to the DOM. Useful for finishing a CSS transition.
251+
- You can also set `res.afterRender(params)` on a per request basis.
252+
- The `params` argument contains:
253+
- `model`: The data model supplied to the template rendered.
254+
- `doc`: The document object created from the template after it was rendered.
255+
- `markup`: The HTML string that was written to the page.
256+
- `targets`: The list of DOM nodes that were updated.
244257
- `postRenderCallbacks`: Optionally supply an object with keys that are template names and values that are functions to execute after that template renders. You can also supply `*` as a key to execute a post-render callback after every template render.
245258

246259
### Application object
@@ -254,6 +267,7 @@ When you call the constructor, it will return an `app` object.
254267
- `appVars`: List of variables stored via `app.set()` and retrieved with `app.get()`.
255268
- `beforeEveryRender`: Function to execute before every template render sourced from the constructor params.
256269
- `defaultTarget`: Query string representing the default element to target if one is not supplied by `res.target`.
270+
- `defaultTargets`: Optional array of query strings representing elements to target for replacement if such an array is not supplied by `res.target`.
257271
- `expressVersion`: Which version of the Express API to use for route string parsing sourced from the constructor params.
258272
- `postRenderCallbacks`: List of callback functions to execute after a render event occurs sourced from the constructor params.
259273
- `routes`: List of routes registered with `single-page-express`.
@@ -366,6 +380,8 @@ Likewise all other `req` methods [from the Node.js API](https://nodejs.org/api/h
366380

367381
#### New properties defined by single-page-express
368382

383+
- `req.backButtonPressed`: This will be `true` when the browser back button was pressed. A class `backButtonPressed` will also be added to the `<html>` element.
384+
- `req.forwardButtonPressed`: This will be `true` when the browser forward button was pressed. A class `forwardButtonPressed` will also be added to the `<html>` element.
369385
- `req.singlePageExpress`: This property will always be set to `true`. You can use it to detect whether your route is executing in the `single-page-express` context or not.
370386

371387
### Response object
@@ -380,8 +396,9 @@ Likewise all other `req` methods [from the Node.js API](https://nodejs.org/api/h
380396

381397
##### New properties defined by single-page-express
382398

383-
- `res.afterRender(model)`: If using the default render method, you can set this to a function that will execute after every render.
384-
- `res.beforeRender(model)` If using the default render method, you can set this to a function that will execute before every render.
399+
- `res.addTargets`: If using the default render method, use this variable to set an array of query selectors representing elements to target for replacement in addition to whatever is set by `app.defaultTargets`. Elements found matching the query strings in the array will be replaced with the corresponding query string from the rendered template.
400+
- `res.afterRender(params)`: If using the default render method, you can set this to a function that will execute after every render.
401+
- `res.beforeRender(params)` If using the default render method, you can set this to a function that will execute before every render.
385402
- `res.focus`: If using the default render method, if you set `res.focus`, the browser's focus will be set to that element after the page is rendered. If you do not set `res.focus`, then the browser's focus will be set to the first non-inert element in the DOM with the `autofocus` attribute, or, if none are present, it will be set to whatever the target element was set to for the DOM update.
386403
- `res.removeBaseTags`: If using the default render method, this will remove any `<base>` tags from the page before doing the DOM update.
387404
- `res.removeHeadTags`: If using the default render method, this will remove all children of the `<head>` tag except the title element from the page before doing the DOM update.
@@ -390,7 +407,7 @@ Likewise all other `req` methods [from the Node.js API](https://nodejs.org/api/h
390407
- `res.removeScriptTags`: If using the default render method, this will remove any `<script>` tags from the page before doing the DOM update.
391408
- `res.removeStyleTags`: If using the default render method, this will remove any `<style>` tags from the page before doing the DOM update.
392409
- `res.removeTemplateTags`: If using the default render method, this will remove any `<template>` tags from the page before doing the DOM update.
393-
- `res.target`: If using the default render method, use this variable to set a query selector to determine which element's contents will be replaced by your template render's contents. If none is supplied, the `<body>` tag's contents will be replaced.
410+
- `res.target`: If using the default render method, use this variable to set a query selector or array of query selectors to determine which DOM node contents will be replaced by your template render's contents. If none is supplied, and neither `app.defaultTarget` nor `app.defaultTargets` is set, then the contents of the `<body>` tag will be replaced with the output of your rendered template.
394411
- `res.title`: If using the default render method, use this variable to set a page title for the new render.
395412
- `res.updateDelay`: If using the default render method, use this variable to set a delay in milliseconds before the render occurs. If not using the default render method, this property will still allow you to specify a delay before resetting the scroll position.
396413
- `res.resetScroll`: Purges the memory of the scroll position for this route so that scroll position is reset to the top for this page and all its child containers.

0 commit comments

Comments
 (0)