1+ //
2+ // Actions to be executed after the document has been loaded.
3+
4+ let executionQueue = [ ] ;
5+
6+ let ready = false ;
7+
8+ function executeQueue ( ) {
9+ executionQueue . forEach ( ( fn ) => fn ( ) ) ;
10+ ready = true ;
11+ }
12+
13+ //
14+ // Different kinds of documents.
15+
16+ /**
17+ * A Quarkdown document, inherited by each specific document type.
18+ */
19+ class QuarkdownDocument {
20+ pageMarginInitializers ;
21+
22+ /**
23+ * Prepares the stages of the document runtime.
24+ */
25+ prepare ( ) {
26+ this . populateExecutionQueue ( ) ;
27+ this . setupBeforeReadyHook ( ) ;
28+ this . setupAfterReadyHook ( ) ;
29+ }
30+
31+ /**
32+ * Hook to be executed before the document is ready.
33+ * For instance, this is run before paged.js or Reveal.js processes the content.
34+ * @param content pre-processed content
35+ */
36+ beforeReady ( content ) {
37+ // A page margin content initializer is an element that will be copied into each section,
38+ // and is placed on one of the page margins.
39+ this . pageMarginInitializers = content . querySelectorAll ( '.page-margin-content' ) ;
40+ }
41+
42+ /**
43+ * Removes all page margin initializers from the document.
44+ */
45+ removeAllPageMarginInitializers ( ) {
46+ this . pageMarginInitializers . forEach ( initializer => initializer . remove ( ) ) ;
47+ }
48+
49+ /**
50+ * To be run after the document is ready.
51+ * This pastes the previously-loaded page margin initializers into each new processed page.
52+ */
53+ copyPageMarginInitializers ( ) {
54+ if ( ! this . pageMarginInitializers ) {
55+ console . error ( 'pageMarginInitializers not set' ) ;
56+ }
57+ }
58+
59+ /**
60+ * Updates the content of `.current-page-number` and `.total-page-number` elements.
61+ */
62+ updatePageNumberElements ( ) { }
63+
64+ /**
65+ * Populates the execution queue with the necessary functions to be executed after the document is ready.
66+ */
67+ populateExecutionQueue ( ) {
68+ executionQueue . push (
69+ ( ) => this . copyPageMarginInitializers ( ) ,
70+ ( ) => this . updatePageNumberElements ( )
71+ ) ;
72+ }
73+
74+ /**
75+ * Sets up a hook called before the document is processed.
76+ */
77+ setupBeforeReadyHook ( ) {
78+ document . addEventListener ( 'DOMContentLoaded' , ( ) => this . beforeReady ( document ) ) ;
79+ }
80+
81+ /**
82+ * Sets up a hook called after the document is processed.
83+ */
84+ setupAfterReadyHook ( ) {
85+ document . addEventListener ( 'DOMContentLoaded' , executeQueue ) ;
86+ }
87+ }
88+
89+ class PlainDocument extends QuarkdownDocument { }
90+
91+ let doc = new PlainDocument ( ) ; // Overridden externally by html-wrapper
92+
93+ //
94+ // Enables toggling of the collapsed/expanded state of inline elements.
95+
96+ executionQueue . push ( ( ) => {
97+ // Add click event listener to the collapsible spans.
98+ const collapsibles = document . querySelectorAll ( '.inline-collapse' ) ;
99+ collapsibles . forEach ( ( span ) => {
100+ span . addEventListener ( 'click' , ( ) => toggleCollapse ( span ) ) ;
101+ } ) ;
102+ } ) ;
103+
104+ function toggleCollapse ( span ) {
105+ const fullText = span . dataset . fullText ;
106+ const collapsedText = span . dataset . collapsedText ;
107+ const collapsed = span . dataset . collapsed === 'true' ;
108+
109+ // Toggle between the full and collapsed text.
110+ const content = collapsed ? fullText : collapsedText ;
111+
112+ span . dataset . collapsed = ( ! collapsed ) . toString ( ) ;
113+
114+ const isUserDefined = span . closest ( '.error' ) === null ;
115+ if ( isUserDefined ) {
116+ span . innerHTML = content ;
117+ } else {
118+ span . textContent = content ;
119+ }
120+ }
0 commit comments