@@ -83,18 +83,63 @@ export class PrintHook {
83
83
return mergeAlias ( event , bp ) ;
84
84
}
85
85
86
+
87
+ // registeredBeforeAfterPrintHooks tracks if we registered the `beforeprint`
88
+ // and `afterprint` event listeners.
89
+ private registeredBeforeAfterPrintHooks : boolean = false ;
90
+
91
+ // isPrintingBeforeAfterEvent is used to track if we are printing from within
92
+ // a `beforeprint` event handler. This prevents the typicall `stopPrinting`
93
+ // form `interceptEvents` so that printing is not stopped while the dialog
94
+ // is still open. This is an extension of the `isPrinting` property on
95
+ // browsers which support `beforeprint` and `afterprint` events.
96
+ private isPrintingBeforeAfterEvent : boolean = false ;
97
+
98
+ private registerBeforeAfterPrintHooks ( target : HookTarget ) {
99
+ // Register a `beforeprint` event hook so we can trigger print styles
100
+ // synchronously and apply proper layout styles.
101
+ if ( this . registeredBeforeAfterPrintHooks ) {
102
+ return ;
103
+ }
104
+
105
+ this . registeredBeforeAfterPrintHooks = true ;
106
+
107
+ // Could we have teardown logic to remove if there are no print listeners being used?
108
+ window . addEventListener ( 'beforeprint' , ( ) => {
109
+ // If we aren't already printing, start printing and update the styles as
110
+ // if there was a regular print `MediaChange`(from matchMedia).
111
+ if ( ! this . isPrinting ) {
112
+ this . isPrintingBeforeAfterEvent = true ;
113
+ this . startPrinting ( target , this . getEventBreakpoints ( new MediaChange ( true , PRINT ) ) ) ;
114
+ target . updateStyles ( ) ;
115
+ }
116
+ } ) ;
117
+
118
+ window . addEventListener ( 'afterprint' , ( ) => {
119
+ // If we aren't already printing, start printing and update the styles as
120
+ // if there was a regular print `MediaChange`(from matchMedia).
121
+ this . isPrintingBeforeAfterEvent = false ;
122
+ if ( this . isPrinting ) {
123
+ this . stopPrinting ( target ) ;
124
+ target . updateStyles ( ) ;
125
+ }
126
+ } ) ;
127
+ }
128
+
86
129
/**
87
130
* Prepare RxJs filter operator with partial application
88
131
* @return pipeable filter predicate
89
132
*/
90
133
interceptEvents ( target : HookTarget ) {
134
+ this . registerBeforeAfterPrintHooks ( target ) ;
135
+
91
136
return ( event : MediaChange ) => {
92
137
if ( this . isPrintEvent ( event ) ) {
93
138
if ( event . matches && ! this . isPrinting ) {
94
139
this . startPrinting ( target , this . getEventBreakpoints ( event ) ) ;
95
140
target . updateStyles ( ) ;
96
141
97
- } else if ( ! event . matches && this . isPrinting ) {
142
+ } else if ( ! event . matches && this . isPrinting && ! this . isPrintingBeforeAfterEvent ) {
98
143
this . stopPrinting ( target ) ;
99
144
target . updateStyles ( ) ;
100
145
}
@@ -131,7 +176,8 @@ export class PrintHook {
131
176
/**
132
177
* To restore pre-Print Activations, we must capture the proper
133
178
* list of breakpoint activations BEFORE print starts. OnBeforePrint()
134
- * is not supported; so 'print' mediaQuery activations must be used.
179
+ * is supported; so 'print' mediaQuery activations are used as a fallback
180
+ * in browsers without `beforeprint` support.
135
181
*
136
182
* > But activated breakpoints are deactivated BEFORE 'print' activation.
137
183
*
@@ -146,14 +192,17 @@ export class PrintHook {
146
192
* - restore as activatedTargets and clear when stop printing
147
193
*/
148
194
collectActivations ( event : MediaChange ) {
149
- if ( ! this . isPrinting ) {
195
+ if ( ! this . isPrinting || this . isPrintingBeforeAfterEvent ) {
150
196
if ( ! event . matches ) {
151
197
const bp = this . breakpoints . findByQuery ( event . mediaQuery ) ;
152
198
if ( bp ) { // Deactivating a breakpoint
153
199
this . deactivations . push ( bp ) ;
154
200
this . deactivations . sort ( sortDescendingPriority ) ;
155
201
}
156
- } else {
202
+ } else if ( ! this . isPrintingBeforeAfterEvent ) {
203
+ // Only clear deactivations if we aren't printing from a `beforeprint` event.
204
+ // Otherwise this will clear before `stopPrinting()` is called to restore
205
+ // the pre-Print Activations.
157
206
this . deactivations = [ ] ;
158
207
}
159
208
}
0 commit comments