Skip to content

Instantly share code, notes, and snippets.

@frankiefu
Last active April 21, 2017 21:06
Show Gist options
  • Save frankiefu/5fba8f6cfdb486b72d68d8b8f487705e to your computer and use it in GitHub Desktop.
Save frankiefu/5fba8f6cfdb486b72d68d8b8f487705e to your computer and use it in GitHub Desktop.
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<!-- <link rel="import" href="../../polymer/polymer.html">
<link rel="import" href="../../iron-flex-layout/iron-flex-layout.html"> -->
<!-- <link rel="import" href="../app-layout-behavior/app-layout-behavior.html"> -->
<!--
app-header-layout is a wrapper element that positions an app-header and other content. This
element uses the document scroll by default, but it can also define its own scrolling region.
Using the document scroll:
```html
<app-header-layout>
<app-header slot="header" fixed condenses effects="waterfall">
<app-toolbar>
<div main-title>App name</div>
</app-toolbar>
</app-header>
<div>
main content
</div>
</app-header-layout>
```
Using an own scrolling region:
```html
<app-header-layout has-scrolling-region style="width: 300px; height: 400px;">
<app-header slot="header" fixed condenses effects="waterfall">
<app-toolbar>
<div main-title>App name</div>
</app-toolbar>
</app-header>
<div>
main content
</div>
</app-header-layout>
```
Add the `fullbleed` attribute to app-header-layout to make it fit the size of its container:
```html
<app-header-layout fullbleed>
...
</app-header-layout>
```
@group App Elements
@element app-header-layout
@demo app-header-layout/demo/simple.html Simple Demo
@demo app-header-layout/demo/scrolling-region.html Scrolling Region
@demo app-header-layout/demo/music.html Music Demo
@demo app-header-layout/demo/footer.html Footer Demo
-->
<dom-module id="app-header-layout">
<template>
<style>
:host {
display: block;
/**
* Force app-header-layout to have its own stacking context so that its parent can
* control the stacking of it relative to other elements (e.g. app-drawer-layout).
* This could be done using `isolation: isolate`, but that's not well supported
* across browsers.
*/
position: relative;
z-index: 0;
}
#wrapper ::slotted([slot=header]) {
@apply --layout-fixed-top;
z-index: 1;
}
#wrapper.initializing ::slotted([slot=header]) {
position: relative;
}
:host([has-scrolling-region]) {
height: 100%;
}
:host([has-scrolling-region]) #wrapper ::slotted([slot=header]) {
position: absolute;
}
:host([has-scrolling-region]) #wrapper.initializing ::slotted([slot=header]) {
position: relative;
}
:host([has-scrolling-region]) #wrapper #contentContainer {
@apply --layout-fit;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
:host([has-scrolling-region]) #wrapper.initializing #contentContainer {
position: relative;
}
:host([fullbleed]) {
@apply --layout-vertical;
@apply --layout-fit;
}
:host([fullbleed]) #wrapper,
:host([fullbleed]) #wrapper #contentContainer {
@apply --layout-vertical;
@apply --layout-flex;
}
#contentContainer {
/* Create a stacking context here so that all children appear below the header. */
position: relative;
z-index: 0;
}
</style>
<div id="wrapper" class="initializing">
<slot id="headerSlot" name="header"></slot>
<div id="contentContainer">
<slot></slot>
</div>
</div>
</template>
<script>
Polymer({
is: 'app-header-layout',
behaviors: [
Polymer.AppLayoutBehavior
],
properties: {
/**
* If true, the current element will have its own scrolling region.
* Otherwise, it will use the document scroll to control the header.
*/
hasScrollingRegion: {
type: Boolean,
value: false,
reflectToAttribute: true
}
},
observers: [
'resetLayout(isAttached, hasScrollingRegion)'
],
/**
* A reference to the app-header element.
*
* @property header
*/
get header() {
return Polymer.dom(this.$.headerSlot).getDistributedNodes()[0];
},
_updateLayoutStates: function() {
var header = this.header;
if (!this.isAttached || !header) {
return;
}
// Remove the initializing class, which staticly positions the header and the content
// until the height of the header can be read.
this.$.wrapper.classList.remove('initializing');
// Update scroll target.
header.scrollTarget = this.hasScrollingRegion ?
this.$.contentContainer : this.ownerDocument.documentElement;
// Get header height here so that style reads are batched together before style writes
// (i.e. getBoundingClientRect() below).
var headerHeight = header.offsetHeight || header.offsetHeight;
console.log('app-header-layout.headerHeight', headerHeight);
debugger;
// Update the header position.
if (!this.hasScrollingRegion) {
requestAnimationFrame(function() {
var rect = this.getBoundingClientRect();
var rightOffset = document.documentElement.clientWidth - rect.right;
header.style.left = rect.left + 'px';
header.style.right = rightOffset + 'px';
}.bind(this));
} else {
header.style.left = '';
header.style.right = '';
}
// Update the content container position.
var containerStyle = this.$.contentContainer.style;
if (header.fixed && !header.condenses && this.hasScrollingRegion) {
// If the header size does not change and we're using a scrolling region, exclude
// the header area from the scrolling region so that the header doesn't overlap
// the scrollbar.
containerStyle.marginTop = headerHeight + 'px';
containerStyle.paddingTop = '';
} else {
containerStyle.paddingTop = headerHeight + 'px';
containerStyle.marginTop = '';
}
}
});
</script>
</dom-module>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment