Skip to content

Commit

Permalink
revert partial
Browse files Browse the repository at this point in the history
  • Loading branch information
zhouyx committed May 30, 2017
1 parent 2dbc5f6 commit 2c98a36
Show file tree
Hide file tree
Showing 8 changed files with 797 additions and 0 deletions.
1 change: 1 addition & 0 deletions css/Z_INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ i-amphtml-video-mask | 1 | css/amp.cs
.i-amphtml-element > [overflow] | 2 | css/amp.css
.amp-carousel-button | 10 | extensions/amp-carousel/0.1/amp-carousel.css
amp-sticky-ad | 11 | extensions/amp-sticky-ad/1.0/amp-sticky-ad.css
amp-sticky-ad | 11 | extensions/amp-sticky-ad/0.1/amp-sticky-ad.css
amp-sticky-ad-top-padding | 12 | extensions/amp-sticky-ad/1.0/amp-sticky-ad.css
amp-app-banner | 13 | extensions/amp-app-banner/0.1/amp-app-banner.css
.amp-app-banner-dismiss-button | 14 | extensions/amp-app-banner/0.1/amp-app-banner.css
Expand Down
64 changes: 64 additions & 0 deletions extensions/amp-sticky-ad/0.1/amp-sticky-ad-0.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<!---
Copyright 2016 The AMP HTML Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS-IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

# <a name="amp-sticky-ad"></a> `amp-sticky-ad`

<table>
<tr>
<td width="40%"><strong>Description</strong></td>
<td>A stickyAd provides a way to fix ad at bottom of a page. The stickyAs serves as a container and the ad as its child will display as sticky-ad</td>
</tr>
<tr>
<td width="40%"><strong>Availability</strong></td>
<td><div><a href="https://www.ampproject.org/docs/reference/experimental.html">Experimental</a>; no validations yet.</div><div>Work in progress.</div></td>
</tr>
<tr>
<td width="40%"><strong>Required Script</strong></td>
<td><code>&lt;script async custom-element="amp-sticky-ad" src="https://cdn.ampproject.org/v0/amp-sticky-ad-0.1.js">&lt;/script></code></td>
</tr>
<tr>
<td class="col-fourty"><strong><a href="https://www.ampproject.org/docs/guides/responsive/control_layout.html">Supported Layouts</a></strong></td>
<td>NODISPLAY</td>
</tr>
</table>

## Behavior

- There can be only one `<amp-sticky-ad>` in an AMP document. The `<amp-sticky-ad>` should only have one direct child of `<amp-ad>`.
- The sticky will appear on the bottom of a page.
- The height of the sticky-ad is whatever its child needs up to its max-height.
- The max-height of the sticky-ad is 100px, if the height exceeds 100px then the height would be 100px and overflow content will be hidden.
- The width of the sticky-ad is set to 100% using CSS and cannot be overridden.
- The sticky-ad will display after scroll one viewport height from top provided there is at least one more viewport of content available.
- Swipe to dismiss (TBD)

Example:
```html
<amp-sticky-ad layout="nodisplay">
<amp-ad width="300" height="65"
type="adman"
data-ws="17342"
data-s="300x65"
data-host="talos.adman.gr">
</amp-ad>
</amp-sticky-ad>
```

## Attributes

**layout**

The only permissible value for the `layout` attribute in `amp-sticky-ad` is `nodisplay`.
88 changes: 88 additions & 0 deletions extensions/amp-sticky-ad/0.1/amp-sticky-ad.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* Copyright 2016 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

amp-sticky-ad {
position: fixed !important;
text-align:center;
bottom: 0 !important;
left: 0;
width: 100% !important;
z-index: 11;
max-height: 100px !important;
box-sizing: border-box;
}

.i-amphtml-sticky-ad-layout {
display: flex;
visibility: hidden !important;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: visible !important;
transform: translateZ(0) !important;
}

amp-sticky-ad[visible] {
visibility: visible !important;
}

.amp-sticky-ad-loaded {
background-color: #fff;
}

.i-amphtml-sticky-ad-layout > amp-ad {
display: block;
}


.amp-sticky-ad-close-button {
position: absolute;
visibility: hidden;
width: 32px;
height: 32px;
top: -32px;
right: 0;
background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
background-size: 26px 26px;
background-position: center;
background-color: #fff;
border: 1px solid #c8c8c8;
}

amp-sticky-ad[visible] > .amp-sticky-ad-close-button {
visibility: visible;
}

/* Increase tapping area of the dismiss button */
.amp-sticky-ad-close-button:before {
position: absolute;
content: '';
top: -18px;
right: 0;
left: -18px;
bottom: 0;
}

[dir=rtl] .amp-sticky-ad-close-button {
right: auto;
left: 0;
}

[dir=rtl] .amp-sticky-ad-close-button:before {
top: -18px;
right: -18px;
left: 0;
}
212 changes: 212 additions & 0 deletions extensions/amp-sticky-ad/0.1/amp-sticky-ad.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/**
* Copyright 2016 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {CommonSignals} from '../../../src/common-signals';
import {CSS} from '../../../build/amp-sticky-ad-0.1.css';
import {Layout} from '../../../src/layout';
import {dev,user} from '../../../src/log';
import {removeElement} from '../../../src/dom';
import {toggle} from '../../../src/style';

class AmpStickyAd extends AMP.BaseElement {
/** @param {!AmpElement} element */
constructor(element) {
super(element);

/** @const @private {!../../../src/service/vsync-impl.Vsync} */
this.vsync_ = this.getVsync();

/** @private {?Element} */
this.ad_ = null;

/** @private {?../../../src/service/viewport-impl.Viewport} */
this.viewport_ = null;

/** @private {boolean} */
this.visible_ = false;

/** @private {?UnlistenDef} */
this.scrollUnlisten_ = null;
}

