Skip to content

Commit 2a1d9ec

Browse files
DAZdaz-yozu
authored andcommitted
initial try at patching methods
typescript fixes added tests updated methods to get classes working adding tests back in and tidying up
1 parent 422eb81 commit 2a1d9ec

3 files changed

Lines changed: 71 additions & 3 deletions

File tree

src/core/controller.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ export class Controller<ElementType extends Element = Element> {
7373
return this.scope.data
7474
}
7575

76+
findElement(selector: string) {
77+
return this.scope.findElement(selector)
78+
}
79+
80+
findAllElements(selector: string) {
81+
return this.scope.findAllElements(selector)
82+
}
83+
7684
initialize() {
7785
// Override in your subclass to set up initial controller state
7886
}

src/core/scope.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,38 @@ export class Scope {
2626
}
2727

2828
findElement(selector: string): Element | undefined {
29-
return this.element.matches(selector) ? this.element : this.queryElements(selector).find(this.containsElement)
29+
const elementWithId = document.getElementById(selector)
30+
if (elementWithId && this.containsElement(elementWithId)) {
31+
return elementWithId
32+
}
33+
const newSelector = this.classifySelector(selector)
34+
return this.element.matches(newSelector) ? this.element : this.queryElements(newSelector).find(this.containsElement)
3035
}
3136

3237
findAllElements(selector: string): Element[] {
38+
const newSelector = this.classifySelector(selector)
3339
return [
34-
...(this.element.matches(selector) ? [this.element] : []),
35-
...this.queryElements(selector).filter(this.containsElement),
40+
...(this.element.matches(newSelector) ? [this.element] : []),
41+
...this.queryElements(newSelector).filter(this.containsElement),
3642
]
3743
}
3844

45+
classifySelector(selector: string | string[]): string {
46+
const tokens = Array.isArray(selector) ? selector : [selector]
47+
48+
const allDefinedTokens = this.getAllClassTokens()
49+
const isDefinedClass = tokens.every((token) => allDefinedTokens.includes(token))
50+
51+
const stringySelector = tokens.join(" ")
52+
return isDefinedClass ? `.${stringySelector.replace(/ /g, ".")}` : stringySelector
53+
}
54+
55+
getAllClassTokens(): string[] {
56+
return Object.entries((this.element as HTMLElement).dataset)
57+
.filter(([key]) => key.endsWith("Class"))
58+
.flatMap(([_, value]) => (value ? value.trim().split(/\s+/) : []))
59+
}
60+
3961
containsElement = (element: Element): boolean => {
4062
return element.closest(this.controllerSelector) === this.element
4163
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { ClassController } from "../../controllers/class_controller"
2+
import { ControllerTestCase } from "../../cases/controller_test_case"
3+
4+
export default class FindElementTests extends ControllerTestCase(ClassController) {
5+
fixtureHTML = `
6+
<div data-controller="${this.identifier}"
7+
data-${this.identifier}-active-class="test--active"
8+
data-${this.identifier}-loading-class="busy"
9+
data-${this.identifier}-success-class="bg-green-400 border border-green-600"
10+
>
11+
<div id="inside-id" class="busy"></div>
12+
</div>
13+
<div id="outside-id" class="busy"></div>
14+
15+
"test findElement finds element by id inside scope"() {
16+
const result = this.controller.findElement("inside-id")
17+
this.assert.equal(result?.id, "inside-id")
18+
}
19+
20+
"test findElement does not find element by id outside scope"() {
21+
const result = this.controller.findElement("outside-id")
22+
this.assert.equal(result, undefined)
23+
}
24+
25+
"test findElement finds element by defined class"() {
26+
const result = this.controller.findElement(this.controller.loadingClass)
27+
this.assert.ok(result instanceof Element)
28+
this.assert.ok(result?.classList.contains("busy"))
29+
}
30+
31+
"test findAllElements returns multiple matches for defined class"() {
32+
const results = this.controller.findAllElements(this.controller.loadingClass)
33+
this.assert.ok(Array.isArray(results))
34+
this.assert.equal(results.length, 1)
35+
this.assert.ok(results[0].classList.contains("busy"))
36+
}
37+
`
38+
}

0 commit comments

Comments
 (0)