grainjs 0.1.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -9
- package/dist/cjs/index.d.ts +6 -2
- package/dist/cjs/index.js +24 -17
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/PriorityQueue.d.ts +1 -1
- package/dist/cjs/lib/PriorityQueue.js +1 -0
- package/dist/cjs/lib/PriorityQueue.js.map +1 -1
- package/dist/cjs/lib/_computed_queue.d.ts +18 -0
- package/dist/cjs/lib/_computed_queue.js +6 -1
- package/dist/cjs/lib/_computed_queue.js.map +1 -1
- package/dist/cjs/lib/binding.d.ts +16 -10
- package/dist/cjs/lib/binding.js +22 -27
- package/dist/cjs/lib/binding.js.map +1 -1
- package/dist/cjs/lib/browserGlobals.d.ts +4 -1
- package/dist/cjs/lib/browserGlobals.js +2 -0
- package/dist/cjs/lib/browserGlobals.js.map +1 -1
- package/dist/cjs/lib/computed.d.ts +11 -7
- package/dist/cjs/lib/computed.js +16 -0
- package/dist/cjs/lib/computed.js.map +1 -1
- package/dist/cjs/lib/dispose.d.ts +106 -14
- package/dist/cjs/lib/dispose.js +76 -11
- package/dist/cjs/lib/dispose.js.map +1 -1
- package/dist/cjs/lib/dom.d.ts +21 -17
- package/dist/cjs/lib/dom.js +33 -26
- package/dist/cjs/lib/dom.js.map +1 -1
- package/dist/cjs/lib/domComponent.d.ts +71 -0
- package/dist/cjs/lib/domComponent.js +15 -0
- package/dist/cjs/lib/domComponent.js.map +1 -0
- package/dist/cjs/lib/domComputed.d.ts +89 -0
- package/dist/cjs/lib/domComputed.js +92 -0
- package/dist/cjs/lib/domComputed.js.map +1 -0
- package/dist/cjs/lib/{_domDispose.d.ts → domDispose.d.ts} +12 -2
- package/dist/cjs/lib/{_domDispose.js → domDispose.js} +21 -8
- package/dist/cjs/lib/domDispose.js.map +1 -0
- package/dist/cjs/lib/{_domForEach.d.ts → domForEach.d.ts} +2 -2
- package/dist/cjs/lib/domForEach.js +72 -0
- package/dist/cjs/lib/domForEach.js.map +1 -0
- package/dist/cjs/lib/{_domImpl.d.ts → domImpl.d.ts} +15 -12
- package/dist/cjs/lib/{_domImpl.js → domImpl.js} +23 -6
- package/dist/cjs/lib/domImpl.js.map +1 -0
- package/dist/cjs/lib/{_domMethods.d.ts → domMethods.d.ts} +27 -62
- package/dist/cjs/lib/{_domMethods.js → domMethods.js} +21 -76
- package/dist/cjs/lib/domMethods.js.map +1 -0
- package/dist/cjs/lib/domevent.d.ts +32 -21
- package/dist/cjs/lib/domevent.js +33 -12
- package/dist/cjs/lib/domevent.js.map +1 -1
- package/dist/cjs/lib/emit.d.ts +25 -2
- package/dist/cjs/lib/emit.js +3 -1
- package/dist/cjs/lib/emit.js.map +1 -1
- package/dist/cjs/lib/kowrap.d.ts +45 -3
- package/dist/cjs/lib/kowrap.js +93 -10
- package/dist/cjs/lib/kowrap.js.map +1 -1
- package/dist/cjs/lib/obsArray.d.ts +8 -8
- package/dist/cjs/lib/obsArray.js +1 -0
- package/dist/cjs/lib/obsArray.js.map +1 -1
- package/dist/cjs/lib/observable.d.ts +6 -1
- package/dist/cjs/lib/observable.js +11 -2
- package/dist/cjs/lib/observable.js.map +1 -1
- package/dist/cjs/lib/pureComputed.d.ts +3 -3
- package/dist/cjs/lib/pureComputed.js +2 -1
- package/dist/cjs/lib/pureComputed.js.map +1 -1
- package/dist/cjs/lib/styled.d.ts +76 -11
- package/dist/cjs/lib/styled.js +55 -23
- package/dist/cjs/lib/styled.js.map +1 -1
- package/dist/cjs/lib/subscribe.d.ts +15 -6
- package/dist/cjs/lib/subscribe.js +6 -2
- package/dist/cjs/lib/subscribe.js.map +1 -1
- package/dist/cjs/lib/util.js +1 -0
- package/dist/cjs/lib/util.js.map +1 -1
- package/dist/cjs/lib/widgets/input.d.ts +2 -2
- package/dist/cjs/lib/widgets/input.js +2 -2
- package/dist/cjs/lib/widgets/input.js.map +1 -1
- package/dist/cjs/lib/widgets/select.d.ts +1 -1
- package/dist/cjs/lib/widgets/select.js +1 -0
- package/dist/cjs/lib/widgets/select.js.map +1 -1
- package/dist/esm/index.js +6 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/PriorityQueue.js.map +1 -1
- package/dist/esm/lib/_computed_queue.js +5 -1
- package/dist/esm/lib/_computed_queue.js.map +1 -1
- package/dist/esm/lib/binding.js +20 -27
- package/dist/esm/lib/binding.js.map +1 -1
- package/dist/esm/lib/browserGlobals.js +1 -0
- package/dist/esm/lib/browserGlobals.js.map +1 -1
- package/dist/esm/lib/computed.js +15 -0
- package/dist/esm/lib/computed.js.map +1 -1
- package/dist/esm/lib/dispose.js +74 -11
- package/dist/esm/lib/dispose.js.map +1 -1
- package/dist/esm/lib/dom.js +21 -17
- package/dist/esm/lib/dom.js.map +1 -1
- package/dist/esm/lib/domComponent.js +11 -0
- package/dist/esm/lib/domComponent.js.map +1 -0
- package/dist/esm/lib/domComputed.js +84 -0
- package/dist/esm/lib/domComputed.js.map +1 -0
- package/dist/esm/lib/{_domDispose.js → domDispose.js} +19 -8
- package/dist/esm/lib/domDispose.js.map +1 -0
- package/dist/esm/lib/domForEach.js +68 -0
- package/dist/esm/lib/domForEach.js.map +1 -0
- package/dist/esm/lib/{_domImpl.js → domImpl.js} +20 -4
- package/dist/esm/lib/domImpl.js.map +1 -0
- package/dist/esm/lib/{_domMethods.js → domMethods.js} +8 -63
- package/dist/esm/lib/domMethods.js.map +1 -0
- package/dist/esm/lib/domevent.js +30 -11
- package/dist/esm/lib/domevent.js.map +1 -1
- package/dist/esm/lib/emit.js +2 -1
- package/dist/esm/lib/emit.js.map +1 -1
- package/dist/esm/lib/kowrap.js +90 -10
- package/dist/esm/lib/kowrap.js.map +1 -1
- package/dist/esm/lib/obsArray.js.map +1 -1
- package/dist/esm/lib/observable.js +9 -1
- package/dist/esm/lib/observable.js.map +1 -1
- package/dist/esm/lib/pureComputed.js +1 -1
- package/dist/esm/lib/pureComputed.js.map +1 -1
- package/dist/esm/lib/styled.js +52 -22
- package/dist/esm/lib/styled.js.map +1 -1
- package/dist/esm/lib/subscribe.js +5 -2
- package/dist/esm/lib/subscribe.js.map +1 -1
- package/dist/esm/lib/util.js.map +1 -1
- package/dist/esm/lib/widgets/input.js +1 -2
- package/dist/esm/lib/widgets/input.js.map +1 -1
- package/dist/esm/lib/widgets/select.js.map +1 -1
- package/dist/grain-full.debug.js +1627 -1222
- package/dist/grain-full.min.js +1 -1
- package/dist/grain-full.min.js.map +1 -1
- package/index.ts +6 -2
- package/lib/_computed_queue.ts +7 -1
- package/lib/binding.ts +33 -28
- package/lib/browserGlobals.ts +3 -1
- package/lib/computed.ts +37 -7
- package/lib/dispose.ts +81 -33
- package/lib/dom.ts +24 -18
- package/lib/domComponent.ts +89 -0
- package/lib/domComputed.ts +146 -0
- package/lib/{_domDispose.ts → domDispose.ts} +26 -8
- package/lib/{_domForEach.ts → domForEach.ts} +12 -11
- package/lib/{_domImpl.ts → domImpl.ts} +36 -30
- package/lib/{_domMethods.ts → domMethods.ts} +33 -103
- package/lib/domevent.ts +59 -22
- package/lib/emit.ts +2 -1
- package/lib/kowrap.ts +109 -11
- package/lib/obsArray.ts +2 -2
- package/lib/observable.ts +10 -2
- package/lib/pureComputed.ts +7 -6
- package/lib/styled.ts +65 -39
- package/lib/subscribe.ts +24 -8
- package/lib/widgets/input.ts +9 -7
- package/lib/widgets/select.ts +3 -3
- package/package.json +41 -42
- package/dist/cjs/lib/_domComponent.d.ts +0 -84
- package/dist/cjs/lib/_domComponent.js +0 -160
- package/dist/cjs/lib/_domComponent.js.map +0 -1
- package/dist/cjs/lib/_domDispose.js.map +0 -1
- package/dist/cjs/lib/_domForEach.js +0 -71
- package/dist/cjs/lib/_domForEach.js.map +0 -1
- package/dist/cjs/lib/_domImpl.js.map +0 -1
- package/dist/cjs/lib/_domMethods.js.map +0 -1
- package/dist/esm/lib/_domComponent.js +0 -155
- package/dist/esm/lib/_domComponent.js.map +0 -1
- package/dist/esm/lib/_domDispose.js.map +0 -1
- package/dist/esm/lib/_domForEach.js +0 -68
- package/dist/esm/lib/_domForEach.js.map +0 -1
- package/dist/esm/lib/_domImpl.js.map +0 -1
- package/dist/esm/lib/_domMethods.js.map +0 -1
- package/lib/_domComponent.ts +0 -167
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { BindableValue } from './binding';
|
|
2
|
+
import { MultiHolder } from './dispose';
|
|
3
|
+
import { DomArg, DomMethod } from './domImpl';
|
|
4
|
+
export declare type DomComputed = [Node, Node, DomMethod];
|
|
5
|
+
export declare type DomContents = Node | string | DomComputed | void | null | undefined | IDomContentsArray;
|
|
6
|
+
export interface IDomContentsArray extends Array<DomContents> {
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Replaces the content between nodeBefore and nodeAfter, which should be two siblings within the
|
|
10
|
+
* same parent node. New content may be anything allowed as an argument to dom(), including null
|
|
11
|
+
* to insert nothing. Runs disposers, if any, on all removed content.
|
|
12
|
+
*/
|
|
13
|
+
export declare function replaceContent(nodeBefore: Node, nodeAfter: Node, content: DomContents): void;
|
|
14
|
+
/**
|
|
15
|
+
* Appends dynamic DOM content to an element. The value may be an observable or function (from
|
|
16
|
+
* which a computed is created), whose value will be passed to `contentFunc` which should return
|
|
17
|
+
* DOM content. If the contentFunc is omitted, it defaults to identity, i.e. it's OK for the
|
|
18
|
+
* observable or function to return DOM directly.
|
|
19
|
+
*
|
|
20
|
+
* The DOM content returned may be an element, string, array, or null. Whenever the observable
|
|
21
|
+
* changes, previous content is disposed and removed, and new content added in its place.
|
|
22
|
+
*
|
|
23
|
+
* The following are roughly equivalent:
|
|
24
|
+
* (A) domComputed(nlinesObs, nlines => nlines > 1 ? dom('textarea') : dom('input'));
|
|
25
|
+
* (B) domComputed(use => use(nlinesObs) > 1 ? dom('textarea') : dom('input'));
|
|
26
|
+
* (C) domComputed(use => use(nlinesObs) > 1, isTall => isTall ? dom('textarea') : dom('input'));
|
|
27
|
+
*
|
|
28
|
+
* Here, (C) is best. Both (A) and (B) would rebuild DOM for any change in nlinesObs, but (C)
|
|
29
|
+
* encapsulates meaningful changes in the observable, and only recreates DOM when necessary.
|
|
30
|
+
*
|
|
31
|
+
* Syntax (B), without the second argument, may be useful in cases of DOM depending on several
|
|
32
|
+
* observables, e.g.
|
|
33
|
+
*
|
|
34
|
+
* domComputed(use => use(readonlyObs) ? dom('div') :
|
|
35
|
+
* (use(nlinesObs) > 1 ? dom('textarea') : dom('input')));
|
|
36
|
+
*
|
|
37
|
+
* If the argument is not an observable, domComputed() may but should not be used. The following
|
|
38
|
+
* are equivalent:
|
|
39
|
+
*
|
|
40
|
+
* dom(..., domComputed(listValue, list => `Have ${list.length} items`), ...)
|
|
41
|
+
* dom(..., `Have ${listValue.length} items`, ...)
|
|
42
|
+
*
|
|
43
|
+
* In this case, the latter is preferred as the clearly simpler one.
|
|
44
|
+
*
|
|
45
|
+
* @param valueObs: Observable or function for a computed.
|
|
46
|
+
* @param contentFunc: Function called with the result of valueObs as the input, and
|
|
47
|
+
* returning DOM as output. If omitted, defaults to the identity function.
|
|
48
|
+
*/
|
|
49
|
+
export declare function domComputed(valueObs: BindableValue<Exclude<DomArg, DomMethod>>): DomComputed;
|
|
50
|
+
export declare function domComputed<T>(valueObs: BindableValue<T>, contentFunc: (val: T) => DomContents): DomComputed;
|
|
51
|
+
/**
|
|
52
|
+
* Like domComputed(), but the callback gets an additional first argument, owner, which may be
|
|
53
|
+
* used to take ownership of objects created by the callback. These will be disposed before each
|
|
54
|
+
* new call to the callback, and when the containing DOM is disposed.
|
|
55
|
+
*
|
|
56
|
+
* domComputedOwned(valueObs, (owner, value) => Editor.create(owner, value).renderSomething());
|
|
57
|
+
*/
|
|
58
|
+
export declare function domComputedOwned<T>(valueObs: BindableValue<T>, contentFunc: (owner: MultiHolder, val: T) => DomContents): DomComputed;
|
|
59
|
+
/**
|
|
60
|
+
* Conditionally appends DOM to an element. The value may be an observable or function (from which
|
|
61
|
+
* a computed is created), whose value -- if truthy -- will be passed to `contentFunc` which
|
|
62
|
+
* should return DOM content. If the value is falsy, DOM content is removed.
|
|
63
|
+
*
|
|
64
|
+
* Note that if the observable changes between different truthy values, contentFunc gets called
|
|
65
|
+
* for each value, and previous content gets destroyed. To consider all truthy values the same,
|
|
66
|
+
* use an observable that returns a proper boolean, e.g.
|
|
67
|
+
*
|
|
68
|
+
* dom.maybe(use => Boolean(use(fooObs)), () => dom(...));
|
|
69
|
+
*
|
|
70
|
+
* As with domComputed(), dom.maybe() may but should not be used when the argument is not an
|
|
71
|
+
* observable or function. The following are equivalent:
|
|
72
|
+
*
|
|
73
|
+
* dom(..., dom.maybe(myValue, () => dom(...)));
|
|
74
|
+
* dom(..., myValue ? dom(...) : null);
|
|
75
|
+
*
|
|
76
|
+
* The latter is preferred for being simpler.
|
|
77
|
+
*
|
|
78
|
+
* @param boolValueObs: Observable or function for a computed.
|
|
79
|
+
* @param contentFunc: Called with the result of boolValueObs when it is truthy. Should return DOM.
|
|
80
|
+
*/
|
|
81
|
+
export declare function maybe<T>(boolValueObs: BindableValue<T>, contentFunc: (val: NonNullable<T>) => DomContents): DomComputed;
|
|
82
|
+
/**
|
|
83
|
+
* Like maybe(), but the callback gets an additional first argument, owner, which may be used to
|
|
84
|
+
* take ownership of objects created by the callback. These will be disposed before each new call
|
|
85
|
+
* to the callback, and when the condition becomes false or the containing DOM gets disposed.
|
|
86
|
+
*
|
|
87
|
+
* maybeOwned(showEditor, (owner) => Editor.create(owner).renderSomething());
|
|
88
|
+
*/
|
|
89
|
+
export declare function maybeOwned<T>(boolValueObs: BindableValue<T>, contentFunc: (owner: MultiHolder, val: NonNullable<T>) => DomContents): DomComputed;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.maybeOwned = exports.maybe = exports.domComputedOwned = exports.domComputed = exports.replaceContent = void 0;
|
|
4
|
+
const binding_1 = require("./binding");
|
|
5
|
+
const dispose_1 = require("./dispose");
|
|
6
|
+
const domDispose_1 = require("./domDispose");
|
|
7
|
+
const domImpl_1 = require("./domImpl");
|
|
8
|
+
// Use the browser globals in a way that allows replacing them with mocks in tests.
|
|
9
|
+
const browserGlobals_1 = require("./browserGlobals");
|
|
10
|
+
/**
|
|
11
|
+
* Replaces the content between nodeBefore and nodeAfter, which should be two siblings within the
|
|
12
|
+
* same parent node. New content may be anything allowed as an argument to dom(), including null
|
|
13
|
+
* to insert nothing. Runs disposers, if any, on all removed content.
|
|
14
|
+
*/
|
|
15
|
+
function replaceContent(nodeBefore, nodeAfter, content) {
|
|
16
|
+
const elem = nodeBefore.parentNode;
|
|
17
|
+
if (elem) {
|
|
18
|
+
let next;
|
|
19
|
+
for (let n = nodeBefore.nextSibling; n && n !== nodeAfter; n = next) {
|
|
20
|
+
next = n.nextSibling;
|
|
21
|
+
domDispose_1.domDispose(n);
|
|
22
|
+
elem.removeChild(n);
|
|
23
|
+
}
|
|
24
|
+
if (content) {
|
|
25
|
+
elem.insertBefore(content instanceof browserGlobals_1.G.Node ? content : domImpl_1.frag(content), nodeAfter);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.replaceContent = replaceContent;
|
|
30
|
+
function domComputed(valueObs, contentFunc = identity) {
|
|
31
|
+
const markerPre = browserGlobals_1.G.document.createComment('a');
|
|
32
|
+
const markerPost = browserGlobals_1.G.document.createComment('b');
|
|
33
|
+
// Function is added after markerPre and markerPost, so that it runs once they have already been
|
|
34
|
+
// attached to elem (the parent element).
|
|
35
|
+
return [markerPre, markerPost, (elem) => {
|
|
36
|
+
binding_1.subscribeElem(markerPost, valueObs, (value) => replaceContent(markerPre, markerPost, contentFunc(value)));
|
|
37
|
+
}];
|
|
38
|
+
}
|
|
39
|
+
exports.domComputed = domComputed;
|
|
40
|
+
/**
|
|
41
|
+
* Like domComputed(), but the callback gets an additional first argument, owner, which may be
|
|
42
|
+
* used to take ownership of objects created by the callback. These will be disposed before each
|
|
43
|
+
* new call to the callback, and when the containing DOM is disposed.
|
|
44
|
+
*
|
|
45
|
+
* domComputedOwned(valueObs, (owner, value) => Editor.create(owner, value).renderSomething());
|
|
46
|
+
*/
|
|
47
|
+
function domComputedOwned(valueObs, contentFunc) {
|
|
48
|
+
const holder = dispose_1.Holder.create(null);
|
|
49
|
+
const [markerPre, markerPost, func] = domComputed(valueObs, (val) => contentFunc(dispose_1.MultiHolder.create(holder), val));
|
|
50
|
+
domDispose_1.autoDisposeElem(markerPost, holder);
|
|
51
|
+
return [markerPre, markerPost, func];
|
|
52
|
+
}
|
|
53
|
+
exports.domComputedOwned = domComputedOwned;
|
|
54
|
+
function identity(arg) { return arg; }
|
|
55
|
+
/**
|
|
56
|
+
* Conditionally appends DOM to an element. The value may be an observable or function (from which
|
|
57
|
+
* a computed is created), whose value -- if truthy -- will be passed to `contentFunc` which
|
|
58
|
+
* should return DOM content. If the value is falsy, DOM content is removed.
|
|
59
|
+
*
|
|
60
|
+
* Note that if the observable changes between different truthy values, contentFunc gets called
|
|
61
|
+
* for each value, and previous content gets destroyed. To consider all truthy values the same,
|
|
62
|
+
* use an observable that returns a proper boolean, e.g.
|
|
63
|
+
*
|
|
64
|
+
* dom.maybe(use => Boolean(use(fooObs)), () => dom(...));
|
|
65
|
+
*
|
|
66
|
+
* As with domComputed(), dom.maybe() may but should not be used when the argument is not an
|
|
67
|
+
* observable or function. The following are equivalent:
|
|
68
|
+
*
|
|
69
|
+
* dom(..., dom.maybe(myValue, () => dom(...)));
|
|
70
|
+
* dom(..., myValue ? dom(...) : null);
|
|
71
|
+
*
|
|
72
|
+
* The latter is preferred for being simpler.
|
|
73
|
+
*
|
|
74
|
+
* @param boolValueObs: Observable or function for a computed.
|
|
75
|
+
* @param contentFunc: Called with the result of boolValueObs when it is truthy. Should return DOM.
|
|
76
|
+
*/
|
|
77
|
+
function maybe(boolValueObs, contentFunc) {
|
|
78
|
+
return domComputed(boolValueObs, (value) => value ? contentFunc(value) : null);
|
|
79
|
+
}
|
|
80
|
+
exports.maybe = maybe;
|
|
81
|
+
/**
|
|
82
|
+
* Like maybe(), but the callback gets an additional first argument, owner, which may be used to
|
|
83
|
+
* take ownership of objects created by the callback. These will be disposed before each new call
|
|
84
|
+
* to the callback, and when the condition becomes false or the containing DOM gets disposed.
|
|
85
|
+
*
|
|
86
|
+
* maybeOwned(showEditor, (owner) => Editor.create(owner).renderSomething());
|
|
87
|
+
*/
|
|
88
|
+
function maybeOwned(boolValueObs, contentFunc) {
|
|
89
|
+
return domComputedOwned(boolValueObs, (owner, value) => value ? contentFunc(owner, value) : null);
|
|
90
|
+
}
|
|
91
|
+
exports.maybeOwned = maybeOwned;
|
|
92
|
+
//# sourceMappingURL=domComputed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domComputed.js","sourceRoot":"","sources":["../../../lib/domComputed.ts"],"names":[],"mappings":";;;AAAA,uCAAuD;AACvD,uCAA8C;AAC9C,6CAAyD;AACzD,uCAAkD;AAElD,mFAAmF;AACnF,qDAAmC;AAUnC;;;;GAIG;AACH,SAAgB,cAAc,CAAC,UAAgB,EAAE,SAAe,EAAE,OAAoB;IACpF,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC;IACnC,IAAI,IAAI,EAAE;QACR,IAAI,IAAI,CAAC;QACT,KAAK,IAAI,CAAC,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE;YACnE,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC;YACrB,uBAAU,CAAC,CAAC,CAAC,CAAC;YACd,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;SACrB;QACD,IAAI,OAAO,EAAE;YACX,IAAI,CAAC,YAAY,CAAC,OAAO,YAAY,kBAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAI,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,CAAC;SACnF;KACF;AACH,CAAC;AAbD,wCAaC;AAyCD,SAAgB,WAAW,CACzB,QAA0B,EAAE,cAAuC,QAAe;IAElF,MAAM,SAAS,GAAG,kBAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,kBAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAEjD,gGAAgG;IAChG,yCAAyC;IACzC,OAAO,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;YAC5C,uBAAa,CAAC,UAAU,EAAE,QAAQ,EAChC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;AACL,CAAC;AAZD,kCAYC;AAED;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAC9B,QAA0B,EAAE,WAAwD;IAEpF,MAAM,MAAM,GAAG,gBAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC,QAAQ,EACxD,CAAC,GAAM,EAAE,EAAE,CAAC,WAAW,CAAC,qBAAW,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC5D,4BAAe,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACpC,OAAO,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC;AARD,4CAQC;AAED,SAAS,QAAQ,CAAI,GAAM,IAAO,OAAO,GAAG,CAAC,CAAC,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAgB,KAAK,CAAI,YAA8B,EACnD,WAAiD;IACnD,OAAO,WAAW,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,KAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAClF,CAAC;AAHD,sBAGC;AAED;;;;;;GAMG;AACH,SAAgB,UAAU,CAAI,YAA8B,EACxD,WAAqE;IACvE,OAAO,gBAAgB,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,KAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACrG,CAAC;AAHD,gCAGC"}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { IDisposable } from './dispose';
|
|
2
2
|
export declare type INodeFunc = (node: Node) => void;
|
|
3
|
+
export declare function _disposeNode(node: Node): void;
|
|
4
|
+
export interface IDomDisposeHooks {
|
|
5
|
+
disposeRecursive: (node: Node) => void;
|
|
6
|
+
disposeNode: (node: Node) => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Support for extending dom disposal. This is very low-level, and needs utmost care. Any
|
|
10
|
+
* disposers set should take care of calling the original versions of the disposers.
|
|
11
|
+
*/
|
|
12
|
+
export declare const domDisposeHooks: IDomDisposeHooks;
|
|
3
13
|
/**
|
|
4
14
|
* Run disposers associated with any descendant of elem or with elem itself. Disposers get
|
|
5
15
|
* associated with elements using dom.onDispose(). Descendants are processed first.
|
|
@@ -7,9 +17,9 @@ export declare type INodeFunc = (node: Node) => void;
|
|
|
7
17
|
* It is automatically called if one of the function arguments to dom() throws an exception during
|
|
8
18
|
* element creation. This way any onDispose() handlers set on the unfinished element get called.
|
|
9
19
|
*
|
|
10
|
-
* @param {
|
|
20
|
+
* @param {Node} node: The element to run disposers on.
|
|
11
21
|
*/
|
|
12
|
-
export declare function domDispose(
|
|
22
|
+
export declare function domDispose(node: Node): void;
|
|
13
23
|
/**
|
|
14
24
|
* Associate a disposerFunc with a DOM element. It will be called when the element is disposed
|
|
15
25
|
* using domDispose() on it or any of its parents. If onDispose is called multiple times, all
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.autoDispose = exports.autoDisposeElem = exports.onDispose = exports.onDisposeElem = exports.domDispose = exports.domDisposeHooks = exports._disposeNode = void 0;
|
|
3
4
|
/**
|
|
4
5
|
* Private global disposal map. It maintains the association between DOM nodes and cleanup
|
|
5
6
|
* functions added with dom.onDispose(). To support multiple disposers on one element, we use a
|
|
@@ -25,19 +26,31 @@ function _walkDom(elem, visitFunc) {
|
|
|
25
26
|
visitFunc(elem);
|
|
26
27
|
}
|
|
27
28
|
// Internal helper to run all disposers for a single element.
|
|
28
|
-
function
|
|
29
|
-
let disposer = _disposeMap.get(
|
|
29
|
+
function _disposeNode(node) {
|
|
30
|
+
let disposer = _disposeMap.get(node);
|
|
30
31
|
if (disposer) {
|
|
31
|
-
let key =
|
|
32
|
+
let key = node;
|
|
32
33
|
do {
|
|
33
34
|
_disposeMap.delete(key);
|
|
34
|
-
disposer(
|
|
35
|
+
disposer(node);
|
|
35
36
|
// Find the next disposer; these are chained when there are multiple.
|
|
36
37
|
key = disposer;
|
|
37
38
|
disposer = _disposeMap.get(key);
|
|
38
39
|
} while (disposer);
|
|
39
40
|
}
|
|
40
41
|
}
|
|
42
|
+
exports._disposeNode = _disposeNode;
|
|
43
|
+
function _disposeNodeRecursive(node) {
|
|
44
|
+
_walkDom(node, exports.domDisposeHooks.disposeNode);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Support for extending dom disposal. This is very low-level, and needs utmost care. Any
|
|
48
|
+
* disposers set should take care of calling the original versions of the disposers.
|
|
49
|
+
*/
|
|
50
|
+
exports.domDisposeHooks = {
|
|
51
|
+
disposeNode: _disposeNode,
|
|
52
|
+
disposeRecursive: _disposeNodeRecursive,
|
|
53
|
+
};
|
|
41
54
|
/**
|
|
42
55
|
* Run disposers associated with any descendant of elem or with elem itself. Disposers get
|
|
43
56
|
* associated with elements using dom.onDispose(). Descendants are processed first.
|
|
@@ -45,10 +58,10 @@ function _disposeElem(elem) {
|
|
|
45
58
|
* It is automatically called if one of the function arguments to dom() throws an exception during
|
|
46
59
|
* element creation. This way any onDispose() handlers set on the unfinished element get called.
|
|
47
60
|
*
|
|
48
|
-
* @param {
|
|
61
|
+
* @param {Node} node: The element to run disposers on.
|
|
49
62
|
*/
|
|
50
|
-
function domDispose(
|
|
51
|
-
|
|
63
|
+
function domDispose(node) {
|
|
64
|
+
exports.domDisposeHooks.disposeRecursive(node);
|
|
52
65
|
}
|
|
53
66
|
exports.domDispose = domDispose;
|
|
54
67
|
/**
|
|
@@ -91,4 +104,4 @@ function autoDispose(disposable) {
|
|
|
91
104
|
}
|
|
92
105
|
}
|
|
93
106
|
exports.autoDispose = autoDispose;
|
|
94
|
-
//# sourceMappingURL=
|
|
107
|
+
//# sourceMappingURL=domDispose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domDispose.js","sourceRoot":"","sources":["../../../lib/domDispose.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,GAAuC,IAAI,OAAO,EAAE,CAAC;AAItE,4FAA4F;AAC5F,mCAAmC;AACnC,SAAS,QAAQ,CAAC,IAAU,EAAE,SAAoB;IAChD,IAAI,CAAC,GAAc,IAAI,CAAC,UAAU,CAAC;IACnC,OAAO,CAAC,EAAE;QACR,4FAA4F;QAC5F,gCAAgC;QAChC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QACvB,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC;KACnB;IACD,SAAS,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED,6DAA6D;AAC7D,SAAgB,YAAY,CAAC,IAAU;IACrC,IAAI,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,QAAQ,EAAE;QACZ,IAAI,GAAG,GAAmB,IAAI,CAAC;QAC/B,GAAG;YACD,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,qEAAqE;YACrE,GAAG,GAAG,QAAQ,CAAC;YACf,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;SACjC,QAAQ,QAAQ,EAAE;KACpB;AACH,CAAC;AAZD,oCAYC;AAED,SAAS,qBAAqB,CAAC,IAAU;IACvC,QAAQ,CAAC,IAAI,EAAE,uBAAe,CAAC,WAAW,CAAC,CAAC;AAC9C,CAAC;AAOD;;;GAGG;AACU,QAAA,eAAe,GAAqB;IAC/C,WAAW,EAAE,YAAY;IACzB,gBAAgB,EAAE,qBAAqB;CACxC,CAAC;AAEF;;;;;;;;GAQG;AACH,SAAgB,UAAU,CAAC,IAAU;IACnC,uBAAe,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAFD,gCAEC;AAED;;;;;;;;;GASG;AACH,SAAgB,aAAa,CAAC,IAAU,EAAE,YAAuB;IAC/D,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3C,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACpC,IAAI,YAAY,EAAE;QAChB,WAAW,CAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;KAC7C;AACH,CAAC;AAND,sCAMC;AACD,SAAgB,SAAS,CAAC,YAAuB;IAC/C,OAAO,CAAC,IAAU,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;AAC3D,CAAC;AAFD,8BAEC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,IAAU,EAAE,UAA4B;IACtE,IAAI,UAAU,EAAE;QACd,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;KACjD;AACH,CAAC;AAJD,0CAIC;AACD,SAAgB,WAAW,CAAC,UAA4B;IACtD,IAAI,UAAU,EAAE;QACd,OAAO,CAAC,IAAU,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;KAC1D;AACH,CAAC;AAJD,kCAIC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DomContents } from './domComputed';
|
|
2
2
|
import { MaybeObsArray } from './obsArray';
|
|
3
3
|
/**
|
|
4
4
|
* Creates DOM elements for each element of an observable array. As the array is changed, children
|
|
@@ -18,4 +18,4 @@ import { MaybeObsArray } from './obsArray';
|
|
|
18
18
|
* If you'd like to map the DOM node back to its source item, use dom.data() and dom.getData() in
|
|
19
19
|
* itemCreateFunc().
|
|
20
20
|
*/
|
|
21
|
-
export declare function forEach<T>(obsArray: MaybeObsArray<T>, itemCreateFunc: (item: T) => Node | null):
|
|
21
|
+
export declare function forEach<T>(obsArray: MaybeObsArray<T>, itemCreateFunc: (item: T) => Node | null): DomContents;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.forEach = void 0;
|
|
4
|
+
const domComputed_1 = require("./domComputed");
|
|
5
|
+
const domDispose_1 = require("./domDispose");
|
|
6
|
+
const domImpl_1 = require("./domImpl");
|
|
7
|
+
const obsArray_1 = require("./obsArray");
|
|
8
|
+
// Use the browser globals in a way that allows replacing them with mocks in tests.
|
|
9
|
+
const browserGlobals_1 = require("./browserGlobals");
|
|
10
|
+
/**
|
|
11
|
+
* Creates DOM elements for each element of an observable array. As the array is changed, children
|
|
12
|
+
* are added or removed. This works for any array-valued observable, and for obsArray() and
|
|
13
|
+
* computedArray() it works more efficiently for simple changes.
|
|
14
|
+
*
|
|
15
|
+
* The given itemCreateFunc() should return a single DOM node for each item, or null to skip that
|
|
16
|
+
* item. It is called for new items whenever they are spliced in, or the array replaced. The
|
|
17
|
+
* forEach() owns the created nodes, and runs domDispose() on them when they are spliced out.
|
|
18
|
+
*
|
|
19
|
+
* If the created nodes are removed from their parent externally, forEach() will cope with it, but
|
|
20
|
+
* will consider these elements as no longer owned, and will not run domDispose() on them.
|
|
21
|
+
*
|
|
22
|
+
* Note that itemCreateFunc() does not receive an index: an index would only be correct at the
|
|
23
|
+
* time the item is created, and would not reflect further changes to the array.
|
|
24
|
+
*
|
|
25
|
+
* If you'd like to map the DOM node back to its source item, use dom.data() and dom.getData() in
|
|
26
|
+
* itemCreateFunc().
|
|
27
|
+
*/
|
|
28
|
+
function forEach(obsArray, itemCreateFunc) {
|
|
29
|
+
const markerPre = browserGlobals_1.G.document.createComment('a');
|
|
30
|
+
const markerPost = browserGlobals_1.G.document.createComment('b');
|
|
31
|
+
return [markerPre, markerPost, (elem) => {
|
|
32
|
+
if (Array.isArray(obsArray)) {
|
|
33
|
+
domComputed_1.replaceContent(markerPre, markerPost, obsArray.map(itemCreateFunc));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const nodes = obsArray_1.computedArray(obsArray, itemCreateFunc);
|
|
37
|
+
// Be sure to dispose the newly-created array when the DOM it's associated with is gone.
|
|
38
|
+
domDispose_1.autoDisposeElem(markerPost, nodes);
|
|
39
|
+
nodes.addListener((newArr, oldArr, splice) => {
|
|
40
|
+
if (splice) {
|
|
41
|
+
// Remove the elements that are gone.
|
|
42
|
+
for (const node of splice.deleted) {
|
|
43
|
+
if (node && node.parentNode === elem) {
|
|
44
|
+
domDispose_1.domDispose(node);
|
|
45
|
+
elem.removeChild(node);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (splice.numAdded > 0) {
|
|
49
|
+
// Find a valid child immediately following the spliced out portion, for DOM insertion.
|
|
50
|
+
const endIndex = splice.start + splice.numAdded;
|
|
51
|
+
let nextElem = markerPost;
|
|
52
|
+
for (let i = endIndex; i < newArr.length; i++) {
|
|
53
|
+
const node = newArr[i];
|
|
54
|
+
if (node && node.parentNode === elem) {
|
|
55
|
+
nextElem = node;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Insert the new elements.
|
|
60
|
+
const content = domImpl_1.frag(newArr.slice(splice.start, endIndex));
|
|
61
|
+
elem.insertBefore(content, nextElem);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
domComputed_1.replaceContent(markerPre, markerPost, newArr);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
domComputed_1.replaceContent(markerPre, markerPost, nodes.get());
|
|
69
|
+
}];
|
|
70
|
+
}
|
|
71
|
+
exports.forEach = forEach;
|
|
72
|
+
//# sourceMappingURL=domForEach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domForEach.js","sourceRoot":"","sources":["../../../lib/domForEach.ts"],"names":[],"mappings":";;;AAAA,+CAA0D;AAC1D,6CAAyD;AACzD,uCAA+B;AAC/B,yCAAkE;AAElE,mFAAmF;AACnF,qDAAmC;AAEnC;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,OAAO,CAAI,QAA0B,EAAE,cAAsC;IAC3F,MAAM,SAAS,GAAG,kBAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,kBAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACjD,OAAO,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;YAC5C,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAC3B,4BAAc,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;gBACpE,OAAO;aACR;YAED,MAAM,KAAK,GAAwB,wBAAa,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;YAE3E,wFAAwF;YACxF,4BAAe,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YAEnC,KAAK,CAAC,WAAW,CAAC,CAAC,MAAwB,EAAE,MAAwB,EAAE,MAAO,EAAE,EAAE;gBAChF,IAAI,MAAM,EAAE;oBACV,qCAAqC;oBACrC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE;wBACjC,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE;4BACpC,uBAAU,CAAC,IAAI,CAAC,CAAC;4BACjB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;yBACxB;qBACF;oBAED,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE;wBACvB,uFAAuF;wBACvF,MAAM,QAAQ,GAAW,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC;wBACxD,IAAI,QAAQ,GAAS,UAAU,CAAC;wBAChC,KAAK,IAAI,CAAC,GAAG,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;4BAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;4BACvB,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE;gCACpC,QAAQ,GAAG,IAAI,CAAC;gCAChB,MAAM;6BACP;yBACF;wBAED,2BAA2B;wBAC3B,MAAM,OAAO,GAAG,cAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;wBAC3D,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;qBACtC;iBACF;qBAAM;oBACL,4BAAc,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;iBAC/C;YACH,CAAC,CAAC,CAAC;YACH,4BAAc,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;AACL,CAAC;AA9CD,0BA8CC"}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
export declare type DomMethod = (elem:
|
|
2
|
-
export declare type DomElementMethod =
|
|
1
|
+
export declare type DomMethod<T = Node> = (elem: T) => DomArg<T> | void;
|
|
2
|
+
export declare type DomElementMethod = DomMethod<HTMLElement>;
|
|
3
3
|
export interface IAttrObj {
|
|
4
4
|
[attrName: string]: string | boolean | null | undefined;
|
|
5
5
|
}
|
|
6
|
-
export declare type DomArg = Node | string |
|
|
7
|
-
export interface
|
|
8
|
-
}
|
|
9
|
-
export declare type DomElementArg = DomArg | IAttrObj | IDomElementArgArray | DomElementMethod;
|
|
10
|
-
export interface IDomElementArgArray extends Array<DomElementArg> {
|
|
6
|
+
export declare type DomArg<T = Node> = Node | string | void | null | undefined | IDomArgs<T> | DomMethod<T> | (T extends Element ? IAttrObj : never);
|
|
7
|
+
export interface IDomArgs<T = Node> extends Array<DomArg<T>> {
|
|
11
8
|
}
|
|
9
|
+
export declare type DomElementArg = DomArg<HTMLElement>;
|
|
12
10
|
/**
|
|
13
11
|
* dom('tag#id.class1.class2', ...args)
|
|
14
12
|
* The first argument is a string consisting of a tag name, with optional #foo suffix
|
|
15
13
|
* to add the ID 'foo', and zero or more .bar suffixes to add a CSS class 'bar'.
|
|
16
14
|
*
|
|
15
|
+
* NOTE that better typings are available when a tag is used directly, e.g.
|
|
16
|
+
* dom('input', {id: 'foo'}, (elem) => ...) --> elem has type HTMLInputElement
|
|
17
|
+
* dom('input#foo', (elem) => ...) --> elem has type HTMLElement
|
|
18
|
+
*
|
|
17
19
|
* The rest of the arguments are optional and may be:
|
|
18
20
|
*
|
|
19
21
|
* Nodes - which become children of the created element;
|
|
@@ -25,21 +27,22 @@ export interface IDomElementArgArray extends Array<DomElementArg> {
|
|
|
25
27
|
* "dom methods" - expressions such as `dom.attr('href', url)` or `dom.hide(obs)`, which
|
|
26
28
|
* are actually special cases of the "functions" category.
|
|
27
29
|
*/
|
|
28
|
-
export declare function dom(tagString:
|
|
30
|
+
export declare function dom<Tag extends TagName>(tagString: Tag, ...args: IDomArgs<TagElem<Tag>>): TagElem<Tag>;
|
|
31
|
+
export declare type TagName = keyof HTMLElementTagNameMap | string;
|
|
32
|
+
export declare type TagElem<T extends TagName> = T extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[T] : HTMLElement;
|
|
29
33
|
/**
|
|
30
34
|
* svg('tag#id.class1.class2', ...args)
|
|
31
35
|
* Same as dom(...), but creates an SVG element.
|
|
32
36
|
*/
|
|
33
|
-
export declare function svg(tagString: string, ...args:
|
|
37
|
+
export declare function svg(tagString: string, ...args: IDomArgs<SVGElement>): SVGElement;
|
|
34
38
|
/**
|
|
35
39
|
* Update an element with any number of arguments, as documented in dom().
|
|
36
40
|
*/
|
|
37
|
-
export declare function update<
|
|
38
|
-
export declare function update<E extends Node>(elem: E, ...args: DomArg[]): E;
|
|
41
|
+
export declare function update<T extends Node, Args extends IDomArgs<T>>(elem: T, ...args: Args): T;
|
|
39
42
|
/**
|
|
40
43
|
* Creates a DocumentFragment processing arguments the same way as the dom() function.
|
|
41
44
|
*/
|
|
42
|
-
export declare function frag(...args:
|
|
45
|
+
export declare function frag(...args: IDomArgs<DocumentFragment>): DocumentFragment;
|
|
43
46
|
/**
|
|
44
47
|
* Find the first element matching a selector; just an abbreviation for document.querySelector().
|
|
45
48
|
*/
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
const
|
|
3
|
+
exports.findAll = exports.find = exports.frag = exports.update = exports.svg = exports.dom = void 0;
|
|
4
|
+
const domDispose_1 = require("./domDispose");
|
|
5
|
+
const domMethods_1 = require("./domMethods");
|
|
5
6
|
// Use the browser globals in a way that allows replacing them with mocks in tests.
|
|
6
7
|
const browserGlobals_1 = require("./browserGlobals");
|
|
7
8
|
// The goal of the above declarations is to get help from TypeScript in detecting incorrect usage:
|
|
8
|
-
//
|
|
9
|
+
// (See test/types/dom.ts for a test of this.)
|
|
10
|
+
// import {text, hide} from './domMethods';
|
|
9
11
|
// dom('div', text('hello')); // OK
|
|
10
12
|
// dom('div', hide(true)); // OK
|
|
11
13
|
// dom('div', {title: 'hello'}); // OK
|
|
@@ -17,6 +19,10 @@ const browserGlobals_1 = require("./browserGlobals");
|
|
|
17
19
|
* The first argument is a string consisting of a tag name, with optional #foo suffix
|
|
18
20
|
* to add the ID 'foo', and zero or more .bar suffixes to add a CSS class 'bar'.
|
|
19
21
|
*
|
|
22
|
+
* NOTE that better typings are available when a tag is used directly, e.g.
|
|
23
|
+
* dom('input', {id: 'foo'}, (elem) => ...) --> elem has type HTMLInputElement
|
|
24
|
+
* dom('input#foo', (elem) => ...) --> elem has type HTMLElement
|
|
25
|
+
*
|
|
20
26
|
* The rest of the arguments are optional and may be:
|
|
21
27
|
*
|
|
22
28
|
* Nodes - which become children of the created element;
|
|
@@ -90,22 +96,33 @@ function _createFromTagString(createFunc, tagString) {
|
|
|
90
96
|
}
|
|
91
97
|
return elem;
|
|
92
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Update an element with any number of arguments, as documented in dom().
|
|
101
|
+
*/
|
|
93
102
|
function update(elem, ...args) {
|
|
94
103
|
return _updateWithArgs(elem, args);
|
|
95
104
|
}
|
|
96
105
|
exports.update = update;
|
|
106
|
+
/**
|
|
107
|
+
* Update an element with an array of arguments.
|
|
108
|
+
*/
|
|
97
109
|
function _updateWithArgs(elem, args) {
|
|
98
110
|
for (const arg of args) {
|
|
99
111
|
_updateWithArg(elem, arg);
|
|
100
112
|
}
|
|
101
113
|
return elem;
|
|
102
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Update an element with an array of arguments, calling disposers in case of an exception. It is
|
|
117
|
+
* an internal helper to be used whenever elem is a newly-created element. If elem is an existing
|
|
118
|
+
* element which the user already knows about, then _updateWithArgs should be called.
|
|
119
|
+
*/
|
|
103
120
|
function _updateWithArgsOrDispose(elem, args) {
|
|
104
121
|
try {
|
|
105
122
|
return _updateWithArgs(elem, args);
|
|
106
123
|
}
|
|
107
124
|
catch (e) {
|
|
108
|
-
|
|
125
|
+
domDispose_1.domDispose(elem);
|
|
109
126
|
throw e;
|
|
110
127
|
}
|
|
111
128
|
}
|
|
@@ -127,7 +144,7 @@ function _updateWithArg(elem, arg) {
|
|
|
127
144
|
elem.appendChild(arg);
|
|
128
145
|
}
|
|
129
146
|
else if (typeof arg === 'object') {
|
|
130
|
-
|
|
147
|
+
domMethods_1.attrsElem(elem, arg);
|
|
131
148
|
}
|
|
132
149
|
else {
|
|
133
150
|
elem.appendChild(browserGlobals_1.G.document.createTextNode(arg));
|
|
@@ -151,4 +168,4 @@ exports.find = find;
|
|
|
151
168
|
*/
|
|
152
169
|
function findAll(selector) { return browserGlobals_1.G.document.querySelectorAll(selector); }
|
|
153
170
|
exports.findAll = findAll;
|
|
154
|
-
//# sourceMappingURL=
|
|
171
|
+
//# sourceMappingURL=domImpl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domImpl.js","sourceRoot":"","sources":["../../../lib/domImpl.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DomArg, DomElementMethod, DomMethod, IAttrObj } from './_domImpl';
|
|
2
1
|
import { BindableValue } from './binding';
|
|
2
|
+
import { DomElementMethod, DomMethod, IAttrObj } from './domImpl';
|
|
3
3
|
/**
|
|
4
4
|
* Sets multiple attributes of a DOM element. The `attrs()` variant takes no `elem` argument.
|
|
5
5
|
* Null and undefined values are omitted, and booleans are either omitted or set to empty string.
|
|
@@ -60,7 +60,7 @@ export declare function prop<T>(property: string, valueObs: BindableValue<T>): D
|
|
|
60
60
|
* @param {Element} elem: The element to update.
|
|
61
61
|
* @param {Boolean} boolValue: True to show the element, false to hide it.
|
|
62
62
|
*/
|
|
63
|
-
export declare function showElem(elem:
|
|
63
|
+
export declare function showElem(elem: HTMLElement, boolValue: boolean): void;
|
|
64
64
|
export declare function show(boolValueObs: BindableValue<boolean>): DomElementMethod;
|
|
65
65
|
/**
|
|
66
66
|
* The opposite of show, hiding the element when boolValue is true.
|
|
@@ -68,7 +68,7 @@ export declare function show(boolValueObs: BindableValue<boolean>): DomElementMe
|
|
|
68
68
|
* @param {Element} elem: The element to update.
|
|
69
69
|
* @param {Boolean} boolValue: True to hide the element, false to show it.
|
|
70
70
|
*/
|
|
71
|
-
export declare function hideElem(elem:
|
|
71
|
+
export declare function hideElem(elem: HTMLElement, boolValue: boolean): void;
|
|
72
72
|
export declare function hide(boolValueObs: BindableValue<boolean>): DomElementMethod;
|
|
73
73
|
/**
|
|
74
74
|
* Sets or toggles the given css class className.
|
|
@@ -103,73 +103,38 @@ export declare function dataElem(elem: Node, key: string, value: any): void;
|
|
|
103
103
|
export declare function data(key: string, valueObs: BindableValue<any>): DomMethod;
|
|
104
104
|
export declare function getData(elem: Node, key: string): any;
|
|
105
105
|
/**
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* to insert nothing. Runs disposers, if any, on all removed content.
|
|
109
|
-
*/
|
|
110
|
-
export declare function replaceContent(nodeBefore: Node, nodeAfter: Node, content: DomArg): void;
|
|
111
|
-
/**
|
|
112
|
-
* Appends dynamic DOM content to an element. The value may be an observable or function (from
|
|
113
|
-
* which a computed is created), whose value will be passed to `contentFunc` which should return
|
|
114
|
-
* DOM content. If the contentFunc is omitted, it defaults to identity, i.e. it's OK for the
|
|
115
|
-
* observable or function to return DOM directly.
|
|
116
|
-
*
|
|
117
|
-
* The DOM content returned may be an element, string, array, or null. Whenever the observable
|
|
118
|
-
* changes, previous content is disposed and removed, and new content added in its place.
|
|
106
|
+
* A very simple setup to identify DOM elements for testing purposes. Here's the recommended
|
|
107
|
+
* usage.
|
|
119
108
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* (B) domComputed(use => use(nlinesObs) > 1, isTall => isTall ? dom('textarea') : dom('input'));
|
|
123
|
-
* (C) domComputed(use => use(nlinesObs) > 1 ? dom('textarea') : dom('input'));
|
|
109
|
+
* // In the component to be tested.
|
|
110
|
+
* import {noTestId, TestId} from 'grainjs';
|
|
124
111
|
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
112
|
+
* function myComponent(myArgs, testId: TestId = noTestId) {
|
|
113
|
+
* return dom(..., testId("some-name"),
|
|
114
|
+
* dom(..., testId("another-name"), ...),
|
|
115
|
+
* );
|
|
116
|
+
* }
|
|
129
117
|
*
|
|
130
|
-
*
|
|
131
|
-
* observables, e.g.
|
|
118
|
+
* In the fixture code using this component:
|
|
132
119
|
*
|
|
133
|
-
*
|
|
134
|
-
* (use(nlinesObs) > 1 ? dom('textarea') : dom('input')));
|
|
120
|
+
* import {makeTestId} from 'grainjs';
|
|
135
121
|
*
|
|
136
|
-
*
|
|
137
|
-
* are equivalent:
|
|
122
|
+
* dom(..., myComponent(myArgs, makeTestId('test-mycomp-'), ...)
|
|
138
123
|
*
|
|
139
|
-
*
|
|
140
|
-
* dom(..., listValue.map(x => dom('div', x)), ...)
|
|
124
|
+
* In the webdriver test code:
|
|
141
125
|
*
|
|
142
|
-
*
|
|
126
|
+
* driver.find('.test-my-comp-some-name')
|
|
127
|
+
* driver.find('.test-my-comp-another-name')
|
|
143
128
|
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* @param [Function] contentFunc: Function called with the result of valueObs as the input, and
|
|
147
|
-
* returning DOM as output. If omitted, defaults to the identity function.
|
|
129
|
+
* When myComponent() is created with testId argument omitted, the testId() calls are no-ops. When
|
|
130
|
+
* makeTestId('test-foo-') is passed in, testId() calls simply add a css class with that prefix.
|
|
148
131
|
*/
|
|
149
|
-
export declare
|
|
150
|
-
export declare function domComputed<T>(valueObs: BindableValue<T>, contentFunc: (val: T) => DomArg): DomMethod;
|
|
132
|
+
export declare type TestId = (name: string) => DomElementMethod | null;
|
|
151
133
|
/**
|
|
152
|
-
*
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
*
|
|
157
|
-
* for each value, and previous content gets destroyed. To consider all truthy values the same,
|
|
158
|
-
* use an observable that returns a proper boolean, e.g.
|
|
159
|
-
*
|
|
160
|
-
* dom.maybe(use => Boolean(use(fooObs)), () => dom(...));
|
|
161
|
-
*
|
|
162
|
-
* As with domComputed(), dom.maybe() may but should not be used when the argument is not an
|
|
163
|
-
* observable or function. The following are equivalent:
|
|
164
|
-
*
|
|
165
|
-
* dom(..., dom.maybe(myValue, () => dom(...)));
|
|
166
|
-
* dom(..., myValue ? dom(...) : null);
|
|
167
|
-
*
|
|
168
|
-
* The latter is preferred for being simpler.
|
|
169
|
-
*
|
|
170
|
-
* @param {Element} elem: The element to which to append the DOM content.
|
|
171
|
-
* @param {Object} boolValueObs: Observable or function for a computed.
|
|
172
|
-
* @param [Function] contentFunc: Function called with the result of boolValueObs when it is
|
|
173
|
-
* truthy. Should returning DOM as output.
|
|
134
|
+
* See documentation for TestId above.
|
|
135
|
+
*/
|
|
136
|
+
export declare function makeTestId(prefix: string): TestId;
|
|
137
|
+
/**
|
|
138
|
+
* See documentation for TestId above.
|
|
174
139
|
*/
|
|
175
|
-
export declare
|
|
140
|
+
export declare const noTestId: TestId;
|