/** @override */
isLayoutSupported(layout) {
return layout == Layout.NODISPLAY;
}

/** @override */
buildCallback() {
this.viewport_ = this.getViewport();

toggle(this.element, true);
this.element.classList.add('i-amphtml-sticky-ad-layout');
const children = this.getRealChildren();
user().assert((children.length == 1 && children[0].tagName == 'AMP-AD'),
'amp-sticky-ad must have a single amp-ad child');

this.ad_ = children[0];
this.setAsOwner(this.ad_);

// On viewport scroll, check requirements for amp-stick-ad to display.
this.scrollUnlisten_ =
this.viewport_.onScroll(() => this.displayAfterScroll_());
}

/** @override */
layoutCallback() {
// Reschedule layout for ad if layout sticky-ad again.
if (this.visible_) {
toggle(this.element, true);
const borderBottom = this.element./*OK*/offsetHeight;
this.viewport_.updatePaddingBottom(borderBottom);
this.updateInViewport(dev().assertElement(this.ad_), true);
this.scheduleLayout(dev().assertElement(this.ad_));
}
return Promise.resolve();
}

/** @override */
unlayoutCallback() {
this.viewport_.updatePaddingBottom(0);
this.element.classList.remove('amp-sticky-ad-loaded');
return true;
}

/** @override */
detachedCallback() {
this.removeOnScrollListener_();
}

/** @override */
collapsedCallback() {
toggle(this.element, false);
this.vsync_.mutate(() => {
this.viewport_.updatePaddingBottom(0);
});
}

/**
* The function that remove listener to viewport onScroll event.
* @private
*/
removeOnScrollListener_() {
if (this.scrollUnlisten_) {
this.scrollUnlisten_();
this.scrollUnlisten_ = null;
}
}

/**
* The listener function that listen on onScroll event and
* show sticky ad when user scroll at least one viewport and
* there is at least one more viewport available.
* @private
*/
displayAfterScroll_() {
const scrollTop = this.viewport_.getScrollTop();
const viewportHeight = this.viewport_.getSize().height;
const scrollHeight = this.viewport_.getScrollHeight();
if (scrollHeight < viewportHeight * 2) {
this.removeOnScrollListener_();
return;
}

// Check user has scrolled at least one viewport from init position.
if (scrollTop > viewportHeight) {
this.removeOnScrollListener_();
this.deferMutate(() => {
this.visible_ = true;
this.viewport_.addToFixedLayer(this.element);
// Add border-bottom to the body to compensate space that was taken
// by sticky ad, so no content would be blocked by sticky ad unit.
const borderBottom = this.element./*OK*/offsetHeight;
this.viewport_.updatePaddingBottom(borderBottom);
this.addCloseButton_();
this.scheduleLayoutForAd_();
});
}
}

/**
* Function that check if ad has been built. If not, wait for the "built"
* signal. Otherwise schedule layout for ad.
* @private
*/
scheduleLayoutForAd_() {
if (this.ad_.isBuilt()) {
this.layoutAd_();
} else {
this.ad_.whenBuilt().then(this.layoutAd_.bind(this));
}
}

/**
* Layout ad, and display sticky-ad container after layout complete.
* @private
*/
layoutAd_() {
const ad = dev().assertElement(this.ad_);
this.updateInViewport(ad, true);
this.scheduleLayout(ad);
// Wait for the earliest: `render-start` or `load-end` signals.
// `render-start` is expected to arrive first, but it's not emitted by
// all types of ads.
const signals = ad.signals();
return Promise.race([
signals.whenSignal(CommonSignals.RENDER_START),
signals.whenSignal(CommonSignals.LOAD_END),
]).then(() => {
return this.vsync_.mutatePromise(() => {
// Set sticky-ad to visible and change container style
this.element.setAttribute('visible', '');
this.element.classList.add('amp-sticky-ad-loaded');
});
});
}

/**
* The function that add a close button to sticky ad
* @private
*/
addCloseButton_() {
const closeButton = this.win.document.createElement('button');
closeButton.classList.add('amp-sticky-ad-close-button');
closeButton.setAttribute('aria-label',
this.element.getAttribute('data-close-button-aria-label')
|| 'Close this ad');
const boundOnCloseButtonClick = this.onCloseButtonClick_.bind(this);
closeButton.addEventListener('click', boundOnCloseButtonClick);
this.element.appendChild(closeButton);
}

/**
* The listener function that listen to click event and dismiss sticky ad
* @private
*/
onCloseButtonClick_() {
this.vsync_.mutate(() => {
this.visible_ = false;
this./*OK*/scheduleUnlayout(dev().assertElement(this.ad_));
this.viewport_.removeFromFixedLayer(this.element);
removeElement(this.element);
this.viewport_.updatePaddingBottom(0);
});
}
}

AMP.extension('amp-sticky-ad', '0.1', AMP => {
AMP.registerElement('amp-sticky-ad', AmpStickyAd, CSS);
});
Loading

0 comments on commit 2c98a36

Please sign in to comment.