From 909895913cedda7fe513481bc324b95870ac1824 Mon Sep 17 00:00:00 2001 From: Patrick Brosset Date: Mon, 18 Mar 2024 18:52:29 +0100 Subject: [PATCH 1/2] Make EditContext demo match the MDN tutorial (remove useless `setInterval`, debug mode, reorganize in files, clean up code) (#266) * Removing useless setInterval render * Remove the debug mode * Not needed debug mode visual transition * Split into multiple files * Final changes --- edit-context/html-editor/converter.js | 96 ++++++ edit-context/html-editor/editor.js | 222 ++++++++++++ edit-context/html-editor/index.html | 473 +------------------------- edit-context/html-editor/styles.css | 126 +++++++ 4 files changed, 448 insertions(+), 469 deletions(-) create mode 100644 edit-context/html-editor/converter.js create mode 100644 edit-context/html-editor/editor.js create mode 100644 edit-context/html-editor/styles.css diff --git a/edit-context/html-editor/converter.js b/edit-context/html-editor/converter.js new file mode 100644 index 0000000..4c0b844 --- /dev/null +++ b/edit-context/html-editor/converter.js @@ -0,0 +1,96 @@ +// The EditContext object only knows about a plain text string and about +// character offsets. However, our editor view renders the text by using +// DOM nodes. So we sometimes need to convert between the two. +// This function converts from a DOM selection object to character offsets. +export function fromSelectionToOffsets(selection, editorEl) { + const treeWalker = document.createTreeWalker(editorEl, NodeFilter.SHOW_TEXT); + + let anchorNodeFound = false; + let extentNodeFound = false; + let anchorOffset = 0; + let extentOffset = 0; + + while (treeWalker.nextNode()) { + const node = treeWalker.currentNode; + if (node === selection.anchorNode) { + anchorNodeFound = true; + anchorOffset += selection.anchorOffset; + } + + if (node === selection.extentNode) { + extentNodeFound = true; + extentOffset += selection.extentOffset; + } + + if (!anchorNodeFound) { + anchorOffset += node.textContent.length; + } + if (!extentNodeFound) { + extentOffset += node.textContent.length; + } + } + + if (!anchorNodeFound || !extentNodeFound) { + return null; + } + + return { start: anchorOffset, end: extentOffset }; +} + +// The EditContext object only knows about a plain text string and about +// character offsets. However, our editor view renders the text by using +// DOM nodes. So we sometimes need to convert between the two. +// This function converts character offsets to a DOM selection object. +export function fromOffsetsToSelection(start, end, editorEl) { + const treeWalker = document.createTreeWalker(editorEl, NodeFilter.SHOW_TEXT); + + let offset = 0; + let anchorNode = null; + let anchorOffset = 0; + let extentNode = null; + let extentOffset = 0; + + while (treeWalker.nextNode()) { + const node = treeWalker.currentNode; + + if (!anchorNode && offset + node.textContent.length >= start) { + anchorNode = node; + anchorOffset = start - offset; + } + + if (!extentNode && offset + node.textContent.length >= end) { + extentNode = node; + extentOffset = end - offset; + } + + if (anchorNode && extentNode) { + break; + } + + offset += node.textContent.length; + } + + return { anchorNode, anchorOffset, extentNode, extentOffset }; +} + +// The EditContext object only knows about character offsets. But out editor +// view renders HTML tokens as DOM nodes. This function finds DOM node tokens +// that are in the provided EditContext offset range. +export function fromOffsetsToRenderedTokenNodes(renderedTokens, start, end) { + const tokenNodes = []; + + for (let offset = start; offset < end; offset++) { + const token = renderedTokens.find( + (token) => token.pos <= offset && token.pos + token.value.length > offset + ); + if (token) { + tokenNodes.push({ + node: token.node, + nodeOffset: token.pos, + charOffset: offset, + }); + } + } + + return tokenNodes; +} diff --git a/edit-context/html-editor/editor.js b/edit-context/html-editor/editor.js new file mode 100644 index 0000000..728b89e --- /dev/null +++ b/edit-context/html-editor/editor.js @@ -0,0 +1,222 @@ +import { tokenizeHTML } from "./tokenizer.js"; +import { + fromOffsetsToRenderedTokenNodes, + fromSelectionToOffsets, + fromOffsetsToSelection, +} from "./converter.js"; + +const IS_EDIT_CONTEXT_SUPPORTED = "EditContext" in window; +const IS_CUSTOM_HIGHLIGHT_SUPPORTED = "Highlight" in window; + +// The editor element. +const editorEl = document.getElementById("html-editor"); + +// The current tokens from the html text. +let currentTokens = []; + +// Instances of CSS custom Highlight objects, used to render +// the IME composition text formats. +const imeHighlights = { + "solid-thin": null, + "solid-thick": null, + "dotted-thin": null, + "dotted-thick": null, + "dashed-thin": null, + "dashed-thick": null, + "wavy-thin": null, + "wavy-thick": null, + "squiggle-thin": null, + "squiggle-thick": null, +}; +if (IS_CUSTOM_HIGHLIGHT_SUPPORTED) { + for (const [key, value] of Object.entries(imeHighlights)) { + imeHighlights[key] = new Highlight(); + CSS.highlights.set(`ime-${key}`, imeHighlights[key]); + } +} else { + console.warn( + "Custom highlights are not supported in this browser. IME formats will not be rendered." + ); +} + +(function () { + if (!IS_EDIT_CONTEXT_SUPPORTED) { + editorEl.textContent = + "Sorry, your browser doesn't support the EditContext API. This demo will not work."; + return; + } + + // Instantiate the EditContext object. + const editContext = new EditContext({ + text: "\n \n

Cool Title

\n

hello
How are you? test

\n \n", + }); + + // Attach the EditContext object to the editor element. + // This makes the element focusable and able to receive text input. + editorEl.editContext = editContext; + + // Update the control bounds (i.e. where the editor is on the screen) + // now, and when the window is resized. + // This helps the OS position the IME composition window correctly. + function updateControlBounds() { + const editorBounds = editorEl.getBoundingClientRect(); + editContext.updateControlBounds(editorBounds); + } + updateControlBounds(); + window.addEventListener("resize", updateControlBounds); + + // Update the selection and selection bounds in the EditContext object. + // This helps the OS position the IME composition window correctly. + function updateSelection(start, end) { + editContext.updateSelection(start, end); + // Get the bounds of the selection. + editContext.updateSelectionBounds( + document.getSelection().getRangeAt(0).getBoundingClientRect() + ); + } + + // The render function is used to update the view of the editor. + // The EditContext object is our "model", and the editorEl is our "view". + // The render function's job is to update the view when the model changes. + function render(text, selectionStart, selectionEnd) { + // Empty the editor. We're re-rendering everything. + editorEl.innerHTML = ""; + + // Tokenize the text. + currentTokens = tokenizeHTML(text); + + // Render each token as a DOM node. + for (const token of currentTokens) { + const span = document.createElement("span"); + span.classList.add(`token-${token.type}`); + span.textContent = token.value; + editorEl.appendChild(span); + + // Store the new DOM node as a property of the token + // in the currentTokens array. We will need it again + // later in fromOffsetsToRenderedTokenNodes. + token.node = span; + } + + // Move the selection to the correct location. + // It was lost when we updated the DOM. + // The EditContext API gives us the selection as text offsets. + // Convert it into a DOM selection. + const { anchorNode, anchorOffset, extentNode, extentOffset } = + fromOffsetsToSelection(selectionStart, selectionEnd, editorEl); + document + .getSelection() + .setBaseAndExtent(anchorNode, anchorOffset, extentNode, extentOffset); + } + + // Listen to the EditContext's textupdate event. + // This tells us when text input happens. We use it to re-render the view. + editContext.addEventListener("textupdate", (e) => { + render(editContext.text, e.selectionStart, e.selectionEnd); + }); + + // Visually show when we're composing text, like when using an IME, + // or voice dictation. + editContext.addEventListener("compositionstart", (e) => { + editorEl.classList.add("is-composing"); + }); + editContext.addEventListener("compositionend", (e) => { + editorEl.classList.remove("is-composing"); + }); + + // Update the character bounds when the EditContext needs it. + editContext.addEventListener("characterboundsupdate", (e) => { + const tokenNodes = fromOffsetsToRenderedTokenNodes( + currentTokens, + e.rangeStart, + e.rangeEnd + ); + + const charBounds = tokenNodes.map(({ node, nodeOffset, charOffset }) => { + const range = document.createRange(); + range.setStart(node.firstChild, charOffset - nodeOffset); + range.setEnd(node.firstChild, charOffset - nodeOffset + 1); + return range.getBoundingClientRect(); + }); + + editContext.updateCharacterBounds(e.rangeStart, charBounds); + }); + + // Draw IME composition text formats if needed. + editContext.addEventListener("textformatupdate", (e) => { + const formats = e.getTextFormats(); + + for (const format of formats) { + // Find the DOM selection that corresponds to the format's range. + const selection = fromOffsetsToSelection( + format.rangeStart, + format.rangeEnd, + editorEl + ); + + // Highlight the selection with the right style and thickness. + addHighlight(selection, format.underlineStyle, format.underlineThickness); + } + }); + + function addHighlight(selection, underlineStyle, underlineThickness) { + // Get the right CSS custom Highlight object depending on the + // underline style and thickness. + const highlight = + imeHighlights[ + `${underlineStyle.toLowerCase()}-${underlineThickness.toLowerCase()}` + ]; + + if (highlight) { + // Add a range to the Highlight object. + const range = document.createRange(); + range.setStart(selection.anchorNode, selection.anchorOffset); + range.setEnd(selection.extentNode, selection.extentOffset); + highlight.add(range); + } + } + + // Handle key presses that are not already handled by the EditContext. + editorEl.addEventListener("keydown", (e) => { + const start = Math.min( + editContext.selectionStart, + editContext.selectionEnd + ); + const end = Math.max(editContext.selectionStart, editContext.selectionEnd); + + if (e.key === "Tab") { + e.preventDefault(); + editContext.updateText(start, end, "\t"); + updateSelection(start + 1, start + 1); + render( + editContext.text, + editContext.selectionStart, + editContext.selectionEnd + ); + } else if (e.key === "Enter") { + editContext.updateText(start, end, "\n"); + updateSelection(start + 1, start + 1); + render( + editContext.text, + editContext.selectionStart, + editContext.selectionEnd + ); + } + }); + + // Listen to selectionchange events to let the EditContext know where it is. + document.addEventListener("selectionchange", () => { + const selection = document.getSelection(); + const offsets = fromSelectionToOffsets(selection, editorEl); + if (offsets) { + updateSelection(offsets.start, offsets.end); + } + }); + + // Render the initial view. + render( + editContext.text, + editContext.selectionStart, + editContext.selectionEnd + ); +})(); diff --git a/edit-context/html-editor/index.html b/edit-context/html-editor/index.html index ad54f6c..9fc192a 100644 --- a/edit-context/html-editor/index.html +++ b/edit-context/html-editor/index.html @@ -6,481 +6,16 @@ Edit Context API: HTML editor demo - + + -
- -
- -
- - + + \ No newline at end of file diff --git a/edit-context/html-editor/styles.css b/edit-context/html-editor/styles.css new file mode 100644 index 0000000..b37ac93 --- /dev/null +++ b/edit-context/html-editor/styles.css @@ -0,0 +1,126 @@ +html, +body { + font-size: 0.9rem; + font-family: consolas, monospace; + margin: 0; + height: 100%; + box-sizing: border-box; +} + +body { + padding: 1rem; +} + +#html-editor { + box-sizing: border-box; + width: 100%; + height: 100%; + border-radius: 0.5rem; + padding: 1rem; + overflow: auto; + white-space: pre; + tab-size: 2; + caret-color: red; + background: #000; + line-height: 1.6; + color: red; +} + +#html-editor::selection { + color: white; + background: red; +} + +#html-editor.is-composing { + box-shadow: 0 0 0 0.25rem red; +} + +.token-openTagStart, +.token-openTagEnd, +.token-closeTagStart, +.token-closeTagEnd, +.token-selfClose { + background: rgb(7 53 92); + margin: 0 2px; + color: white; + border-radius: 0.25rem; +} + +.token-equal { + color: white; +} + +.token-tagName { + font-weight: bold; + color: rgb(117, 186, 242); +} + +.token-attributeName { + color: rgb(207, 81, 198); +} + +.token-attributeValue { + font-style: italic; + color: rgb(127 230 127); + border: 1px dashed #8c8c8c; + border-width: 1px 0 1px 0; +} + +.token-quoteStart, +.token-quoteEnd { + font-weight: bold; + color: rgb(127 230 127); + border: 1px solid #8c8c8c; + border-width: 1px 0 1px 1px; + border-radius: 0.25rem 0 0 0.25rem; +} + +.token-quoteEnd { + border-width: 1px 1px 1px 0; + border-radius: 0 0.25rem 0.25rem 0; +} + +.token-text { + color: #6a6a6a; + padding: 0 0.25rem; +} + +::highlight(ime-solid-thin) { + text-decoration: underline 1px; +} + +::highlight(ime-solid-thick) { + text-decoration: underline 2px; +} + +::highlight(ime-dotted-thin) { + text-decoration: underline dotted 1px; +} + +::highlight(ime-dotted-thick) { + text-decoration: underline dotted 2px; +} + +::highlight(ime-dashed-thin) { + text-decoration: underline dashed 1px; +} + +::highlight(ime-dashed-thick) { + text-decoration: underline dashed 2px; +} + +::highlight(ime-wavy-thin) { + text-decoration: underline wavy 1px; +} + +::highlight(ime-wavy-thick) { + text-decoration: underline wavy 2px; +} + +::highlight(ime-squiggle-thin) { + text-decoration: underline wavy 1px; +} + +::highlight(ime-squiggle-thick) { + text-decoration: underline wavy 2px; +} From 6d7115ef281a5576d5cc53532380e845eb1adc07 Mon Sep 17 00:00:00 2001 From: Brian Thomas Smith Date: Fri, 22 Mar 2024 17:07:11 +0100 Subject: [PATCH 2/2] fix(html): Make script elements children of head or body elements (#268) * fix(html): Make script elements children of head or body elements * Apply suggestions from code review Co-authored-by: Vadim Makeev * fix(html): Remove .htmlvalidate.json config --------- Co-authored-by: Vadim Makeev --- abort-api/index.html | 4 +- audiocontext-setsinkid/index.html | 32 +- drag-and-drop/DnD-support.html | 313 ++++++++------- fetch/basic-fetch/index.html | 41 +- fetch/fetch-array-buffer/index.html | 95 ++--- fetch/fetch-json/index.html | 69 ++-- fetch/fetch-request-with-init/index.html | 63 +-- fetch/fetch-request/index.html | 43 +- fetch/fetch-response-clone/index.html | 55 +-- fetch/fetch-response/index.html | 63 +-- fetch/fetch-text/index.html | 59 +-- fetch/fetch-with-init-then-request/index.html | 3 +- fetch/object-fit-gallery-fetch/index.html | 3 +- indexeddb-examples/idbcursor/index.html | 4 +- indexeddb-examples/idbindex/index.html | 6 +- indexeddb-examples/idbkeyrange/index.html | 3 +- insert-adjacent/insertAdjacentElement.html | 195 ++++----- insert-adjacent/insertAdjacentText.html | 110 +++-- matchmedia/index.html | 117 +++--- mediaquerylist/index.html | 118 +++--- pointerevents/Multi-touch_interaction.html | 346 ++++++++-------- pointerevents/Pinch_zoom_gestures.html | 297 +++++++------- touchevents/Multi-touch_interaction.html | 378 +++++++++--------- web-crypto/derive-bits/index.html | 3 +- web-crypto/derive-key/index.html | 3 +- web-crypto/encrypt-decrypt/index.html | 125 ++++-- web-crypto/export-key/index.html | 3 +- web-crypto/import-key/index.html | 119 ++++-- web-crypto/sign-verify/index.html | 26 +- web-crypto/unwrap-key/index.html | 3 +- web-crypto/wrap-key/index.html | 3 +- web-storage/event.html | 34 +- web-storage/index.html | 81 ++-- 33 files changed, 1498 insertions(+), 1319 deletions(-) diff --git a/abort-api/index.html b/abort-api/index.html index fcbde29..42bb80d 100644 --- a/abort-api/index.html +++ b/abort-api/index.html @@ -36,7 +36,7 @@

Simple offline video player

Sintel © copyright Blender Foundation | www.sintel.org.

- + - + diff --git a/audiocontext-setsinkid/index.html b/audiocontext-setsinkid/index.html index 9ab6e04..ebc4817 100644 --- a/audiocontext-setsinkid/index.html +++ b/audiocontext-setsinkid/index.html @@ -1,7 +1,6 @@ - @@ -14,27 +13,22 @@ -

- SetSinkId test example -

- - - -
- -
- - - +

SetSinkId test example

+ + + +
+ + + - diff --git a/drag-and-drop/DnD-support.html b/drag-and-drop/DnD-support.html index e416541..c0db00d 100644 --- a/drag-and-drop/DnD-support.html +++ b/drag-and-drop/DnD-support.html @@ -1,152 +1,177 @@ - -Feature tests for DnD interfaces - - - - -

Log support of DnD objects' methods and properties

-
-

- Select this element, drag it to the Drop Zone and then release the mouse. The console log will contain data about the DnD interfaces supported.

-
-
Drop Zone
- + for (var i = 0; i < properties.length; i++) { + if (dti === undefined) { + console.log("... items." + properties[i] + " = undefined"); + } else { + var supported = properties[i] in dti; + console.log( + "... items." + properties[i] + " = " + (supported ? "Yes" : "No") + ); + } + } + for (var i = 0; i < methods.length; i++) { + if (dti === undefined) { + console.log("... items." + methods[i] + "() = undefined"); + } else { + var supported = typeof dti[methods[i]] == "function"; + console.log( + "... items." + methods[i] + "() = " + (supported ? "Yes" : "No") + ); + } + } + } + function check_DataTransferItemList(dtil) { + // Check the DataTransferItemList object's methods and properties + var properties = ["length"]; + var methods = ["add", "remove", "clear"]; + + console.log("DataTransferItemList ... " + dtil); + + for (var i = 0; i < properties.length; i++) { + if (dtil === undefined) { + console.log("... items." + properties[i] + " = undefined"); + } else { + var supported = properties[i] in dtil; + console.log( + "... items." + properties[i] + " = " + (supported ? "Yes" : "No") + ); + } + } + for (var i = 0; i < methods.length; i++) { + if (dtil === undefined) { + console.log("... items." + methods[i] + "() = undefined"); + } else { + var supported = typeof dtil[methods[i]] == "function"; + console.log( + "... items." + methods[i] + "() = " + (supported ? "Yes" : "No") + ); + } + } + } + function dragstart_handler(ev) { + ev.dataTransfer.dropEffect = "move"; + check_DragEvents(); + var dt = ev.dataTransfer; + if (dt === undefined) { + console.log("DataTransfer is NOT supported."); + } else { + // Make sure there is at least one item + dt.setData("text/plain", "Move this."); + check_DataTransfer(dt); + } + } + function dragover_handler(ev) { + ev.dataTransfer.dropEffect = "move"; + ev.preventDefault(); + } + function drop_handler(ev) { + if (ev.dataTransfer === undefined) { + console.log("DataTransferItem NOT supported."); + console.log("DataTransferItemList NOT supported."); + } else { + var dti = ev.dataTransfer.items; + if (dti === undefined) { + console.log("DataTransferItem NOT supported."); + console.log("DataTransferItemList NOT supported."); + } else { + check_DataTransferItem(dti[0]); + check_DataTransferItemList(dti); + } + } + } + + + +

Log support of DnD objects' methods and properties

+
+

+ Select this element, drag it to the Drop Zone and then release the + mouse. The console log will contain data about the DnD interfaces + supported. +

+
+
+ Drop Zone +
+ diff --git a/fetch/basic-fetch/index.html b/fetch/basic-fetch/index.html index 034973a..ac63092 100644 --- a/fetch/basic-fetch/index.html +++ b/fetch/basic-fetch/index.html @@ -14,25 +14,26 @@

Fetch basic example

- - + + diff --git a/fetch/fetch-array-buffer/index.html b/fetch/fetch-array-buffer/index.html index 6403df0..3466317 100644 --- a/fetch/fetch-array-buffer/index.html +++ b/fetch/fetch-array-buffer/index.html @@ -18,55 +18,58 @@

Fetch arrayBuffer example


-  
-  
+      // dump script to pre element
+      pre.innerHTML = myScript.innerHTML;
+    
+  
 
diff --git a/fetch/fetch-json/index.html b/fetch/fetch-json/index.html
index 801d9df..87cc137 100644
--- a/fetch/fetch-json/index.html
+++ b/fetch/fetch-json/index.html
@@ -13,39 +13,40 @@
   
     

Fetch json example

    + + - diff --git a/fetch/fetch-request-with-init/index.html b/fetch/fetch-request-with-init/index.html index fc03bf8..3074db6 100644 --- a/fetch/fetch-request-with-init/index.html +++ b/fetch/fetch-request-with-init/index.html @@ -13,36 +13,37 @@

    Fetch Request with init example

    + + - diff --git a/fetch/fetch-request/index.html b/fetch/fetch-request/index.html index ab63d5d..40b62f3 100644 --- a/fetch/fetch-request/index.html +++ b/fetch/fetch-request/index.html @@ -11,26 +11,27 @@

    Fetch Request example

    - - + + diff --git a/fetch/fetch-response-clone/index.html b/fetch/fetch-response-clone/index.html index 0d1eede..fd2ee22 100644 --- a/fetch/fetch-response-clone/index.html +++ b/fetch/fetch-response-clone/index.html @@ -21,33 +21,34 @@

    Fetch response clone example

    - - + function useResponse(response, image) { + response + .blob() + .then((myBlob) => { + const objectURL = URL.createObjectURL(myBlob); + image.src = objectURL; + }) + .catch((error) => { + const p = document.createElement("p"); + p.appendChild(document.createTextNode(`Error: ${error}`)); + document.body.insertBefore(p, image); + }); + } + + diff --git a/fetch/fetch-response/index.html b/fetch/fetch-response/index.html index b8ed361..4a88e28 100644 --- a/fetch/fetch-response/index.html +++ b/fetch/fetch-response/index.html @@ -13,38 +13,39 @@

    Fetch basic response example

    - - + const myBlob = new Blob(); + const options = { status: 200, statusText: "SuperSmashingGreat!" }; + const myResponse = new Response(myBlob, options); + + diff --git a/fetch/fetch-text/index.html b/fetch/fetch-text/index.html index df06204..82868c0 100644 --- a/fetch/fetch-text/index.html +++ b/fetch/fetch-text/index.html @@ -18,35 +18,36 @@

    Fetch text example

  • Page 3
  • - - + fetch(myRequest) + .then((response) => { + if (!response.ok) { + throw new Error(`HTTP error, status = ${response.status}`); + } + return response.text(); + }) + .then((text) => { + myArticle.innerText = text; + }) + .catch((error) => { + myArticle.innerText = `Error: ${error.message}`; + }); + } + + diff --git a/fetch/fetch-with-init-then-request/index.html b/fetch/fetch-with-init-then-request/index.html index 56c7e32..43bdbbe 100644 --- a/fetch/fetch-with-init-then-request/index.html +++ b/fetch/fetch-with-init-then-request/index.html @@ -13,7 +13,7 @@

    Fetch with init then Request example

    - + + diff --git a/fetch/object-fit-gallery-fetch/index.html b/fetch/object-fit-gallery-fetch/index.html index eaf23fd..7561f80 100644 --- a/fetch/object-fit-gallery-fetch/index.html +++ b/fetch/object-fit-gallery-fetch/index.html @@ -36,6 +36,7 @@ + + - diff --git a/indexeddb-examples/idbcursor/index.html b/indexeddb-examples/idbcursor/index.html index d8fa6c6..e8ef4fa 100644 --- a/indexeddb-examples/idbcursor/index.html +++ b/indexeddb-examples/idbcursor/index.html @@ -18,7 +18,7 @@

    Basic IDBCursor example — Rush studio albums 74-85

    - - + + diff --git a/indexeddb-examples/idbindex/index.html b/indexeddb-examples/idbindex/index.html index 99fdaef..51f59d1 100644 --- a/indexeddb-examples/idbindex/index.html +++ b/indexeddb-examples/idbindex/index.html @@ -6,8 +6,7 @@ + type="text/css" /> @@ -32,7 +31,6 @@

    Basic IDBIndex example — contacts directory

    Click/focus each table column heading to sort the data by that column.

    + - - diff --git a/indexeddb-examples/idbkeyrange/index.html b/indexeddb-examples/idbkeyrange/index.html index 8ad516f..7a901d3 100644 --- a/indexeddb-examples/idbkeyrange/index.html +++ b/indexeddb-examples/idbkeyrange/index.html @@ -88,7 +88,8 @@

    - + + diff --git a/insert-adjacent/insertAdjacentElement.html b/insert-adjacent/insertAdjacentElement.html index 511908f..45e3095 100644 --- a/insert-adjacent/insertAdjacentElement.html +++ b/insert-adjacent/insertAdjacentElement.html @@ -1,99 +1,102 @@ - - insertAdjacentElement() demo - - - - -

    Click colored box to select it, then use the first two buttons below to insert elements before and after your selection.

    - -
    -
    -
    - - - - - - - - - + + insertAdjacentElement() demo + + + +

    + Click colored box to select it, then use the first two buttons below to + insert elements before and after your selection. +

    + +
    +
    +
    +
    +
    +
    + + + + + + + diff --git a/insert-adjacent/insertAdjacentText.html b/insert-adjacent/insertAdjacentText.html index 86aa5ab..c86aad6 100644 --- a/insert-adjacent/insertAdjacentText.html +++ b/insert-adjacent/insertAdjacentText.html @@ -1,57 +1,55 @@ - + - - insertAdjacentText() demo - - - - -

    Enter some text to add, then use the first two buttons below to insert your text after the existing text.

    - -
    -

    This is my text

    -
    - -
    - - - - - - - - - \ No newline at end of file + + insertAdjacentText() demo + + + +

    + Enter some text to add, then use the first two buttons below to insert + your text after the existing text. +

    + +
    +

    This is my text

    +
    + +
    + + + + + + + diff --git a/matchmedia/index.html b/matchmedia/index.html index fd6c93c..e6dcb19 100644 --- a/matchmedia/index.html +++ b/matchmedia/index.html @@ -1,60 +1,59 @@ - + - - matchMedia test file - - - -

    matchMedia test

    - -

    - - - - - - - \ No newline at end of file + + matchMedia test file + + + +

    matchMedia test

    + +

    + + + + diff --git a/mediaquerylist/index.html b/mediaquerylist/index.html index 0412d23..de4c654 100644 --- a/mediaquerylist/index.html +++ b/mediaquerylist/index.html @@ -1,64 +1,60 @@ - - - - MediaQueryList example - - - -

    matchMedia test

    - -

    - - - - - - + + + + MediaQueryList example + + + +

    matchMedia test

    + +

    + + + diff --git a/pointerevents/Multi-touch_interaction.html b/pointerevents/Multi-touch_interaction.html index bf5fc53..c62d8a1 100644 --- a/pointerevents/Multi-touch_interaction.html +++ b/pointerevents/Multi-touch_interaction.html @@ -1,176 +1,186 @@ - - - -Pointer Events multi-touch interaction - - - - - - -

    Multi-touch interaction

    - -
    Tap, Hold or Swipe me 1
    -
    Tap, Hold or Swipe me 2
    -
    Tap, Hold or Swipe me 3
    - - - - -

    - - + + Pointer Events multi-touch interaction + + + + + + +

    Multi-touch interaction

    + +
    Tap, Hold or Swipe me 1
    +
    Tap, Hold or Swipe me 2
    +
    Tap, Hold or Swipe me 3
    + + + + +

    + + diff --git a/pointerevents/Pinch_zoom_gestures.html b/pointerevents/Pinch_zoom_gestures.html index 635be62..6d4bcce 100644 --- a/pointerevents/Pinch_zoom_gestures.html +++ b/pointerevents/Pinch_zoom_gestures.html @@ -1,148 +1,159 @@ - - - -Pointer Events pinch/zoom example - - - - - - -

    Pointer Event pinch/zoom gesture

    - -
    Touch and Hold with 2 pointers, then pinch in or out.
    - The background color will change to pink if the pinch is opening (Zoom In) - or changes to lightblue if the pinch is closing (Zoom out).
    - - - -

    - - + + Pointer Events pinch/zoom example + + + + + + +

    Pointer Event pinch/zoom gesture

    + +
    + Touch and Hold with 2 pointers, then pinch in or out.
    + The background color will change to pink if the pinch is opening (Zoom In) + or changes to lightblue if the pinch is closing (Zoom out). +
    + + + +

    + + diff --git a/touchevents/Multi-touch_interaction.html b/touchevents/Multi-touch_interaction.html index 5fd6c6e..1541a35 100644 --- a/touchevents/Multi-touch_interaction.html +++ b/touchevents/Multi-touch_interaction.html @@ -1,6 +1,6 @@ - - - -Touch Events tutorial - - - - - - -

    Multi-touch interaction

    - -
    Tap, Hold or Swipe me 1
    -
    Tap, Hold or Swipe me 2
    -
    Tap, Hold or Swipe me 3
    -
    Tap, Hold or Swipe me 4
    - - - - -

    - - + + Touch Events tutorial + + + + + + +

    Multi-touch interaction

    + +
    Tap, Hold or Swipe me 1
    +
    Tap, Hold or Swipe me 2
    +
    Tap, Hold or Swipe me 3
    +
    Tap, Hold or Swipe me 4
    + + + + +

    + + diff --git a/web-crypto/derive-bits/index.html b/web-crypto/derive-bits/index.html index 74fa62e..f7ac07d 100644 --- a/web-crypto/derive-bits/index.html +++ b/web-crypto/derive-bits/index.html @@ -49,7 +49,8 @@

    ECDH

    - + + diff --git a/web-crypto/derive-key/index.html b/web-crypto/derive-key/index.html index 23770a0..ca19acb 100644 --- a/web-crypto/derive-key/index.html +++ b/web-crypto/derive-key/index.html @@ -179,8 +179,9 @@

    HKDF

    - + + diff --git a/web-crypto/encrypt-decrypt/index.html b/web-crypto/encrypt-decrypt/index.html index 25b2a0c..8d8ccc9 100644 --- a/web-crypto/encrypt-decrypt/index.html +++ b/web-crypto/encrypt-decrypt/index.html @@ -1,9 +1,9 @@ - + Web Crypto API example - + @@ -11,29 +11,49 @@

    Web Crypto: encrypt/decrypt

    -

    This page shows the use of the encrypt() and decrypt() functions of the Web Crypto API. It contains four separate examples, one for each encryption algorithm supported:

    +

    + This page shows the use of the encrypt() and + decrypt() functions of the + Web Crypto API. It contains four separate examples, one for each encryption + algorithm supported: +

    • "RSA-OAEP"
    • "AES-CTR"
    • "AES-CBC"
    • "AES-GCM"
    -
    +

    Each example has five components:

    • A text box containing a message to encrypt.
    • A representation of the ciphertext.
    • A box that will contain the decrypted ciphertext.
    • -
    • An "Encrypt" button: this encrypts the text box contents, displays part of the ciphertext, and stores the complete ciphertext.
    • -
    • A "Decrypt" button: this decrypts the ciphertext and writes the result into the "Decrypted" box.
    • +
    • + An "Encrypt" button: this encrypts the text box contents, displays + part of the ciphertext, and stores the complete ciphertext. +
    • +
    • + A "Decrypt" button: this decrypts the ciphertext and writes the + result into the "Decrypted" box. +

    Try it:

    • Press "Encrypt". The ciphertext should appear.
    • -
    • Press "Decrypt". The decrypted text should appear, and match the original message.
    • +
    • + Press "Decrypt". The decrypted text should appear, and match the + original message. +
    • Edit the text box contents.
    • Press "Encrypt" again. A different ciphertext should appear.
    • -
    • Press "Decrypt" again. The new text box contents should appear next to "Decrypted:".
    • +
    • + Press "Decrypt" again. The new text box contents should appear next + to "Decrypted:". +
    @@ -43,13 +63,21 @@

    RSA-OAEP

    - +
    -
    Ciphertext:
    -
    Decrypted:
    - - +
    + Ciphertext: +
    +
    + Decrypted: +
    + +
    @@ -58,13 +86,21 @@

    AES-CTR

    - + +
    +
    + Ciphertext:
    -
    Ciphertext:
    -
    Decrypted:
    - - +
    + Decrypted: +
    + +
    @@ -73,13 +109,21 @@

    AES-CBC

    - + +
    +
    + Ciphertext:
    -
    Ciphertext:
    -
    Decrypted:
    - - +
    + Decrypted: +
    + +
    @@ -88,22 +132,29 @@

    AES-GCM

    - + +
    +
    + Ciphertext:
    -
    Ciphertext:
    -
    Decrypted:
    - - +
    + Decrypted: +
    + +
    - + + + + - - - - diff --git a/web-crypto/export-key/index.html b/web-crypto/export-key/index.html index 21d0fa8..9d0b65a 100644 --- a/web-crypto/export-key/index.html +++ b/web-crypto/export-key/index.html @@ -43,9 +43,10 @@

    Web Crypto: exportKey

    - + + diff --git a/web-crypto/import-key/index.html b/web-crypto/import-key/index.html index 209d39e..b71f0e0 100644 --- a/web-crypto/import-key/index.html +++ b/web-crypto/import-key/index.html @@ -1,9 +1,9 @@ - + Web Crypto API example - + @@ -11,37 +11,63 @@

    Web Crypto: importKey

    -

    This page shows the use of the importKey() function of the Web Crypto API. It contains four separate examples, one for each import format supported:

    +

    + This page shows the use of the importKey() function of + the + Web Crypto API. It contains four separate examples, one for each import format + supported: +

    • Raw
    • PKCS #8
    • SubjectPublicKeyInfo
    • JSON Web Key
    -

    Each example has the same structure: you get a message a button labeled "Import Key".

    -

    If you click "Import Key" then the example imports a particular key:

    +

    + Each example has the same structure: you get a message a button + labeled "Import Key". +

    +

    + If you click "Import Key" then the example imports a particular key: +

    • For "Raw", an AES encryption key.
    • For "PKCS #8", an RSA private signing key.
    • For "SubjectPublicKeyInfo", an RSA public encryption key.
    • For "JSON Web Key", an EC private signing key.
    -

    A new button is then displayed, labeled "Sign" or "Encrypt", depending on the key that was imported. You can click it to use the imported key to perform the appropriate operation and display the result.

    +

    + A new button is then displayed, labeled "Sign" or "Encrypt", depending + on the key that was imported. You can click it to use the imported key + to perform the appropriate operation and display the result. +

    -

    Raw

    - + +
    +
    + Ciphertext:
    -
    Ciphertext:
    - - + +
    @@ -50,12 +76,22 @@

    PKCS #8

    - + +
    +
    + Signature:
    -
    Signature:
    - - + +
    @@ -64,12 +100,22 @@

    SubjectPublicKeyInfo

    - +
    -
    Ciphertext:
    - - +
    + Ciphertext: +
    + +
    @@ -78,21 +124,30 @@

    JSON Web Key

    - + +
    +
    + Signature:
    -
    Signature:
    - - + +
    - + + + + - - - - diff --git a/web-crypto/sign-verify/index.html b/web-crypto/sign-verify/index.html index a184a48..5df26c5 100644 --- a/web-crypto/sign-verify/index.html +++ b/web-crypto/sign-verify/index.html @@ -88,8 +88,7 @@

    RSASSA-PKCS1-v1_5

    id="rsassa-pkcs1-message" name="message" size="25" - value="The owl hoots at midnight" - /> + value="The owl hoots at midnight" />
    Signature: @@ -109,8 +108,7 @@

    RSA-PSS

    id="rsa-pss-message" name="message" size="25" - value="The tiger prowls at dawn" - /> + value="The tiger prowls at dawn" />
    Signature: @@ -130,8 +128,7 @@

    ECDSA

    id="ecdsa-message" name="message" size="25" - value="The eagle flies at twilight" - /> + value="The eagle flies at twilight" />
    Signature: @@ -151,8 +148,7 @@

    HMAC

    id="hmac-message" name="message" size="25" - value="The bunny hops at teatime" - /> + value="The bunny hops at teatime" />
    Signature: @@ -172,8 +168,7 @@

    Ed25519

    id="ed25519-message" name="message" size="25" - value="The lion roars near dawn" - /> + value="The lion roars near dawn" />
    Signature: @@ -184,10 +179,11 @@

    Ed25519

    + + + + + + - - - - - diff --git a/web-crypto/unwrap-key/index.html b/web-crypto/unwrap-key/index.html index 4bbbe9b..28bfe6d 100644 --- a/web-crypto/unwrap-key/index.html +++ b/web-crypto/unwrap-key/index.html @@ -54,7 +54,8 @@

    PKCS #8/RSA-PSS/AES-GCM

    - + + diff --git a/web-crypto/wrap-key/index.html b/web-crypto/wrap-key/index.html index f16d25a..b84fb8a 100644 --- a/web-crypto/wrap-key/index.html +++ b/web-crypto/wrap-key/index.html @@ -44,9 +44,10 @@

    Web Crypto: wrapKey

    - + + diff --git a/web-storage/event.html b/web-storage/event.html index 253bf58..24eb7e8 100644 --- a/web-storage/event.html +++ b/web-storage/event.html @@ -1,31 +1,29 @@ - - - + + + Web Storage API storage event output - + -
    -

    Event output

    +
    +

    Event output

    -
      -
    • Key:
    • -
    • Old value:
    • -
    • New value:
    • -
    • URL:
    • -
    • Storage area:
    • -
    +
      +
    • Key:
    • +
    • Old value:
    • +
    • New value:
    • +
    • URL:
    • +
    • Storage area:
    • +
    -

    Go back to the main example page.

    - - -
    +

    Go back to the main example page.

    +
    + - diff --git a/web-storage/index.html b/web-storage/index.html index 9733dbf..005da49 100644 --- a/web-storage/index.html +++ b/web-storage/index.html @@ -1,48 +1,61 @@ - - - + + + Web Storage API example - + -
    -

    Web storage

    +
    +

    Web storage

    -

    This example is designed to demonstrate usage of the W3C Web Storage API. It should work as far back as IE8. Choose custom background colours, logos and fonts from the below drop down menus, then try closing and reopening the page — you will find that your choices are remembered, as they are stored using Web Storage. You can also visit the storage event output (opens in new tab). Open this, change some values in the index page, then look at the events page — you'll see the storage changes reported.

    +

    + This example is designed to demonstrate usage of the + W3C Web Storage API. It should work as far back as IE8. Choose custom background colours, + logos and fonts from the below drop down menus, then try closing and + reopening the page — you will find that your choices are remembered, as + they are stored using Web Storage. You can also visit the + storage event output (opens in + new tab). Open this, change some values in the index page, then look at + the events page — you'll see the storage changes reported. +

    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    -
    - -
    +
    + +
    + + + - -