@@ -51,6 +51,7 @@ export interface RawAttributes {
51
51
}
52
52
53
53
export type InsertPosition = 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend' ;
54
+ export type NodeInsertable = Node | string ;
54
55
55
56
// https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
56
57
const Htags = [ 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' , 'header' , 'hgroup' ] ;
@@ -643,29 +644,10 @@ export default class HTMLElement extends Node {
643
644
* @return {Node } node appended
644
645
*/
645
646
public appendChild < T extends Node = Node > ( node : T ) {
646
- // remove the node from it's parent
647
- node . remove ( ) ;
648
- this . childNodes . push ( node ) ;
649
- node . parentNode = this ;
647
+ this . append ( node ) ;
650
648
return node ;
651
649
}
652
650
653
- /**
654
- * Get first child node
655
- * @return {Node | undefined } first child node; or undefined if none
656
- */
657
- public get firstChild ( ) : Node | undefined {
658
- return this . childNodes [ 0 ] ;
659
- }
660
-
661
- /**
662
- * Get last child node
663
- * @return {Node | undefined } last child node; or undefined if none
664
- */
665
- public get lastChild ( ) : Node | undefined {
666
- return arr_back ( this . childNodes ) ;
667
- }
668
-
669
651
/**
670
652
* Get attributes
671
653
* @access private
@@ -818,33 +800,46 @@ export default class HTMLElement extends Node {
818
800
}
819
801
const p = parse ( html , this . _parseOptions ) ;
820
802
if ( where === 'afterend' ) {
821
- const idx = this . parentNode . childNodes . findIndex ( ( child ) => {
822
- return child === this ;
823
- } ) ;
824
- resetParent ( p . childNodes , this . parentNode ) ;
825
- this . parentNode . childNodes . splice ( idx + 1 , 0 , ...p . childNodes ) ;
803
+ this . after ( ...p . childNodes ) ;
826
804
} else if ( where === 'afterbegin' ) {
827
- resetParent ( p . childNodes , this ) ;
828
- this . childNodes . unshift ( ...p . childNodes ) ;
805
+ this . prepend ( ...p . childNodes ) ;
829
806
} else if ( where === 'beforeend' ) {
830
- p . childNodes . forEach ( ( n ) => {
831
- this . appendChild ( n ) ;
832
- } ) ;
807
+ this . append ( ...p . childNodes ) ;
833
808
} else if ( where === 'beforebegin' ) {
834
- const idx = this . parentNode . childNodes . findIndex ( ( child ) => {
835
- return child === this ;
836
- } ) ;
837
- resetParent ( p . childNodes , this . parentNode ) ;
838
- this . parentNode . childNodes . splice ( idx , 0 , ...p . childNodes ) ;
809
+ this . before ( ...p . childNodes ) ;
839
810
} else {
840
811
throw new Error (
841
812
`The value provided ('${ where as string } ') is not one of 'beforebegin', 'afterbegin', 'beforeend', or 'afterend'`
842
813
) ;
843
814
}
844
815
return this ;
845
- // if (!where || html === undefined || html === null) {
846
- // return;
847
- // }
816
+ }
817
+
818
+ /** Prepend nodes or strings to this node's children. */
819
+ public prepend ( ...insertable : NodeInsertable [ ] ) {
820
+ const nodes = resolveInsertable ( insertable ) ;
821
+ resetParent ( nodes , this ) ;
822
+ this . childNodes . unshift ( ...nodes ) ;
823
+ }
824
+ /** Append nodes or strings to this node's children. */
825
+ public append ( ...insertable : NodeInsertable [ ] ) {
826
+ const nodes = resolveInsertable ( insertable ) ;
827
+ resetParent ( nodes , this ) ;
828
+ this . childNodes . push ( ...nodes ) ;
829
+ }
830
+ /** Insert nodes or strings before this node. */
831
+ public before ( ...insertable : NodeInsertable [ ] ) {
832
+ const nodes = resolveInsertable ( insertable ) ;
833
+ const siblings = this . parentNode . childNodes ;
834
+ resetParent ( nodes , this . parentNode ) ;
835
+ siblings . splice ( siblings . indexOf ( this ) , 0 , ...nodes ) ;
836
+ }
837
+ /** Insert nodes or strings after this node. */
838
+ public after ( ...insertable : NodeInsertable [ ] ) {
839
+ const nodes = resolveInsertable ( insertable ) ;
840
+ const siblings = this . parentNode . childNodes ;
841
+ resetParent ( nodes , this . parentNode ) ;
842
+ siblings . splice ( siblings . indexOf ( this ) + 1 , 0 , ...nodes ) ;
848
843
}
849
844
850
845
public get nextSibling ( ) : Node | null {
@@ -909,13 +904,56 @@ export default class HTMLElement extends Node {
909
904
}
910
905
}
911
906
912
- public get classNames ( ) {
913
- return this . classList . toString ( ) ;
907
+ /** Get all childNodes of type {@link HTMLElement}. */
908
+ public get children ( ) : HTMLElement [ ] {
909
+ const children = [ ] ;
910
+ for ( const childNode of this . childNodes ) {
911
+ if ( childNode instanceof HTMLElement ) {
912
+ children . push ( childNode ) ;
913
+ }
914
+ }
915
+ return children ;
916
+ }
917
+
918
+ /**
919
+ * Get the first child node.
920
+ * @return The first child or undefined if none exists.
921
+ */
922
+ public get firstChild ( ) : Node | undefined {
923
+ return this . childNodes [ 0 ] ;
924
+ }
925
+ /**
926
+ * Get the first child node of type {@link HTMLElement}.
927
+ * @return The first child element or undefined if none exists.
928
+ */
929
+ public get firstElementChild ( ) : HTMLElement | undefined {
930
+ return this . children [ 0 ] ;
914
931
}
915
932
916
933
/**
917
- * Clone this Node
934
+ * Get the last child node.
935
+ * @return The last child or undefined if none exists.
918
936
*/
937
+ public get lastChild ( ) : Node | undefined {
938
+ return arr_back ( this . childNodes ) ;
939
+ }
940
+ /**
941
+ * Get the last child node of type {@link HTMLElement}.
942
+ * @return The last child element or undefined if none exists.
943
+ */
944
+ public get lastElementChild ( ) : HTMLElement | undefined {
945
+ return this . children [ this . children . length - 1 ] ;
946
+ }
947
+
948
+ public get childElementCount ( ) : number {
949
+ return this . children . length ;
950
+ }
951
+
952
+ public get classNames ( ) {
953
+ return this . classList . toString ( ) ;
954
+ }
955
+
956
+ /** Clone this Node */
919
957
public clone ( ) {
920
958
return parse ( this . toString ( ) , this . _parseOptions ) . firstChild ;
921
959
}
@@ -1204,6 +1242,20 @@ export function parse(data: string, options = {} as Partial<Options>) {
1204
1242
return root ;
1205
1243
}
1206
1244
1245
+ /**
1246
+ * Resolves a list of {@link NodeInsertable} to a list of nodes,
1247
+ * and removes nodes from any potential parent.
1248
+ */
1249
+ function resolveInsertable ( insertable : NodeInsertable [ ] ) : Node [ ] {
1250
+ return insertable . map ( val => {
1251
+ if ( typeof val === 'string' ) {
1252
+ return new TextNode ( val ) ;
1253
+ }
1254
+ val . remove ( ) ;
1255
+ return val ;
1256
+ } ) ;
1257
+ }
1258
+
1207
1259
function resetParent ( nodes : Node [ ] , parent : HTMLElement ) {
1208
1260
return nodes . map ( ( node ) => {
1209
1261
node . parentNode = parent ;
0 commit comments