Skip to content
This repository was archived by the owner on Oct 21, 2021. It is now read-only.

Commit b36a4d6

Browse files
committed
Extract query-selector package
0 parents  commit b36a4d6

File tree

9 files changed

+4938
-0
lines changed

9 files changed

+4938
-0
lines changed

.flowconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[ignore]
2+
3+
[include]
4+
5+
[libs]
6+
7+
[options]
8+
9+
[lints]

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dist
2+
node_modules

LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2018 GitHub, Inc.
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be
12+
included in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# A typed querySelector function for Flow
2+
3+
## Installation
4+
5+
```
6+
$ npm install @github/query-selector
7+
```
8+
9+
## Usage
10+
11+
```js
12+
import {closest, getAttribute, query, querySelectorAll} from '@github/query-selector'
13+
14+
// Find an element by selector and type or throw if not found.
15+
const image: HTMLImageElement = query(document, '.avatar', HTMLImageElement)
16+
image.src = '/hubot.png'
17+
18+
// Find the parent by selector and type or throw if not found.
19+
const parent: HTMLDetailsElement = closest(image, '.container', HTMLDetailsElement)
20+
parent.open = true
21+
22+
// Retrieve the attribute's value or throw.
23+
const url: string = getAttribute(image, 'data-url')
24+
25+
// Filter all children by selector and type.
26+
const inputs: Array<HTMLInputElement> = querySelectorAll(document, 'input', HTMLInputElement)
27+
for (const input of inputs) {
28+
input.value = ''
29+
}
30+
```
31+
32+
## Development
33+
34+
```
35+
npm install
36+
npm test
37+
```
38+
39+
## License
40+
41+
Distributed under the MIT license. See LICENSE for details.

index.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* @flow strict */
2+
3+
type Queryable = Document | DocumentFragment | Element
4+
5+
export function closest<T: Element>(element: Element, selectors: string, type: Class<T>): T {
6+
const klass = type || HTMLElement
7+
const el = element.closest(selectors)
8+
if (el instanceof klass) {
9+
return el
10+
}
11+
throw new Error(`Element not found: <${klass.name}> ${selectors}`)
12+
}
13+
14+
export function query<T: Element>(context: Queryable, selectors: string, type: Class<T>): T {
15+
const klass = type || HTMLElement
16+
const el = context.querySelector(selectors)
17+
if (el instanceof klass) {
18+
return el
19+
}
20+
throw new Error(`Element not found: <${klass.name}> ${selectors}`)
21+
}
22+
23+
export function querySelectorAll<T: Element>(context: Queryable, selectors: string, type: Class<T>): Array<T> {
24+
const klass = type || HTMLElement
25+
const els: Array<T> = []
26+
for (const el of context.querySelectorAll(selectors)) {
27+
if (el instanceof klass) {
28+
els.push(el)
29+
}
30+
}
31+
return els
32+
}
33+
34+
export function namedItem<T: HTMLElement>(form: HTMLFormElement, itemName: string, type: Class<T>): T {
35+
const klass = type || HTMLInputElement
36+
const el = form.elements.namedItem(itemName)
37+
if (el instanceof klass) {
38+
return el
39+
}
40+
throw new Error(`Element not found by name: <${klass.name}> ${itemName}`)
41+
}
42+
43+
export function getAttribute(element: Element, attributeName: string): string {
44+
const attribute = element.getAttribute(attributeName)
45+
if (attribute != null) {
46+
return attribute
47+
}
48+
throw new Error(`Attribute not found on element: ${attributeName}`)
49+
}

index.js.flow

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* @flow strict */
2+
3+
type Queryable = Document | DocumentFragment | Element;
4+
5+
declare export function closest(context: Queryable, selectors: string): HTMLElement;
6+
declare export function closest<T: Element>(context: Queryable, selectors: string, klass: Class<T>): T;
7+
declare export function query(context: Queryable, selectors: string): HTMLElement;
8+
declare export function query<T: Element>(context: Queryable, selectors: string, klass: Class<T>): T;
9+
declare export function querySelectorAll(context: Queryable, selectors: string): Array<HTMLElement>;
10+
declare export function querySelectorAll<T: Element>(context: Queryable, selectors: string, klass: Class<T>): Array<T>;
11+
declare export function namedItem(form: HTMLFormElement, itemName: string): HTMLInputElement;
12+
declare export function namedItem<T: HTMLElement>(form: HTMLFormElement, itemName: string, klass: Class<T>): T;
13+
declare export function getAttribute(element: Element, attributeName: string): string;

0 commit comments

Comments
 (0)