@@ -39,7 +39,7 @@ export class ScullyContentComponent implements OnInit, OnDestroy {
3939 @Input ( ) type = 'MD' ;
4040
4141 elm = this . elmRef . nativeElement as HTMLElement ;
42- mutationSubscription : Subscription ;
42+ // mutationSubscription: Subscription;
4343 routes = this . srs . available$ . pipe ( take ( 1 ) ) . toPromise ( ) ;
4444
4545 constructor (
@@ -53,10 +53,15 @@ export class ScullyContentComponent implements OnInit, OnDestroy {
5353 /** make sure the idle-check is loaded. */
5454 this . idle . init ( ) ;
5555 if ( this . elm ) {
56+ /** this will only fire in a browser environment */
5657 this . handlePage ( ) ;
5758 }
5859 }
5960
61+ /**
62+ * Loads the static content from scully into the view
63+ * Will fetch the content from sibling links with xmlHTTPrequest
64+ */
6065 private async handlePage ( ) {
6166 const template = document . createElement ( 'template' ) ;
6267 // tslint:disable-next-line: no-string-literal
@@ -66,17 +71,25 @@ export class ScullyContentComponent implements OnInit, OnDestroy {
6671 template . innerHTML = window [ 'scullyContent' ] ;
6772 } else {
6873 const curPage = location . href ;
74+ /**
75+ * NOTE
76+ * when updateting the texts for the errors, make sure you leave the
77+ * `id="___scully-parsing-error___"`
78+ * in there. That way users can detect rendering errors in their CI
79+ * on a reliable way.
80+ */
6981 await fetchHttp ( curPage , 'text' )
7082 . then ( ( html : string ) => {
7183 try {
7284 template . innerHTML = html . split ( scullyBegin ) [ 1 ] . split ( scullyEnd ) [ 0 ] ;
7385 } catch ( e ) {
74- template . innerHTML = `<h2>Sorry, could not parse static page content</h2>
86+ template . innerHTML = `<h2 id="___scully-parsing-error___" >Sorry, could not parse static page content</h2>
7587 <p>This might happen if you are not using the static generated pages.</p>` ;
7688 }
7789 } )
7890 . catch ( e => {
79- template . innerHTML = '<h2>Sorry, could not load static page content</h2>' ;
91+ template . innerHTML =
92+ '<h2 id="___scully-parsing-error___">Sorry, could not load static page content</h2>' ;
8093 console . error ( 'problem during loading static scully content' , e ) ;
8194 } ) ;
8295 }
@@ -86,24 +99,45 @@ export class ScullyContentComponent implements OnInit, OnDestroy {
8699 parent . insertBefore ( begin , this . elm ) ;
87100 parent . insertBefore ( template . content , this . elm ) ;
88101 parent . insertBefore ( end , this . elm ) ;
102+ /** upgrade all hrefs to simulated routelinks */
89103 document . querySelectorAll ( '[href]' ) . forEach ( this . upgradeToRoutelink . bind ( this ) ) ;
90104 }
91105
106+ /**
107+ * upgrade a **href** attributes to links that respect the Angular router
108+ * and don't do a full page reload. Only works on links that are found in the
109+ * Scully route config file.
110+ * @param elm the element containing the **hrefs**
111+ */
92112 async upgradeToRoutelink ( elm : HTMLElement ) {
93113 const routes = await this . routes ;
94114 const lnk = elm . getAttribute ( 'href' ) . toLowerCase ( ) ;
95115 const route = routes . find ( r => r . route . toLowerCase ( ) === lnk ) ;
116+ /** only upgrade routes known by scully. */
96117 if ( lnk && route ) {
97- elm . onclick = ( ev : MouseEvent ) => {
118+ elm . onclick = async ( ev : MouseEvent ) => {
98119 const splitRoute = route . route . split ( `/` ) ;
99120 const curSplit = location . pathname . split ( '/' ) ;
100121 // loose last "part" of route
101122 curSplit . pop ( ) ;
102123
103124 ev . preventDefault ( ) ;
104- this . router . navigate ( splitRoute ) . catch ( e => console . error ( 'routing error' , e ) ) ;
125+ const routed = await this . router . navigate ( splitRoute ) . catch ( e => {
126+ console . error ( 'routing error' , e ) ;
127+ return false ;
128+ } ) ;
129+ if ( ! routed ) {
130+ return ;
131+ }
132+ /** delete the content, as it is now out of date! */
133+ window [ 'scullyContent' ] = undefined ;
105134 /** check for the same route with different "data", and NOT a level higher (length) */
106135 if ( curSplit . every ( ( part , i ) => splitRoute [ i ] === part ) && splitRoute . length > curSplit . length ) {
136+ /**
137+ * as Angular doesn't destroy the component if we stay on the same page,
138+ * we have to manually delete old content. Also we need to kick of loading
139+ * the new content. handlePage() takes care of that.
140+ */
107141 setTimeout ( ( ) => {
108142 const p = this . elm . parentElement ;
109143 let cur = findComments ( p , 'scullyContent-begin' ) [ 0 ] as HTMLElement ;
@@ -114,21 +148,26 @@ export class ScullyContentComponent implements OnInit, OnDestroy {
114148 cur = next ;
115149 } while ( next && next !== this . elm ) ;
116150 // tslint:disable-next-line: no-string-literal
117- window [ 'scullyContent' ] = undefined ;
118151 this . handlePage ( ) ;
119- } , 20 ) ;
152+ } , 10 ) ; // a small delay, so we are sure the angular parts in the page are settled enough
120153 }
121154 } ;
122155 }
123156 }
124157
125158 ngOnDestroy ( ) {
126- if ( this . mutationSubscription ) {
127- this . mutationSubscription . unsubscribe ( ) ;
128- }
159+ // if (this.mutationSubscription) {
160+ // this.mutationSubscription.unsubscribe();
161+ // }
129162 }
130163}
131164
165+ /**
166+ * Returns an observable that fires a mutation when the domMutationObserves does that.
167+ * if flattens the mutations to make handling easier, so you only get 1 mutationRecord at a time.
168+ * @param elm the elm to obse with a mutationObserver
169+ * @param config the config for the mutationobserver
170+ */
132171export function fromMutationObserver (
133172 elm : HTMLElement ,
134173 config : MutationObserverInit
@@ -140,6 +179,12 @@ export function fromMutationObserver(
140179 } ) ;
141180}
142181
182+ /**
183+ * Returns an array of nodes coninting all the html comments in the element.
184+ * When a searchText is given this is narrowed down to only comments that contian this text
185+ * @param rootElem Element to search nto
186+ * @param searchText optional string that needs to be in a HTML comment
187+ */
143188function findComments ( rootElem : HTMLElement , searchText ?: string ) {
144189 const comments = [ ] ;
145190 // Fourth argument, which is actually obsolete according to the DOM4 standard, seems required in IE 11
@@ -150,7 +195,7 @@ function findComments(rootElem: HTMLElement, searchText?: string) {
150195 acceptNode : node => {
151196 // Logic to determine whether to accept, reject or skip node
152197 // In this case, only accept nodes that have content
153- // other than whitespace
198+ // that is containing our searchText, by rejecting any other nodes.
154199 if ( searchText && node . nodeValue && ! node . nodeValue . includes ( searchText ) ) {
155200 return NodeFilter . FILTER_REJECT ;
156201 }
0 commit comments