Skip to content

Commit ca6de49

Browse files
Merge pull request #1227 from basecamp/morphing
Make Trix compatible with morphing
2 parents d8416c7 + 2329941 commit ca6de49

File tree

4 files changed

+64
-16
lines changed

4 files changed

+64
-16
lines changed

karma.conf.js

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,12 @@ if (process.env.SAUCE_ACCESS_KEY) {
5353
browserVersion: "latest",
5454
"moz:debuggerAddress": true
5555
},
56-
sl_safari_12_1: {
57-
base: "SauceLabs",
58-
browserName: "safari",
59-
platform: "macOS 10.13",
60-
version: "12.1"
61-
},
6256
sl_edge_latest: {
6357
base: "SauceLabs",
6458
browserName: "microsoftedge",
6559
platform: "Windows 10",
6660
version: "latest"
6761
},
68-
sl_ios_latest: {
69-
base: "SauceLabs",
70-
browserName: "safari",
71-
platform: "ios",
72-
device: "iPhone X Simulator",
73-
version: "13.0"
74-
},
7562
sl_android_9: {
7663
base: "SauceLabs",
7764
browserName: "chrome",

src/test/system.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import "test/system/html_replacement_test"
1515
import "test/system/installation_process_test"
1616
import "test/system/level_2_input_test"
1717
import "test/system/list_formatting_test"
18+
import "test/system/morphing_test"
1819
import "test/system/mutation_input_test"
1920
import "test/system/pasting_test"
2021
import "test/system/text_formatting_test"

src/test/system/morphing_test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { assert, test, testGroup } from "test/test_helper"
2+
import { nextFrame } from "../test_helpers/timing_helpers"
3+
4+
testGroup("morphing with internal toolbar", { template: "editor_empty" }, () => {
5+
test("removing the 'connected' attribute will reset the editor and recreate toolbar", async () => {
6+
const element = getEditorElement()
7+
8+
assert.ok(element.hasAttribute("connected"))
9+
10+
const originalToolbar = element.toolbarElement
11+
element.toolbarElement.remove()
12+
element.removeAttribute("toolbar")
13+
element.removeAttribute("connected")
14+
await nextFrame()
15+
16+
assert.ok(element.hasAttribute("connected"))
17+
assert.ok(element.toolbarElement)
18+
assert.notEqual(originalToolbar, element.toolbarElement)
19+
})
20+
})
21+
22+
testGroup("morphing with external toolbar", { template: "editor_with_toolbar_and_input" }, () => {
23+
test("removing the 'connected' attribute will reset the editor leave the toolbar untouched", async () => {
24+
const element = getEditorElement()
25+
26+
assert.ok(element.hasAttribute("connected"))
27+
28+
const originalToolbar = element.toolbarElement
29+
element.removeAttribute("connected")
30+
await nextFrame()
31+
32+
assert.ok(element.hasAttribute("connected"))
33+
assert.ok(element.toolbarElement)
34+
assert.equal(originalToolbar, element.toolbarElement)
35+
})
36+
})

src/trix/elements/trix_editor_element.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ class LegacyDelegate {
348348
export default class TrixEditorElement extends HTMLElement {
349349
static formAssociated = "ElementInternals" in window
350350

351+
static observedAttributes = [ "connected" ]
352+
351353
#delegate
352354

353355
constructor() {
@@ -410,9 +412,9 @@ export default class TrixEditorElement extends HTMLElement {
410412
} else if (this.parentNode) {
411413
const toolbarId = `trix-toolbar-${this.trixId}`
412414
this.setAttribute("toolbar", toolbarId)
413-
const element = makeElement("trix-toolbar", { id: toolbarId })
414-
this.parentNode.insertBefore(element, this)
415-
return element
415+
this.internalToolbar = makeElement("trix-toolbar", { id: toolbarId })
416+
this.parentNode.insertBefore(this.internalToolbar, this)
417+
return this.internalToolbar
416418
} else {
417419
return undefined
418420
}
@@ -453,6 +455,14 @@ export default class TrixEditorElement extends HTMLElement {
453455
this.editor?.loadHTML(this.defaultValue)
454456
}
455457

458+
// Element callbacks
459+
460+
attributeChangedCallback(name, oldValue, newValue) {
461+
if (name === "connected" && this.isConnected && oldValue != null && oldValue !== newValue) {
462+
requestAnimationFrame(() => this.reconnect())
463+
}
464+
}
465+
456466
// Controller delegate methods
457467

458468
notify(message, data) {
@@ -485,13 +495,27 @@ export default class TrixEditorElement extends HTMLElement {
485495
}
486496
this.editorController.registerSelectionManager()
487497
this.#delegate.connectedCallback()
498+
499+
this.toggleAttribute("connected", true)
488500
autofocus(this)
489501
}
490502
}
491503

492504
disconnectedCallback() {
493505
this.editorController?.unregisterSelectionManager()
494506
this.#delegate.disconnectedCallback()
507+
this.toggleAttribute("connected", false)
508+
}
509+
510+
reconnect() {
511+
this.removeInternalToolbar()
512+
this.disconnectedCallback()
513+
this.connectedCallback()
514+
}
515+
516+
removeInternalToolbar() {
517+
this.internalToolbar?.remove()
518+
this.internalToolbar = null
495519
}
496520

497521
// Form support

0 commit comments

Comments
 (0)