Skip to content
This repository has been archived by the owner on Jan 6, 2025. It is now read-only.

feat(core): add print support with mediaQuery override #954

Merged
merged 4 commits into from
Jan 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/documentation/BreakPoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import {BREAKPOINT} from '@angular/flex-layout';
const PRINT_BREAKPOINTS = [{
alias: 'xs.print',
suffix: 'XsPrint',
mediaQuery: 'print and (max-width: 297px)',
mediaQuery: 'screen and (max-width: 297px)',
overlapping: false
}];

Expand Down Expand Up @@ -157,4 +157,4 @@ export class CustomShowHideDirective extends ShowHideDirective {
this._cacheInput("showXsPrint", negativeOf(val));
}
}
```
```
2 changes: 1 addition & 1 deletion docs/documentation/fxHide-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ e.g.
### Using Responsive API

When a mediaQuery range activates, the directive instances will be notified. If the current activate mediaQuery range
When a mediaQuery range activates, the directive instances will be notified. If the current activated mediaQuery range
(and its associated alias) are not used, then the static API value is restored as the fallback value.

The *fallback* solution uses a **`largest_range-to-smallest_range`** search algorithm. Consider the following:
Expand Down
2 changes: 1 addition & 1 deletion docs/documentation/fxShow-API.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ e.g.
### Using Responsive API

When a mediaQuery range activates, the directive instances will be notified. If the current activate mediaQuery range
When a mediaQuery range activates, the directive instances will be notified. If the current activated mediaQuery range
(and its associated alias) are not used, then the static API value is restored as the fallback value.

The *fallback* solution uses a **`largest_range-to-smallest_range`** search algorithm. Consider the following:
Expand Down
6 changes: 5 additions & 1 deletion src/apps/demo-app/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ <h2>Layout Demos: </h2>
</span>
</div>
<div fxLayout="row"
fxLayoutAlign="start center"
fxLayoutGap="20px"
fxHide.print
style="height:40px; min-height:40px;">
<button mat-raised-button color="primary" [routerLink]="['']">
Static
Expand All @@ -30,4 +30,8 @@ <h2>Layout Demos: </h2>

<div class="demo-content">
<router-outlet></router-outlet>
<watermark
title="@angular/layout"
message="HTML Layouts w/ Flex and Grid CSS"
fxHide fxShow.print></watermark>
</div>
19 changes: 12 additions & 7 deletions src/apps/demo-app/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,31 @@ import {FlexLayoutModule, BREAKPOINT} from '@angular/flex-layout';
import {RoutingModule} from './routing.module';
import {AppComponent} from './app.component';
import {DemoMaterialModule} from './material.module';
import {WatermarkComponent} from './watermark.component';

