Skip to content

Commit 374764d

Browse files
author
jin
committed
$mol_dom_point, $mol_dom_range, $mol_dom = $mol_dom_context
1 parent 32ba95f commit 374764d

File tree

3 files changed

+172
-0
lines changed

3 files changed

+172
-0
lines changed

dom/dom.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace $ {
2+
3+
export var $mol_dom = $mol_dom_context
4+
5+
}

dom/point/point.ts

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
namespace $ {
2+
3+
export class $mol_dom_point extends Object {
4+
5+
constructor(
6+
public node: Node,
7+
public pos: number,
8+
) { super() }
9+
10+
static start( node: Node ) {
11+
return new this( node, 0 )
12+
}
13+
14+
static end( node: Node ) {
15+
const length = node.nodeValue?.length ?? node.childNodes.length
16+
return new this( node, length )
17+
}
18+
19+
to( point: $mol_dom_point ) {
20+
this.node = point.node
21+
this.pos = point.pos
22+
}
23+
24+
to_start() {
25+
this.pos = 0
26+
return this
27+
}
28+
29+
to_end() {
30+
this.pos = this.node.nodeValue?.length ?? this.node.childNodes.length
31+
return this
32+
}
33+
34+
is_start() {
35+
return this.pos <= 0
36+
}
37+
38+
is_end() {
39+
return this.pos >= ( this.node.nodeValue?.length ?? this.node.childNodes.length )
40+
}
41+
42+
char_backward( root: Element ): $mol_dom_point {
43+
return this.backward( ()=> {
44+
if( this.node === root && this.is_start() ) return true
45+
if( this.node.nodeType !== this.node.TEXT_NODE ) return false
46+
if( this.is_start() ) return false
47+
this.pos -= 1
48+
return true
49+
} )
50+
}
51+
52+
char_forward( root: Element ): $mol_dom_point {
53+
return this.forward( ()=> {
54+
if( this.node === root && this.is_end() ) return true
55+
if( this.node.nodeType !== this.node.TEXT_NODE ) return false
56+
if( this.is_end() ) return false
57+
this.pos += 1
58+
return true
59+
} )
60+
}
61+
62+
backward( check: ()=> boolean ): $mol_dom_point {
63+
64+
if( check() ) return this
65+
66+
if( !this.is_start() ) {
67+
const kid = this.node.childNodes[ this.pos - 1 ]
68+
this.node = kid
69+
this.to_end()
70+
return this.backward( check )
71+
}
72+
73+
const parent = this.node.parentElement
74+
if( !parent ) return this
75+
76+
const offset = [ ... parent.childNodes ].indexOf( this.node as ChildNode )
77+
this.node = parent
78+
this.pos = offset
79+
return this.backward( check )
80+
81+
}
82+
83+
forward( check: ()=> boolean ): $mol_dom_point {
84+
85+
if( check() ) return this
86+
87+
if( !this.is_end() ) {
88+
const kid = this.node.childNodes[ this.pos ]
89+
this.node = kid
90+
this.to_start()
91+
return this.forward( check )
92+
}
93+
94+
const parent = this.node.parentElement
95+
if( !parent ) return this
96+
97+
const offset = [ ... parent.childNodes ].indexOf( this.node as ChildNode ) + 1
98+
this.node = parent
99+
this.pos = offset
100+
return this.forward( check )
101+
102+
}
103+
104+
}
105+
106+
}

dom/range/range.ts

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
namespace $ {
2+
export class $mol_dom_range extends Object {
3+
4+
constructor(
5+
readonly head: $mol_dom_point,
6+
readonly foot: $mol_dom_point,
7+
) { super() }
8+
9+
static from_selection( sel = $mol_dom_context.getSelection()! ) {
10+
return this.from_native( sel?.getRangeAt(0) )
11+
}
12+
13+
static from_native( range: Range ) {
14+
return new this(
15+
new $mol_dom_point( range.startContainer, range.startOffset ),
16+
new $mol_dom_point( range.endContainer, range.endOffset ),
17+
)
18+
}
19+
20+
static inside( node: Node ) {
21+
return new this(
22+
$mol_dom_point.start( node ),
23+
$mol_dom_point.end( node ),
24+
)
25+
}
26+
27+
static around( node: Node ) {
28+
29+
const parent = node.parentNode!
30+
const pos = [ ... parent.childNodes ].indexOf( node as ChildNode )
31+
32+
return new this(
33+
new $mol_dom_point( parent, pos ),
34+
new $mol_dom_point( parent, pos + 1 ),
35+
)
36+
37+
}
38+
39+
is_empty() {
40+
return this.head.node === this.foot.node && this.head.pos === this.foot.pos
41+
}
42+
43+
clear() {
44+
this.native().deleteContents()
45+
}
46+
47+
select() {
48+
const sel = $mol_dom_context.document.getSelection()!
49+
sel.removeAllRanges()
50+
sel.addRange( this.native() )
51+
}
52+
53+
native() {
54+
const range = $mol_dom_context.document.createRange()
55+
range.setEnd( this.foot.node, this.foot.pos )
56+
range.setStart( this.head.node, this.head.pos )
57+
return range
58+
}
59+
60+
}
61+
}

0 commit comments

Comments
 (0)