import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, NgZone, Optional, Output, Renderer, ViewChild, ViewEncapsulation } from '@angular/core';
import { App } from '../app/app';
import { Config } from '../../config/config';
import { DomController } from '../../platform/dom-controller';
import { Ion } from '../ion';
import { isTabs } from '../../navigation/nav-util';
import { isTrueProperty, removeArrayItem } from '../../util/util';
import { Keyboard } from '../../platform/keyboard';
import { NavController } from '../../navigation/nav-controller';
import { Platform } from '../../platform/platform';
import { ScrollView } from '../../util/scroll-view';
import { ViewController } from '../../navigation/view-controller';
export class EventEmitterProxy extends EventEmitter {
subscribe(generatorOrNext, error, complete) {
this.onSubscribe();
return super.subscribe(generatorOrNext, error, complete);
}
}
/**
* @name Content
* @description
* The Content component provides an easy to use content area with
* some useful methods to control the scrollable area. There should
* only be one content in a single view component. If additional scrollable
* elements are needed, use [ionScroll](../../scroll/Scroll).
*
*
* The content area can also implement pull-to-refresh with the
* [Refresher](../../refresher/Refresher) component.
*
* @usage
* ```html
*
* Add your content here!
*
* ```
*
* To get a reference to the content component from a Page's logic,
* you can use Angular's `@ViewChild` annotation:
*
* ```ts
* import { Component, ViewChild } from '@angular/core';
* import { Content } from 'ionic-angular';
*
* @Component({...})
* export class MyPage{
* @ViewChild(Content) content: Content;
*
* scrollToTop() {
* this.content.scrollToTop();
* }
* }
* ```
*
* @advanced
*
* ### Scroll Events
*
* Scroll events happen outside of Angular's Zones. This is for performance reasons. So
* if you're trying to bind a value to any scroll event, it will need to be wrapped in
* a `zone.run()`
*
* ```ts
* import { Component, NgZone } from '@angular/core';
* @Component({
* template: `
*
*
* {{scrollAmount}}
*
*
*
*
Some realllllllly long content
*
* `})
* class E2EPage {
* public scrollAmount = 0;
* constructor( public zone: NgZone){}
* scrollHandler(event) {
* console.log(`ScrollEvent: ${event}`)
* this.zone.run(()=>{
* // since scrollAmount is data-binded,
* // the update needs to happen in zone
* this.scrollAmount++
* })
* }
* }
* ```
*
* This goes for any scroll event, not just `ionScroll`.
*
* ### Resizing the content
*
* If the height of `ion-header`, `ion-footer` or `ion-tabbar`
* changes dynamically, `content.resize()` has to be called in order to update the
* layout of `Content`.
*
*
* ```ts
* @Component({
* template: `
*
*
* Main Navbar
*
*
* Dynamic Toolbar
*
*
*
*
*
* `})
*
* class E2EPage {
* @ViewChild(Content) content: Content;
* showToolbar: boolean = false;
*
* toggleToolbar() {
* this.showToolbar = !this.showToolbar;
* this.content.resize();
* }
* }
* ```
*
*
* Scroll to a specific position
*
* ```ts
* import { Component, ViewChild } from '@angular/core';
* import { Content } from 'ionic-angular';
*
* @Component({
* template: `
*
* `
* )}
* export class MyPage{
* @ViewChild(Content) content: Content;
*
* scrollTo() {
* // set the scrollLeft to 0px, and scrollTop to 500px
* // the scroll duration should take 200ms
* this.content.scrollTo(0, 500, 200);
* }
* }
* ```
*
*/
export class Content extends Ion {
constructor(config, _plt, _dom, elementRef, renderer, _app, _keyboard, _zone, viewCtrl, navCtrl) {
super(config, elementRef, renderer, 'content');
this._plt = _plt;
this._dom = _dom;
this._app = _app;
this._keyboard = _keyboard;
this._zone = _zone;
/** @internal */
this._scrollPadding = 0;
/** @internal */
this._inputPolling = false;
/** @internal */
this._hasRefresher = false;
/** @internal */
this._imgs = [];
/** @internal */
this._scrollDownOnLoad = false;
/**
* @output {ScrollEvent} Emitted when the scrolling first starts.
*/
this.ionScrollStart = new EventEmitterProxy();
/**
* @output {ScrollEvent} Emitted on every scroll event.
*/
this.ionScroll = new EventEmitterProxy();
/**
* @output {ScrollEvent} Emitted when scrolling ends.
*/
this.ionScrollEnd = new EventEmitterProxy();
const enableScrollListener = () => this._scroll.enableEvents();
this.ionScroll.onSubscribe = enableScrollListener;
this.ionScrollStart.onSubscribe = enableScrollListener;
this.ionScrollEnd.onSubscribe = enableScrollListener;
this.statusbarPadding = config.getBoolean('statusbarPadding', false);
this._imgReqBfr = config.getNumber('imgRequestBuffer', 1400);
this._imgRndBfr = config.getNumber('imgRenderBuffer', 400);
this._imgVelMax = config.getNumber('imgVelocityMax', 3);
this._scroll = new ScrollView(_app, _plt, _dom);
while (navCtrl) {
if (isTabs(navCtrl)) {
this._tabs = navCtrl;
break;
}
navCtrl = navCtrl.parent;
}
if (viewCtrl) {
this._viewCtrl = viewCtrl;
// content has a view controller
viewCtrl._setIONContent(this);
viewCtrl._setIONContentRef(elementRef);
this._viewCtrlReadSub = viewCtrl.readReady.subscribe(() => {
this._viewCtrlReadSub.unsubscribe();
this._readDimensions();
});
this._viewCtrlWriteSub = viewCtrl.writeReady.subscribe(() => {
this._viewCtrlWriteSub.unsubscribe();
this._writeDimensions();
});
}
else {
// content does not have a view controller
_dom.read(this._readDimensions.bind(this));
_dom.write(this._writeDimensions.bind(this));
}
}
/**
* Content height of the viewable area. This does not include content
* which is outside the overflow area, or content area which is under
* headers and footers. Read-only.
*
* @return {number}
*/
get contentHeight() {
return this._scroll.ev.contentHeight;
}
/**
* Content width including content which is not visible on the screen
* due to overflow. Read-only.
*
* @return {number}
*/
get contentWidth() {
return this._scroll.ev.contentWidth;
}
/**
* Content height including content which is not visible on the screen
* due to overflow. Read-only.
*
* @return {number}
*/
get scrollHeight() {
return this._scroll.ev.scrollHeight;
}
/**
* Content width including content which is not visible due to
* overflow. Read-only.
*
* @return {number}
*/
get scrollWidth() {
return this._scroll.ev.scrollWidth;
}
/**
* The distance of the content's top to its topmost visible content.
*
* @return {number}
*/
get scrollTop() {
return this._scroll.ev.scrollTop;
}
/**
* @param {number} top
*/
set scrollTop(top) {
this._scroll.setTop(top);
}
/**
* The distance of the content's left to its leftmost visible content.
*
* @return {number}
*/
get scrollLeft() {
return this._scroll.ev.scrollLeft;
}
/**
* @param {number} top
*/
set scrollLeft(top) {
this._scroll.setLeft(top);
}
/**
* If the content is actively scrolling or not.
*
* @return {boolean}
*/
get isScrolling() {
return this._scroll.isScrolling;
}
/**
* The current, or last known, vertical scroll direction. Possible
* string values include `down` and `up`.
*
* @return {string}
*/
get directionY() {
return this._scroll.ev.directionY;
}
/**
* The current, or last known, horizontal scroll direction. Possible
* string values include `right` and `left`.
*
* @return {string}
*/
get directionX() {
return this._scroll.ev.directionX;
}
/**
* @hidden
*/
ngAfterViewInit() {
(void 0) /* assert */;
(void 0) /* assert */;
const scroll = this._scroll;
scroll.ev.fixedElement = this.getFixedElement();
scroll.ev.scrollElement = this.getScrollElement();
// subscribe to the scroll start
scroll.onScrollStart = (ev) => {
this.ionScrollStart.emit(ev);
};
// subscribe to every scroll move
scroll.onScroll = (ev) => {
// emit to all of our other friends things be scrolling
this.ionScroll.emit(ev);
this.imgsUpdate();
};
// subscribe to the scroll end
scroll.onScrollEnd = (ev) => {
this.ionScrollEnd.emit(ev);
this.imgsUpdate();
};
}
/**
* @hidden
*/
enableJsScroll() {
this._scroll.enableJsScroll(this._cTop, this._cBottom);
}
/**
* @hidden
*/
ngOnDestroy() {
this._scLsn && this._scLsn();
this._viewCtrlReadSub && this._viewCtrlReadSub.unsubscribe();
this._viewCtrlWriteSub && this._viewCtrlWriteSub.unsubscribe();
this._viewCtrlReadSub = this._viewCtrlWriteSub = null;
this._scroll && this._scroll.destroy();
this._footerEle = this._scLsn = this._scroll = null;
}
/**
* @hidden
*/
getScrollElement() {
return this._scrollContent.nativeElement;
}
/**
* @private
*/
getFixedElement() {
return this._fixedContent.nativeElement;
}
/**
* @hidden
*/
onScrollElementTransitionEnd(callback) {
this._plt.transitionEnd(this.getScrollElement(), callback);
}
/**
* Scroll to the specified position.
*
* @param {number} x The x-value to scroll to.
* @param {number} y The y-value to scroll to.
* @param {number} [duration] Duration of the scroll animation in milliseconds. Defaults to `300`.
* @returns {Promise} Returns a promise which is resolved when the scroll has completed.
*/
scrollTo(x, y, duration = 300, done) {
(void 0) /* console.debug */;
return this._scroll.scrollTo(x, y, duration, done);
}
/**
* Scroll to the top of the content component.
*
* @param {number} [duration] Duration of the scroll animation in milliseconds. Defaults to `300`.
* @returns {Promise} Returns a promise which is resolved when the scroll has completed.
*/
scrollToTop(duration = 300) {
(void 0) /* console.debug */;
return this._scroll.scrollToTop(duration);
}
/**
* Scroll to the bottom of the content component.
*
* @param {number} [duration] Duration of the scroll animation in milliseconds. Defaults to `300`.
* @returns {Promise} Returns a promise which is resolved when the scroll has completed.
*/
scrollToBottom(duration = 300) {
(void 0) /* console.debug */;
return this._scroll.scrollToBottom(duration);
}
/**
* @input {boolean} If true, the content will scroll behind the headers
* and footers. This effect can easily be seen by setting the toolbar
* to transparent.
*/
get fullscreen() {
return this._fullscreen;
}
set fullscreen(val) {
this._fullscreen = isTrueProperty(val);
}
/**
* @input {boolean} If true, the content will scroll down on load.
*/
get scrollDownOnLoad() {
return this._scrollDownOnLoad;
}
set scrollDownOnLoad(val) {
this._scrollDownOnLoad = isTrueProperty(val);
}
/**
* @private
*/
addImg(img) {
this._imgs.push(img);
}
/**
* @hidden
*/
removeImg(img) {
removeArrayItem(this._imgs, img);
}
/**
* @hidden
* DOM WRITE
*/
setScrollElementStyle(prop, val) {
const scrollEle = this.getScrollElement();
if (scrollEle) {
this._dom.write(() => {
scrollEle.style[prop] = val;
});
}
}
/**
* Returns the content and scroll elements' dimensions.
* @returns {object} dimensions The content and scroll elements' dimensions
* {number} dimensions.contentHeight content offsetHeight
* {number} dimensions.contentTop content offsetTop
* {number} dimensions.contentBottom content offsetTop+offsetHeight
* {number} dimensions.contentWidth content offsetWidth
* {number} dimensions.contentLeft content offsetLeft
* {number} dimensions.contentRight content offsetLeft + offsetWidth
* {number} dimensions.scrollHeight scroll scrollHeight
* {number} dimensions.scrollTop scroll scrollTop
* {number} dimensions.scrollBottom scroll scrollTop + scrollHeight
* {number} dimensions.scrollWidth scroll scrollWidth
* {number} dimensions.scrollLeft scroll scrollLeft
* {number} dimensions.scrollRight scroll scrollLeft + scrollWidth
*/
getContentDimensions() {
const scrollEle = this.getScrollElement();
const parentElement = scrollEle.parentElement;
return {
contentHeight: parentElement.offsetHeight - this._cTop - this._cBottom,
contentTop: this._cTop,
contentBottom: this._cBottom,
contentWidth: parentElement.offsetWidth,
contentLeft: parentElement.offsetLeft,
scrollHeight: scrollEle.scrollHeight,
scrollTop: scrollEle.scrollTop,
scrollWidth: scrollEle.scrollWidth,
scrollLeft: scrollEle.scrollLeft,
};
}
/**
* @hidden
* DOM WRITE
* Adds padding to the bottom of the scroll element when the keyboard is open
* so content below the keyboard can be scrolled into view.
*/
addScrollPadding(newPadding) {
(void 0) /* assert */;
if (newPadding === 0) {
this._inputPolling = false;
this._scrollPadding = -1;
}
if (newPadding > this._scrollPadding) {
(void 0) /* console.debug */;
this._scrollPadding = newPadding;
var scrollEle = this.getScrollElement();
if (scrollEle) {
this._dom.write(() => {
scrollEle.style.paddingBottom = (newPadding > 0) ? newPadding + 'px' : '';
});
}
}
}
/**
* @hidden
* DOM WRITE
*/
clearScrollPaddingFocusOut() {
if (!this._inputPolling) {
(void 0) /* console.debug */;
this._inputPolling = true;
this._keyboard.onClose(() => {
(void 0) /* console.debug */;
this.addScrollPadding(0);
}, 200, 3000);
}
}
/**
* Tell the content to recalculate its dimensions. This should be called
* after dynamically adding/removing headers, footers, or tabs.
*/
resize() {
this._dom.read(this._readDimensions.bind(this));
this._dom.write(this._writeDimensions.bind(this));
}
/**
* @hidden
* DOM READ
*/
_readDimensions() {
const cachePaddingTop = this._pTop;
const cachePaddingRight = this._pRight;
const cachePaddingBottom = this._pBottom;
const cachePaddingLeft = this._pLeft;
const cacheHeaderHeight = this._hdrHeight;
const cacheFooterHeight = this._ftrHeight;
const cacheTabsPlacement = this._tabsPlacement;
let tabsTop = 0;
let scrollEvent;
this._pTop = 0;
this._pRight = 0;
this._pBottom = 0;
this._pLeft = 0;
this._hdrHeight = 0;
this._ftrHeight = 0;
this._tabsPlacement = null;
this._tTop = 0;
this._fTop = 0;
this._fBottom = 0;
// In certain cases this._scroll is undefined
// if that is the case then we should just return
if (!this._scroll) {
return;
}
scrollEvent = this._scroll.ev;
let ele = this.getNativeElement();
if (!ele) {
(void 0) /* assert */;
return;
}
let computedStyle;
let tagName;
let parentEle = ele.parentElement;
let children = parentEle.children;
for (var i = children.length - 1; i >= 0; i--) {
ele = children[i];
tagName = ele.tagName;
if (tagName === 'ION-CONTENT') {
scrollEvent.contentElement = ele;
if (this._fullscreen) {
// ******** DOM READ ****************
computedStyle = getComputedStyle(ele);
this._pTop = parsePxUnit(computedStyle.paddingTop);
this._pBottom = parsePxUnit(computedStyle.paddingBottom);
this._pRight = parsePxUnit(computedStyle.paddingRight);
this._pLeft = parsePxUnit(computedStyle.paddingLeft);
}
}
else if (tagName === 'ION-HEADER') {
scrollEvent.headerElement = ele;
// ******** DOM READ ****************
this._hdrHeight = ele.clientHeight;
}
else if (tagName === 'ION-FOOTER') {
scrollEvent.footerElement = ele;
// ******** DOM READ ****************
this._ftrHeight = ele.clientHeight;
this._footerEle = ele;
}
}
ele = parentEle;
let tabbarEle;
while (ele && ele.tagName !== 'ION-MODAL' && !ele.classList.contains('tab-subpage')) {
if (ele.tagName === 'ION-TABS') {
tabbarEle = ele.firstElementChild;
// ******** DOM READ ****************
this._tabbarHeight = tabbarEle.clientHeight;
if (this._tabsPlacement === null) {
// this is the first tabbar found, remember it's position
this._tabsPlacement = ele.getAttribute('tabsplacement');
}
}
ele = ele.parentElement;
}
// Tabs top
if (this._tabs && this._tabsPlacement === 'top') {
this._tTop = this._hdrHeight;
tabsTop = this._tabs._top;
}
// Toolbar height
this._cTop = this._hdrHeight;
this._cBottom = this._ftrHeight;
// Tabs height
if (this._tabsPlacement === 'top') {
this._cTop += this._tabbarHeight;
}
else if (this._tabsPlacement === 'bottom') {
this._cBottom += this._tabbarHeight;
}
// Refresher uses a border which should be hidden unless pulled
if (this._hasRefresher) {
this._cTop -= 1;
}
// Fixed content shouldn't include content padding
this._fTop = this._cTop;
this._fBottom = this._cBottom;
// Handle fullscreen viewport (padding vs margin)
if (this._fullscreen) {
this._cTop += this._pTop;
this._cBottom += this._pBottom;
}
// ******** DOM READ ****************
const contentDimensions = this.getContentDimensions();
scrollEvent.scrollHeight = contentDimensions.scrollHeight;
scrollEvent.scrollWidth = contentDimensions.scrollWidth;
scrollEvent.contentHeight = contentDimensions.contentHeight;
scrollEvent.contentWidth = contentDimensions.contentWidth;
scrollEvent.contentTop = contentDimensions.contentTop;
scrollEvent.contentBottom = contentDimensions.contentBottom;
this._dirty = (cachePaddingTop !== this._pTop ||
cachePaddingBottom !== this._pBottom ||
cachePaddingLeft !== this._pLeft ||
cachePaddingRight !== this._pRight ||
cacheHeaderHeight !== this._hdrHeight ||
cacheFooterHeight !== this._ftrHeight ||
cacheTabsPlacement !== this._tabsPlacement ||
tabsTop !== this._tTop ||
this._cTop !== this.contentTop ||
this._cBottom !== this.contentBottom);
this._scroll.init(this.getScrollElement(), this._cTop, this._cBottom);
// initial imgs refresh
this.imgsUpdate();
}
/**
* @hidden
* DOM WRITE
*/
_writeDimensions() {
if (!this._dirty) {
(void 0) /* console.debug */;
return;
}
const scrollEle = this.getScrollElement();
if (!scrollEle) {
(void 0) /* assert */;
return;
}
const fixedEle = this.getFixedElement();
if (!fixedEle) {
(void 0) /* assert */;
return;
}
// Tabs height
if (this._tabsPlacement === 'bottom' && this._cBottom > 0 && this._footerEle) {
var footerPos = this._cBottom - this._ftrHeight;
(void 0) /* assert */;
// ******** DOM WRITE ****************
this._footerEle.style.bottom = cssFormat(footerPos);
}
// Handle fullscreen viewport (padding vs margin)
let topProperty = 'marginTop';
let bottomProperty = 'marginBottom';
let fixedTop = this._fTop;
let fixedBottom = this._fBottom;
if (this._fullscreen) {
(void 0) /* assert */;
(void 0) /* assert */;
// adjust the content with padding, allowing content to scroll under headers/footers
// however, on iOS you cannot control the margins of the scrollbar (last tested iOS9.2)
// only add inline padding styles if the computed padding value, which would
// have come from the app's css, is different than the new padding value
topProperty = 'paddingTop';
bottomProperty = 'paddingBottom';
}
// Only update top margin if value changed
if (this._cTop !== this.contentTop) {
(void 0) /* assert */;
(void 0) /* assert */;
// ******** DOM WRITE ****************
scrollEle.style[topProperty] = cssFormat(this._cTop);
// ******** DOM WRITE ****************
fixedEle.style.marginTop = cssFormat(fixedTop);
this.contentTop = this._cTop;
}
// Only update bottom margin if value changed
if (this._cBottom !== this.contentBottom) {
(void 0) /* assert */;
(void 0) /* assert */;
// ******** DOM WRITE ****************
scrollEle.style[bottomProperty] = cssFormat(this._cBottom);
// ******** DOM WRITE ****************
fixedEle.style.marginBottom = cssFormat(fixedBottom);
this.contentBottom = this._cBottom;
}
if (this._tabsPlacement !== null && this._tabs) {
// set the position of the tabbar
if (this._tabsPlacement === 'top') {
// ******** DOM WRITE ****************
this._tabs.setTabbarPosition(this._tTop, -1);
}
else {
(void 0) /* assert */;
// ******** DOM WRITE ****************
this._tabs.setTabbarPosition(-1, 0);
}
}
// Scroll the page all the way down after setting dimensions
if (this._scrollDownOnLoad) {
this.scrollToBottom(0);
this._scrollDownOnLoad = false;
}
}
/**
* @hidden
*/
imgsUpdate() {
if (this._scroll.initialized && this._imgs.length && this.isImgsUpdatable()) {
updateImgs(this._imgs, this.scrollTop, this.contentHeight, this.directionY, this._imgReqBfr, this._imgRndBfr);
}
}
/**
* @hidden
*/
isImgsUpdatable() {
// an image is only "updatable" if the content isn't scrolling too fast
// if scroll speed is above the maximum velocity, then let current
// requests finish, but do not start new requets or render anything
// if scroll speed is below the maximum velocity, then it's ok
// to start new requests and render images
return Math.abs(this._scroll.ev.velocityY) < this._imgVelMax;
}
}
Content.decorators = [
{ type: Component, args: [{
selector: 'ion-content',
template: '
' +
'' +
'
' +
'
' +
'' +
'
' +
'',
host: {
'[class.statusbar-padding]': 'statusbarPadding',
'[class.has-refresher]': '_hasRefresher'
},
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None
},] },
];
/** @nocollapse */
Content.ctorParameters = () => [
{ type: Config, },
{ type: Platform, },
{ type: DomController, },
{ type: ElementRef, },
{ type: Renderer, },
{ type: App, },
{ type: Keyboard, },
{ type: NgZone, },
{ type: ViewController, decorators: [{ type: Optional },] },
{ type: NavController, decorators: [{ type: Optional },] },
];
Content.propDecorators = {
'_fixedContent': [{ type: ViewChild, args: ['fixedContent', { read: ElementRef },] },],
'_scrollContent': [{ type: ViewChild, args: ['scrollContent', { read: ElementRef },] },],
'ionScrollStart': [{ type: Output },],
'ionScroll': [{ type: Output },],
'ionScrollEnd': [{ type: Output },],
'fullscreen': [{ type: Input },],
'scrollDownOnLoad': [{ type: Input },],
};
export function updateImgs(imgs, viewableTop, contentHeight, scrollDirectionY, requestableBuffer, renderableBuffer) {
// ok, so it's time to see which images, if any, should be requested and rendered
// ultimately, if we're scrolling fast then don't bother requesting or rendering
// when scrolling is done, then it needs to do a check to see which images are
// important to request and render, and which image requests should be aborted.
// Additionally, images which are not near the viewable area should not be
// rendered at all in order to save browser resources.
const viewableBottom = (viewableTop + contentHeight);
const priority1 = [];
const priority2 = [];
let img;
// all images should be paused
for (var i = 0, ilen = imgs.length; i < ilen; i++) {
img = imgs[i];
if (scrollDirectionY === 'up') {
// scrolling up
if (img.top < viewableBottom && img.bottom > viewableTop - renderableBuffer) {
// scrolling up, img is within viewable area
// or about to be viewable area
img.canRequest = img.canRender = true;
priority1.push(img);
continue;
}
if (img.bottom <= viewableTop && img.bottom > viewableTop - requestableBuffer) {
// scrolling up, img is within requestable area
img.canRequest = true;
img.canRender = false;
priority2.push(img);
continue;
}
if (img.top >= viewableBottom && img.top < viewableBottom + renderableBuffer) {
// scrolling up, img below viewable area
// but it's still within renderable area
// don't allow a reset
img.canRequest = img.canRender = false;
continue;
}
}
else {
// scrolling down
if (img.bottom > viewableTop && img.top < viewableBottom + renderableBuffer) {
// scrolling down, img is within viewable area
// or about to be viewable area
img.canRequest = img.canRender = true;
priority1.push(img);
continue;
}
if (img.top >= viewableBottom && img.top < viewableBottom + requestableBuffer) {
// scrolling down, img is within requestable area
img.canRequest = true;
img.canRender = false;
priority2.push(img);
continue;
}
if (img.bottom <= viewableTop && img.bottom > viewableTop - renderableBuffer) {
// scrolling down, img above viewable area
// but it's still within renderable area
// don't allow a reset
img.canRequest = img.canRender = false;
continue;
}
}
img.canRequest = img.canRender = false;
img.reset();
}
// update all imgs which are viewable
priority1.sort(sortTopToBottom).forEach(i => i.update());
if (scrollDirectionY === 'up') {
// scrolling up
priority2.sort(sortTopToBottom).reverse().forEach(i => i.update());
}
else {
// scrolling down
priority2.sort(sortTopToBottom).forEach(i => i.update());
}
}
function sortTopToBottom(a, b) {
if (a.top < b.top) {
return -1;
}
if (a.top > b.top) {
return 1;
}
return 0;
}
function parsePxUnit(val) {
return (val.indexOf('px') > 0) ? parseInt(val, 10) : 0;
}
function cssFormat(val) {
return (val > 0 ? val + 'px' : '');
}
//# sourceMappingURL=content.js.map