const PRINT_BREAKPOINTS = [{
ThomasBurleson marked this conversation as resolved.
Show resolved Hide resolved
alias: 'xs.print',
suffix: 'XsPrint',
mediaQuery: 'print and (max-width: 297px)',
const EXTRA_BREAKPOINT = [{
alias: 'xs.landscape',
suffix: 'XsLandscape',
mediaQuery: 'screen and (orientation: landscape) and (max-width: 559px)',
priority: 1000,
overlapping: false
}];

@NgModule({
declarations: [
AppComponent,
AppComponent, WatermarkComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
BrowserAnimationsModule,
RoutingModule,
DemoMaterialModule,
FlexLayoutModule.withConfig({useColumnBasisZero: false}),
FlexLayoutModule.withConfig({
useColumnBasisZero: false,
printWithBreakpoints: ['md', 'lt-lg', 'lt-xl', 'gt-sm', 'gt-xs']
}),
],
providers: [{provide: BREAKPOINT, useValue: PRINT_BREAKPOINTS, multi: true}],
providers: [{provide: BREAKPOINT, useValue: EXTRA_BREAKPOINT, multi: true}],
bootstrap: [AppComponent]
})
export class AppModule { }
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {Component} from '@angular/core';
@Component({
selector: 'demo-docs-responsive',
template: `
<demo-responsive-layout-direction class='small-demo'> </demo-responsive-layout-direction>
<demo-responsive-layout-direction class='small-demo' fxHide.print>
</demo-responsive-layout-direction>
<demo-responsive-row-column class='small-demo'> </demo-responsive-row-column>
<demo-responsive-flex-directive class='small-demo'> </demo-responsive-flex-directive>
<demo-responsive-flex-order class='small-demo'> </demo-responsive-flex-order>
Expand Down
16 changes: 16 additions & 0 deletions src/apps/demo-app/src/app/watermark.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
:host {
display: block;
position: absolute;

width: 100vw;
min-height: 100vh;
top: 0;
left: 0;
right: 0;
bottom: 0;

div {
width: 100vw;
min-height: 100vh;
}
}
56 changes: 56 additions & 0 deletions src/apps/demo-app/src/app/watermark.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {Component, Input} from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser';

@Component({
selector: 'watermark',
styleUrls: ['watermark.component.scss'],
template: `
<div [style.background]="backgroundImage">
</div>
`,
})
export class WatermarkComponent {
@Input() title = '@angular/layout';
@Input() message = 'Layout with FlexBox + CSS Grid';

constructor(private _sanitizer: DomSanitizer) {
}

/* tslint:disable:max-line-length */
get backgroundImage() {
const rawSVG = `
<svg id="diagonalWatermark"
width="100%" height="100%"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<style type="text/css">
text {
fill: currentColor;
font-family: Avenir, Arial, Helvetica, sans-serif;
opacity: 0.25;
}
</style>
<defs>
<pattern id="titlePattern" patternUnits="userSpaceOnUse" width="350" height="150">
<text y="30" font-size="30" id="title">
${this.title}
</text>
</pattern>
<pattern xlink:href="#titlePattern">
<text y="60" x="0" font-size="16" id="message" width="350" height="150">
${this.message}
</text>
</pattern>
<pattern id="combo" xlink:href="#titlePattern" patternTransform="rotate(-30)">
<use xlink:href="#title"/>
<use xlink:href="#message"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#combo)"/>
</svg>
`;
const bkgrndImageUrl = `data:image/svg+xml;base64,${window.btoa(rawSVG)}`;

return this._sanitizer.bypassSecurityTrustStyle(`url('${bkgrndImageUrl}') repeat-y`);
}
}
12 changes: 12 additions & 0 deletions src/apps/demo-app/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ body {
font-size: 16px;
line-height: 1.4;
-webkit-font-smoothing: antialiased;
-webkit-print-color-adjust: exact !important;
}

@page {
size: auto; /* auto is the initial value */
margin: 2cm;
}

@media print {
body {
background: white;
}
}

h3 {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/add-alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {extendObject} from '../utils/object-extend';
* and suffix (if available).
*/
export function mergeAlias(dest: MediaChange, source: BreakPoint | null): MediaChange {
return extendObject(dest, source ? {
return extendObject(dest || {}, source ? {
ThomasBurleson marked this conversation as resolved.
Show resolved Hide resolved
mqAlias: source.alias,
suffix: source.suffix
} : {});
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/base/base2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export abstract class BaseDirective2 implements OnChanges, OnDestroy {
}
set activatedValue(value: string) {
this.marshal.setValue(this.nativeElement, this.DIRECTIVE_KEY, value,
this.marshal.activatedBreakpoint);
this.marshal.activatedAlias);
}

/** Cache map for style computation */
Expand Down
4 changes: 2 additions & 2 deletions src/lib/core/breakpoints/break-point-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {BreakPoint} from './break-point';
import {BREAKPOINTS} from './break-points-token';
import {sortAscendingPriority} from './breakpoint-tools';

type OptionalBreakPoint = BreakPoint | null;
export type OptionalBreakPoint = BreakPoint | null;

/**
* Registry of 1..n MediaQuery breakpoint ranges
Expand All @@ -30,7 +30,7 @@ export class BreakPointRegistry {
* Search breakpoints by alias (e.g. gt-xs)
*/
findByAlias(alias: string): OptionalBreakPoint {
return this.findWithPredicate(alias, (bp) => bp.alias == alias);
return !alias ? null : this.findWithPredicate(alias, (bp) => bp.alias == alias);
}

findByQuery(query: string): OptionalBreakPoint {
Expand Down
7 changes: 4 additions & 3 deletions src/lib/core/breakpoints/breakpoint-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {OptionalBreakPoint} from './break-point-registry';
import {BreakPoint} from './break-point';
import {extendObject} from '../../utils/object-extend';

Expand Down Expand Up @@ -65,9 +66,9 @@ export function mergeByAlias(defaults: BreakPoint[], custom: BreakPoint[] = []):
}

/** HOF to sort the breakpoints by priority */
export function sortDescendingPriority(a: BreakPoint, b: BreakPoint): number {
const priorityA = a.priority || 0;
const priorityB = b.priority || 0;
export function sortDescendingPriority(a: OptionalBreakPoint, b: OptionalBreakPoint): number {
const priorityA = a ? a.priority || 0 : 0;
const priorityB = b ? b.priority || 0 : 0;
return priorityB - priorityA;
}

Expand Down
29 changes: 14 additions & 15 deletions src/lib/core/breakpoints/data/orientation-break-points.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {TestBed, inject} from '@angular/core/testing';
import {TestBed, inject, async} from '@angular/core/testing';

import {BreakPoint} from '../break-point';
import {DEFAULT_BREAKPOINTS} from './break-points';
Expand Down Expand Up @@ -70,45 +70,44 @@ describe('break-point-provider', () => {

describe('with custom breakpoint overrides', () => {
const gtXsMediaQuery = 'screen and (max-width:20px) and (orientations: landscape)';
const mdMediaQuery = 'print and (min-width:10000px)';
const xxxlQuery = 'screen and (min-width:10000px)';
const EXTRAS: BreakPoint[] = [
{alias: 'md', mediaQuery: mdMediaQuery},
{alias: 'gt-xs', mediaQuery: gtXsMediaQuery},
{alias: 'lt-ab', mediaQuery: '(max-width: 297px)'},
{alias: 'cd', mediaQuery: '(min-width: 298px) and (max-width:414px)'}
{alias: 'xxl', priority: 2000, mediaQuery: xxxlQuery},
{alias: 'gt-xsl', priority: 2000, mediaQuery: gtXsMediaQuery},
{alias: 'lt-ab', priority: 2000, mediaQuery: '(max-width: 297px)'},
{alias: 'cd', priority: 2000, mediaQuery: '(min-width: 298px) and (max-width:414px)'}
];
const NUM_EXTRAS = 2; // since md and gt-xs will not be added but merged
let bpList: BreakPoint[];
let accumulator: BreakPoint | null = null;
let byAlias = (alias: string): BreakPoint | null => bpList.reduce((pos, it) => {
return pos || ((it.alias === alias) ? it : null);
}, accumulator);

beforeEach(() => {
beforeEach(async (() => {
// Configure testbed to prepare services
TestBed.configureTestingModule({
imports: [FlexLayoutModule.withConfig({addOrientationBps: true}, EXTRAS)]
});
});
}));
// tslint:disable-next-line:no-shadowed-variable
beforeEach(inject([BREAKPOINTS], (breakPoints: BreakPoint[]) => {
bpList = breakPoints;
}));

it('has merged the custom breakpoints as overrides to existing defaults', () => {
const total = ORIENTATION_BREAKPOINTS.length + DEFAULT_BREAKPOINTS.length + NUM_EXTRAS;
const total = ORIENTATION_BREAKPOINTS.length + DEFAULT_BREAKPOINTS.length + EXTRAS.length;

expect(bpList.length).toEqual(total);

expect(byAlias('gt-xs')).toBeDefined();
expect(byAlias('gt-xs')!.mediaQuery).toEqual(gtXsMediaQuery);
expect(byAlias('gt-xsl')).toBeDefined();
expect(byAlias('gt-xsl')!.mediaQuery).toEqual(gtXsMediaQuery);

expect(byAlias('md')).toBeDefined();
expect(byAlias('md')!.mediaQuery).toEqual(mdMediaQuery);
expect(byAlias('xxl')).toBeDefined();
expect(byAlias('xxl')!.mediaQuery).toEqual(xxxlQuery);
});

it('can extend existing default breakpoints with custom settings', () => {
const total = ORIENTATION_BREAKPOINTS.length + DEFAULT_BREAKPOINTS.length + NUM_EXTRAS;
const total = ORIENTATION_BREAKPOINTS.length + DEFAULT_BREAKPOINTS.length + EXTRAS.length;

expect(bpList.length).toEqual(total);
expect(bpList[bpList.length - 2].alias).toEqual('lt-ab');
Expand Down
18 changes: 9 additions & 9 deletions src/lib/core/breakpoints/data/orientation-break-points.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ export const ScreenTypes = {
* Extended Breakpoints for handset/tablets with landscape or portrait orientations
*/
export const ORIENTATION_BREAKPOINTS : BreakPoint[] = [
{'alias': 'handset', priority: 10000, 'mediaQuery': ScreenTypes.HANDSET},
{'alias': 'handset.landscape', priority: 10000, 'mediaQuery': ScreenTypes.HANDSET_LANDSCAPE},
{'alias': 'handset.portrait', priority: 10000, 'mediaQuery': ScreenTypes.HANDSET_PORTRAIT},
{'alias': 'handset', priority: 2000, 'mediaQuery': ScreenTypes.HANDSET},
{'alias': 'handset.landscape', priority: 2000, 'mediaQuery': ScreenTypes.HANDSET_LANDSCAPE},
{'alias': 'handset.portrait', priority: 2000, 'mediaQuery': ScreenTypes.HANDSET_PORTRAIT},

{'alias': 'tablet', priority: 8000, 'mediaQuery': ScreenTypes.TABLET},
{'alias': 'tablet.landscape', priority: 8000, 'mediaQuery': ScreenTypes.TABLET},
{'alias': 'tablet.portrait', priority: 8000, 'mediaQuery': ScreenTypes.TABLET_PORTRAIT},
{'alias': 'tablet', priority: 2100, 'mediaQuery': ScreenTypes.TABLET},
{'alias': 'tablet.landscape', priority: 2100, 'mediaQuery': ScreenTypes.TABLET},
{'alias': 'tablet.portrait', priority: 2100, 'mediaQuery': ScreenTypes.TABLET_PORTRAIT},

{'alias': 'web', priority: 9000, 'mediaQuery': ScreenTypes.WEB, overlapping : true },
{'alias': 'web.landscape', priority: 9000, 'mediaQuery': ScreenTypes.WEB_LANDSCAPE, overlapping : true },
{'alias': 'web.portrait', priority: 9000, 'mediaQuery': ScreenTypes.WEB_PORTRAIT, overlapping : true }
{'alias': 'web', priority: 2200, 'mediaQuery': ScreenTypes.WEB, overlapping : true },
{'alias': 'web.landscape', priority: 2200, 'mediaQuery': ScreenTypes.WEB_LANDSCAPE, overlapping : true },
{'alias': 'web.portrait', priority: 2200, 'mediaQuery': ScreenTypes.WEB_PORTRAIT, overlapping : true }
];
5 changes: 3 additions & 2 deletions src/lib/core/match-media/match-media.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ describe('match-media-observable', () => {
});

/**
* Only the ObservableMedia ignores de-activations;
* Only the MediaObserver ignores de-activations;
* MediaMonitor and MatchMedia report both activations and de-activations!
*/
it('ignores mediaQuery de-activations', () => {
Expand All @@ -189,9 +189,10 @@ describe('match-media-observable', () => {

matchMedia.activate(breakPoints.findByAlias('md')!.mediaQuery);
matchMedia.activate(breakPoints.findByAlias('gt-md')!.mediaQuery);
matchMedia.activate(breakPoints.findByAlias('lg')!.mediaQuery);

// 'all' mediaQuery is already active; total count should be (3)
expect(activationCount).toEqual(3);
expect(activationCount).toEqual(4);
expect(deactivationCount).toEqual(0);

subscription.unsubscribe();
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/match-media/mock/mock-match-media.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ describe('mock-match-media', () => {
subscription.unsubscribe();
});

it('can activate with either a mediaQuery or an alias', () => {
it('can onMediaChange with either a mediaQuery or an alias', () => {
ThomasBurleson marked this conversation as resolved.
Show resolved Hide resolved
let activates = 0;
let bpGtSM = breakPoints.findByAlias('gt-sm'),
bpLg = breakPoints.findByAlias('lg');
Expand Down
Loading