ng-page-slider
Version:
Mimicks the functionality of UIPageViewController in pure HTML for mobile web apps with Angular 2.
988 lines (987 loc) • 71 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
/*
This file contains some helpful types that are used throughout the module
*/
System.register("src/types", [], function (exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
var StackLocation;
return {
setters: [],
execute: function () {/*
This file contains some helpful types that are used throughout the module
*/
// The slider renders 3 pages to DOM at once, as follows
(function (StackLocation) {
StackLocation[StackLocation["Previous"] = 0] = "Previous";
StackLocation[StackLocation["Current"] = 1] = "Current";
StackLocation[StackLocation["Next"] = 2] = "Next";
})(StackLocation || (StackLocation = {}));
exports_1("StackLocation", StackLocation);
;
}
};
});
System.register("src/components/render.component", ["@angular/core", "src/types"], function (exports_2, context_2) {
"use strict";
var __moduleName = context_2 && context_2.id;
var core_1, types_1, KBPage, KBPagesRendererDirective;
return {
setters: [
function (core_1_1) {
core_1 = core_1_1;
},
function (types_1_1) {
types_1 = types_1_1;
}
],
execute: function () {
// PAGE CLASS ===============================================================================
// Stores information about each page that is accessible from the template
KBPage = (function () {
function KBPage($implicit, index, parent) {
this.$implicit = $implicit;
this.index = index;
this.parent = parent;
}
;
Object.defineProperty(KBPage.prototype, "isActive", {
get: function () { return this.parent.page == this.index; },
enumerable: true,
configurable: true
});
;
Object.defineProperty(KBPage.prototype, "isFirst", {
get: function () { return this.index == 0; },
enumerable: true,
configurable: true
});
Object.defineProperty(KBPage.prototype, "isLast", {
get: function () { return this.index == this.parent.pageCount - 1; },
enumerable: true,
configurable: true
});
return KBPage;
}());
exports_2("KBPage", KBPage);
KBPagesRendererDirective = (function () {
// Angular Injection
function KBPagesRendererDirective(viewContainer, template) {
this.viewContainer = viewContainer;
this.template = template;
// Initialization
this.isInitialized = false;
this.pageCountChange = new core_1.EventEmitter();
// Page access
this._page = 0;
// SIZING
this.pageWidth = 0;
this.pageHeight = 0;
// DOM RENDERING ========================================================================
this.views = [null, null, null];
}
Object.defineProperty(KBPagesRendererDirective.prototype, "kbPagesOf", {
set: function (coll) {
this.collection = coll;
if (this.isInitialized) {
this.ClearDOM();
this.CreateDOM();
}
},
enumerable: true,
configurable: true
});
KBPagesRendererDirective.prototype.ngOnInit = function () {
this.isInitialized = true;
this.CreateDOM();
};
Object.defineProperty(KBPagesRendererDirective.prototype, "pageCount", {
get: function () {
var count = (this.collection) ? this.collection.length : 0;
if (this._lastPageCount != count)
this.pageCountChange.emit(count);
return count;
},
enumerable: true,
configurable: true
});
Object.defineProperty(KBPagesRendererDirective.prototype, "page", {
get: function () { return this._page; },
set: function (page) { this.SetPage(page); },
enumerable: true,
configurable: true
});
KBPagesRendererDirective.prototype.SetPage = function (page) {
if (page < 0 || page >= this.pageCount)
return false;
var oldPage = this._page;
this._page = page;
this.ChangePage(page, oldPage);
return true;
};
KBPagesRendererDirective.prototype.Resize = function (width, height) {
this.pageWidth = width;
this.pageHeight = height;
if (this.isInitialized) {
this.ClearDOM();
this.CreateDOM();
}
};
// Renders 3 pages
KBPagesRendererDirective.prototype.CreateDOM = function () {
if (this.pageCount == 0 || this.collection == undefined)
return;
if (this.page > 0)
this.BuildPage(this.page - 1, types_1.StackLocation.Previous);
this.BuildPage(this.page, types_1.StackLocation.Current);
if (this.page < this.pageCount - 1)
this.BuildPage(this.page + 1, types_1.StackLocation.Next);
};
// Clears all pages out of the DOM, useful for re-rendering
KBPagesRendererDirective.prototype.ClearDOM = function () {
for (var _i = 0, _a = this.views; _i < _a.length; _i++) {
var view = _a[_i];
if (view)
view.destroy();
}
this.views = [null, null, null];
};
// HTML CONSTRUCTION AND MANAGEMENT
KBPagesRendererDirective.prototype.BuildPage = function (pageNumber, loc) {
if (pageNumber < 0 || pageNumber >= this.pageCount)
throw new Error("Attempted to create non-existent page: " + pageNumber);
// Create the page given the template
this.views[loc] = this.viewContainer.createEmbeddedView(this.template, new KBPage(this.collection[pageNumber], pageNumber, this));
// Style the page accordingly
for (var _i = 0, _a = this.views[loc].rootNodes; _i < _a.length; _i++) {
var rootNode = _a[_i];
this.StyleAsPage(rootNode);
this.StyleAtStackLocation(rootNode, loc);
}
};
// Styles a DOM element to be an absolute-positioned page-sized container
KBPagesRendererDirective.prototype.StyleAsPage = function (pageElement) {
pageElement.style.display = "block";
pageElement.style.position = "absolute";
pageElement.style.width = this.pageWidth + "px";
pageElement.style.height = this.pageHeight + "px";
};
// Styles a DOM element with an X location in the container
KBPagesRendererDirective.prototype.StyleAtStackLocation = function (pageElement, loc) {
var xLocationInContainer = loc * this.pageWidth;
pageElement.style.left = xLocationInContainer + "px";
};
// Moves an existing page to a new stack location
KBPagesRendererDirective.prototype.ChangeStackLocationOfView = function (curr, to) {
if (!this.views[curr])
throw new Error("View does not exist at location: " + curr);
for (var _i = 0, _a = this.views[curr].rootNodes; _i < _a.length; _i++) {
var rootNode = _a[_i];
this.StyleAtStackLocation(rootNode, to);
}
this.views[to] = this.views[curr];
this.views[curr] = null;
};
// NAVIGATION
// Updates rendering to display a new page
KBPagesRendererDirective.prototype.ChangePage = function (newPage, oldPage) {
// If the page is incrementing or decrementing, we can simply shift existing views
if (newPage == oldPage + 1) {
this.GoToNextPage();
}
else if (newPage == oldPage - 1) {
this.GoToPreviousPage();
// Otherwise, just rebuild the DOM around this new page
}
else {
this.ClearDOM();
this.CreateDOM();
}
};
KBPagesRendererDirective.prototype.GoToNextPage = function () {
// Remove the previous page from the DOM
if (this.views[types_1.StackLocation.Previous]) {
this.views[types_1.StackLocation.Previous].destroy();
this.views[types_1.StackLocation.Previous] = null;
}
// Shift the Current and Next pages backwards
this.ChangeStackLocationOfView(types_1.StackLocation.Current, types_1.StackLocation.Previous);
this.ChangeStackLocationOfView(types_1.StackLocation.Next, types_1.StackLocation.Current);
// Render a new page, if possible
if (this.page < this.pageCount - 1) {
this.BuildPage(this.page + 1, types_1.StackLocation.Next);
}
};
KBPagesRendererDirective.prototype.GoToPreviousPage = function () {
// Remove the previous page from the DOM
if (this.views[types_1.StackLocation.Next]) {
this.views[types_1.StackLocation.Next].destroy();
this.views[types_1.StackLocation.Next] = null;
}
// Shift the Current and Next pages backwards
this.ChangeStackLocationOfView(types_1.StackLocation.Current, types_1.StackLocation.Next);
this.ChangeStackLocationOfView(types_1.StackLocation.Previous, types_1.StackLocation.Current);
// Render a new page, if possible
if (this.page > 0) {
this.BuildPage(this.page - 1, types_1.StackLocation.Previous);
}
};
return KBPagesRendererDirective;
}());
__decorate([
core_1.Input(),
__metadata("design:type", Array),
__metadata("design:paramtypes", [Array])
], KBPagesRendererDirective.prototype, "kbPagesOf", null);
KBPagesRendererDirective = __decorate([
core_1.Directive({ selector: '[kbPages]' }),
__metadata("design:paramtypes", [core_1.ViewContainerRef,
core_1.TemplateRef])
], KBPagesRendererDirective);
exports_2("KBPagesRendererDirective", KBPagesRendererDirective);
}
};
});
System.register("src/components/navbutton.component", ["@angular/core"], function (exports_3, context_3) {
"use strict";
var __moduleName = context_3 && context_3.id;
var core_2, KBNavButtonComponent;
return {
setters: [
function (core_2_1) {
core_2 = core_2_1;
}
],
execute: function () {
KBNavButtonComponent = (function () {
function KBNavButtonComponent(forward, backward) {
this.pageChange = new core_2.EventEmitter();
this.size = 44;
this.showBackground = false;
this.backgroundColor = "white";
if (forward != undefined) {
if (backward != undefined) {
throw new Error("Nav Button cannot be both forward and backwards");
}
else {
this.isForward = true;
}
}
else if (backward != undefined) {
this.isForward = false;
}
else {
throw new Error("Must specify either 'forward' or 'backward' on nav button");
}
}
Object.defineProperty(KBNavButtonComponent.prototype, "disabled", {
// TEMPLATE FEATURES
get: function () {
if (this.isForward) {
return this.page >= this.pageCount - 1;
}
else {
return this.page <= 0;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(KBNavButtonComponent.prototype, "derivedIconColor", {
get: function () {
if (this.iconColor !== undefined)
return this.iconColor;
return (this.showBackground) ? "black" : "white";
},
enumerable: true,
configurable: true
});
Object.defineProperty(KBNavButtonComponent.prototype, "derivedBackgroundColor", {
get: function () {
return (this.showBackground) ? this.backgroundColor : "none";
},
enumerable: true,
configurable: true
});
Object.defineProperty(KBNavButtonComponent.prototype, "derivedSize", {
get: function () { return this.size + "px"; },
enumerable: true,
configurable: true
});
Object.defineProperty(KBNavButtonComponent.prototype, "halfSize", {
get: function () { return this.size / 2 + "px"; },
enumerable: true,
configurable: true
});
Object.defineProperty(KBNavButtonComponent.prototype, "symbol", {
get: function () {
return (this.isForward) ? "›" : "‹";
},
enumerable: true,
configurable: true
});
KBNavButtonComponent.prototype.OnClick = function () {
if (this.disabled)
return;
this.pageChange.emit((this.isForward) ? ++this.page : --this.page);
};
return KBNavButtonComponent;
}());
__decorate([
core_2.Input(),
__metadata("design:type", Number)
], KBNavButtonComponent.prototype, "page", void 0);
__decorate([
core_2.Output(),
__metadata("design:type", Object)
], KBNavButtonComponent.prototype, "pageChange", void 0);
__decorate([
core_2.Input(),
__metadata("design:type", Number)
], KBNavButtonComponent.prototype, "pageCount", void 0);
__decorate([
core_2.Input(),
__metadata("design:type", Number)
], KBNavButtonComponent.prototype, "size", void 0);
__decorate([
core_2.Input(),
__metadata("design:type", Boolean)
], KBNavButtonComponent.prototype, "showBackground", void 0);
__decorate([
core_2.Input(),
__metadata("design:type", String)
], KBNavButtonComponent.prototype, "iconColor", void 0);
__decorate([
core_2.Input(),
__metadata("design:type", String)
], KBNavButtonComponent.prototype, "backgroundColor", void 0);
KBNavButtonComponent = __decorate([
core_2.Component({
selector: 'kb-nav-button',
template: "\n\t\t<a\t(click)=\"OnClick()\"\n\t\t\t[innerHTML]=\"symbol\"\n\t\t\t[class.circle]=\"showBackground\"\n\t\t\t[class.disabled]=\"disabled\"\n\t\t\t[style.width]=\"derivedSize\" [style.height]=\"derivedSize\"\n\t\t\t[style.borderRadius]=\"halfSize\"\n\t\t\t[style.fontSize]=\"derivedSize\"\n\t\t\t[style.color]=\"derivedIconColor\"\n\t\t\t[style.backgroundColor]=\"derivedBackgroundColor\"\n\t\t></a>\n\t",
styles: [
":host {\n\t\t\tcursor: pointer;\n\t\t\t-webkit-touch-callout: none; /* iOS Safari */\n\t\t\t-webkit-user-select: none; /* Chrome/Safari/Opera */\n\t\t\t-khtml-user-select: none; /* Konqueror */\n\t\t\t-moz-user-select: none; /* Firefox */\n\t\t\t-ms-user-select: none; /* Internet Explorer/Edge */\n\t\t\tuser-select: none;\n\t\t}",
"a {\n\t\t\tdisplay: block;\n\t\t\ttext-align: center;\n \t\tline-height: 36px;\n\t\t}",
":host[forward] a {\n\t\t\tpadding-left: 3px;\n\t\t}",
":host[backward] a {\n\t\t\tpadding-right: 3px;\n\t\t}",
"a.circle {\n\t\t\tbox-shadow: 0 1px 2px rgba(0,0,0,0.25);\n\t\t}",
"a.disabled {\n\t\t\topacity: 0.33;\n\t\t}"
]
}),
__param(0, core_2.Attribute('forward')),
__param(1, core_2.Attribute('backward')),
__metadata("design:paramtypes", [String, String])
], KBNavButtonComponent);
exports_3("KBNavButtonComponent", KBNavButtonComponent);
}
};
});
/*
A special class that wraps CSS3 animations and also determines their ideal duration
based on momentum and distance to travel.
*/
System.register("src/functionality/animation", [], function (exports_4, context_4) {
"use strict";
var __moduleName = context_4 && context_4.id;
var kEasingFunction, kEasingStartSlope, kDefaultDuration, kMinDuration, kMaxDuration, SlideAnimation;
return {
setters: [],
execute: function () {/*
A special class that wraps CSS3 animations and also determines their ideal duration
based on momentum and distance to travel.
*/
kEasingFunction = "cubic-bezier(.35,.45,.5,1)";
kEasingStartSlope = 1.33;
kDefaultDuration = 250;
kMinDuration = 60;
kMaxDuration = 660;
SlideAnimation = (function () {
// The real meat of the animation code
// Hard-coded to the 'left' property because that's all we use here
// but certainly this code could be generalized if needed.
function SlideAnimation(element, current_px, dest_px, momentum_px, default_duration) {
var _this = this;
this.current_px = current_px;
this.dest_px = dest_px;
this.momentum_px = momentum_px;
this.default_duration = default_duration;
// Pseudo-promise
this.on_complete = [];
if (default_duration === undefined) {
this.default_duration = kDefaultDuration;
}
// Set up the CSS transition
var duration = Math.round(this.CalculateDuration());
var tProperty = "left " + duration + "ms " + kEasingFunction;
element.style.transition = tProperty;
element.style.webkitTransition = tProperty;
// Wait for that to propogate
setTimeout(function () {
// Move to the destination location
element.style.left = dest_px + "px";
// Wait for that to finish and clean it up
setTimeout(function () {
for (var _i = 0, _a = _this.on_complete; _i < _a.length; _i++) {
var f = _a[_i];
f();
}
element.style.transition = "";
element.style.webkitTransition = "";
}, duration + 10);
}, 10);
}
SlideAnimation.prototype.then = function (on_complete) {
this.on_complete.push(on_complete);
return this;
};
// HELPERS
// First step is figuring out the duration such that the starting
// momentum of the transition matches the user's scroll momentum.
// We could do this with 100% accuracy by determining the slope
// of the bezier easing curve but ... meh. It's about 1.5-ish.
SlideAnimation.prototype.CalculateDuration = function () {
var travel_px = this.dest_px - this.current_px;
// If the momentum is going the same direction as the movement, use it!
if (this.momentum_px != 0 && (this.momentum_px < 0) == (travel_px < 0)) {
var linear_duration = 1000 * Math.abs(travel_px) / Math.abs(this.momentum_px);
var estimate = linear_duration * kEasingStartSlope;
return Math.max(Math.min(estimate, kMaxDuration), kMinDuration);
// Otherwise, throw it out and use our default duration
}
else {
return this.default_duration;
}
};
return SlideAnimation;
}());
exports_4("SlideAnimation", SlideAnimation);
}
};
});
/**
* When the user clicks very close to the edge of a page, move in that direction.
*/
System.register("src/functionality/sideclick", [], function (exports_5, context_5) {
"use strict";
var __moduleName = context_5 && context_5.id;
var SideClickHandler;
return {
setters: [],
execute: function () {/**
* When the user clicks very close to the edge of a page, move in that direction.
*/
SideClickHandler = (function () {
function SideClickHandler(delegate, element) {
this.delegate = delegate;
this.element = element;
this.enabled = true;
this.threshold = 20; // 20px from the edge of the screen
element.addEventListener("click", this.ClickHandler.bind(this));
}
SideClickHandler.prototype.ClickHandler = function (e) {
if (!this.enabled)
return;
var elementX = e.clientX - this.element.getBoundingClientRect().left;
if (elementX < this.threshold) {
this.delegate.AnimateToPreviousPage(0);
}
else if (elementX > this.element.offsetWidth - this.threshold) {
this.delegate.AnimateToNextPage(0);
}
};
return SideClickHandler;
}());
exports_5("SideClickHandler", SideClickHandler);
}
};
});
// INTERACTIVITY - TOUCH EVENTS =============================================================
// Handles HTML touch events and formats it nicely for
System.register("src/functionality/touchevents", [], function (exports_6, context_6) {
"use strict";
var __moduleName = context_6 && context_6.id;
var kDistanceThreshold, kMomentumThreshold, kDistanceMomentumThreshold, kAcceptAtX, kRejectAtY, TouchEventHandler;
return {
setters: [],
execute: function () {// INTERACTIVITY - TOUCH EVENTS =============================================================
// Handles HTML touch events and formats it nicely for
// Snap back if user has moved less than 10% of the page
kDistanceThreshold = 0.1;
// If the user has moved less than 50% of the page, snap back
// unless that are moving at more than 30% the page width every second
kMomentumThreshold = 0.3;
kDistanceMomentumThreshold = 0.5;
// Ignore scrolls until they have moved at least 3% along X. If, during that time, they
// move more than 20px on Y, they will be rejected and interpreted instead as a vertical
// scroll gesture
kAcceptAtX = 0.03;
kRejectAtY = 20;
TouchEventHandler = (function () {
function TouchEventHandler(delegate, element) {
this.delegate = delegate;
// Touch tracking state
this.start_x = 0;
this.current_x = 0;
this.start_ypx = 0;
this.current_scroll = 1;
this.tracking = null;
this.accepted = false;
// MOMENTUM HIGH PASS
this.diffs_x = [0, 0, 0];
this.times_x = [20, 20, 20];
this.diffs_index = 0;
// Add touch event listeners
element.addEventListener("touchstart", this.TouchStart.bind(this));
element.addEventListener("touchmove", this.TouchMove.bind(this));
element.addEventListener("touchend", this.TouchEnd.bind(this));
element.addEventListener("touchcancel", this.TouchEnd.bind(this));
}
TouchEventHandler.prototype.CaptureXDiff = function (diff) {
this.diffs_x[this.diffs_index] = diff;
var ctime = new Date().getTime();
this.times_x[this.diffs_index] = ctime - this.last_sample_time;
this.last_sample_time = ctime;
if (++this.diffs_index == this.diffs_x.length)
this.diffs_index = 0;
};
Object.defineProperty(TouchEventHandler.prototype, "momentum_x", {
// Returns the scroll momentum in fractional page widths per second.
// (fpw/s * page width = px/s)
get: function () {
var acc = 0;
for (var i = 0; i < this.diffs_x.length; i++) {
acc += (this.diffs_x[i] / this.times_x[i]) * 1000 / 3;
}
return acc;
},
enumerable: true,
configurable: true
});
// DOM EVENT HANDLERS ===================================================================
TouchEventHandler.prototype.TouchStart = function (event) {
if (this.tracking)
return;
if (event.touches.length > 1)
return;
this.tracking = event.touches.item(0).identifier;
this.start_x = event.touches.item(0).clientX / this.delegate.pageWidth;
this.current_x = this.start_x;
this.start_ypx = event.touches.item(0).clientY;
this.last_sample_time = new Date().getTime();
this.accepted = false;
};
TouchEventHandler.prototype.TouchMove = function (event) {
var touch = this.GetTrackingTouch(event.changedTouches);
if (touch == null)
return;
var new_x = touch.clientX / this.delegate.pageWidth;
var diff_x = new_x - this.current_x;
if (!this.accepted) {
if (Math.abs(new_x - this.start_x) >= kAcceptAtX) {
if (Math.abs(touch.clientY - this.start_ypx) > kRejectAtY) {
this.tracking = null;
return;
}
else {
this.accepted = true;
this.delegate.StartScroll();
}
}
else
return;
}
event.preventDefault();
this.CaptureXDiff(diff_x);
this.current_scroll = this.current_scroll - diff_x;
this.delegate.ScrollTo(this.current_scroll);
this.current_x = new_x;
};
TouchEventHandler.prototype.TouchEnd = function (event) {
var touch = this.GetTrackingTouch(event.changedTouches);
if (touch == null)
return;
this.tracking = null;
if (this.start_x == this.current_x)
return;
if (!this.accepted)
return;
event.preventDefault();
this.delegate.EndScroll();
this.current_scroll = 1;
var ending_momentum_x = this.momentum_x;
if (this.current_x + kDistanceThreshold < this.start_x) {
if (this.current_x + kDistanceMomentumThreshold < this.start_x ||
-ending_momentum_x > kMomentumThreshold) {
this.delegate.AnimateToNextPage(ending_momentum_x);
}
else {
this.delegate.AnimateToX(1, ending_momentum_x);
}
}
else if (this.current_x - kDistanceThreshold > this.start_x) {
if (this.current_x - kDistanceMomentumThreshold > this.start_x ||
ending_momentum_x > kMomentumThreshold) {
this.delegate.AnimateToPreviousPage(ending_momentum_x);
}
else {
this.delegate.AnimateToX(1, ending_momentum_x);
}
}
else {
this.delegate.AnimateToX(1, ending_momentum_x);
}
};
// HELPERS
TouchEventHandler.prototype.GetTrackingTouch = function (list) {
if (this.tracking === null)
return null;
for (var i = 0; i < list.length; i++) {
var touch = list.item(i);
if (touch.identifier == this.tracking)
return touch;
}
return null;
};
return TouchEventHandler;
}());
exports_6("TouchEventHandler", TouchEventHandler);
}
};
});
/**
* When the user clicks very close to the edge of a page, move in that direction.
*/
System.register("src/functionality/arrowkeys", [], function (exports_7, context_7) {
"use strict";
var __moduleName = context_7 && context_7.id;
var ArrowKeysHandler;
return {
setters: [],
execute: function () {/**
* When the user clicks very close to the edge of a page, move in that direction.
*/
ArrowKeysHandler = (function () {
function ArrowKeysHandler(delegate) {
this.delegate = delegate;
this.enabled = true;
document.addEventListener("keydown", this.KeyHandler.bind(this));
}
ArrowKeysHandler.prototype.KeyHandler = function (e) {
if (!this.enabled)
return;
if (e.keyCode == 37) {
this.delegate.AnimateToPreviousPage(0);
}
else if (e.keyCode == 39) {
this.delegate.AnimateToNextPage(0);
}
};
return ArrowKeysHandler;
}());
exports_7("ArrowKeysHandler", ArrowKeysHandler);
}
};
});
System.register("src/components/pageslider.component", ["src/components/render.component", "@angular/core", "src/components/navbutton.component", "src/functionality/animation", "src/functionality/sideclick", "src/functionality/touchevents", "src/functionality/arrowkeys"], function (exports_8, context_8) {
"use strict";
var __moduleName = context_8 && context_8.id;
var core_3, render_component_1, navbutton_component_1, animation_1, sideclick_1, touchevents_1, arrowkeys_1, KBPageSliderComponent;
return {
setters: [
function (render_component_2_1) {
exports_8({
"KBPagesRendererDirective": render_component_2_1["KBPagesRendererDirective"],
"KBPage": render_component_2_1["KBPage"]
});
render_component_1 = render_component_2_1;
},
function (core_3_1) {
core_3 = core_3_1;
},
function (navbutton_component_1_1) {
navbutton_component_1 = navbutton_component_1_1;
},
function (animation_1_1) {
animation_1 = animation_1_1;
},
function (sideclick_1_1) {
sideclick_1 = sideclick_1_1;
},
function (touchevents_1_1) {
touchevents_1 = touchevents_1_1;
},
function (arrowkeys_1_1) {
arrowkeys_1 = arrowkeys_1_1;
}
],
execute: function () {
KBPageSliderComponent = (function () {
function KBPageSliderComponent(element) {
this.element = element;
this.pageChange = new core_3.EventEmitter();
this.pageSizeChange = new core_3.EventEmitter();
this.pageCountChange = new core_3.EventEmitter();
// Dot Indicator
this.showIndicator = true;
this.overlayIndicator = true;
this.dotColor = "white";
// Interactivity
this.locked = false;
this.enableOverscroll = true;
this.scrollStateChange = new core_3.EventEmitter();
// INTERNAL STATE =======================================================================
this._pageOffset = 1;
// INTERACTIVE NAVIGATION ===============================================================
this.blockInteraction = false;
var htmlElement = this.element.nativeElement;
this.touchEventHandler = new touchevents_1.TouchEventHandler(this, htmlElement);
this.sideClickHandler = new sideclick_1.SideClickHandler(this, htmlElement);
this.arrowKeysHandler = new arrowkeys_1.ArrowKeysHandler(this);
}
Object.defineProperty(KBPageSliderComponent.prototype, "page", {
get: function () { return (this.renderer) ? this.renderer.page : 0; },
// PUBLIC INTERFACE =====================================================================
set: function (pn) {
if (pn < 0 || pn >= this.pageCount)
return;
if (pn == this.renderer.page)
return;
if (this.renderer) {
if (pn == this.renderer.page + 1) {
if (this.blockInteraction) {
this.pageChange.emit(this.page);
return;
}
this.AnimateToNextPage();
}
else if (pn == this.renderer.page - 1) {
if (this.blockInteraction) {
this.pageChange.emit(this.page);
return;
}
this.AnimateToPreviousPage();
}
else {
if (this.blockInteraction) {
this.pageChange.emit(this.page);
return;
}
this.renderer.page = pn;
this.pageChange.emit(pn);
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "pageCount", {
get: function () { return (this.renderer) ? this.renderer.pageCount : 0; },
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "enableSideClicks", {
set: function (enabled) {
(this.sideClickHandler) ? this.sideClickHandler.enabled = enabled : null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "enableArrowKeys", {
set: function (enabled) {
(this.arrowKeysHandler) ? this.arrowKeysHandler.enabled = enabled : null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "pageOffset", {
get: function () { return this._pageOffset; },
set: function (v) {
this._pageOffset = v;
if (!this.blockInteraction) {
this.innerContainer.style.left = this.pxOffset;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "pxOffset", {
get: function () { return -this.pageOffset * this.pageWidth + "px"; },
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "buttonTop", {
get: function () {
return this.pageHeight / 2 - this.buttons.first.size / 2 + "px";
},
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "pageWidth", {
// SIZING
get: function () { return this.element.nativeElement.offsetWidth; },
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "pageHeight", {
get: function () {
var fullHeight = this.element.nativeElement.offsetHeight;
var chin = (this.showIndicator && !this.overlayIndicator) ? 20 : 0;
return fullHeight - chin;
},
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "containerWidth", {
get: function () { return this.pageWidth * 3 + "px"; },
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "containerHeight", {
get: function () { return this.pageHeight + "px"; },
enumerable: true,
configurable: true
});
Object.defineProperty(KBPageSliderComponent.prototype, "dotBottom", {
get: function () { return (this.overlayIndicator) ? "16px" : "0px"; },
enumerable: true,
configurable: true
});
KBPageSliderComponent.prototype.ngOnInit = function () {
var _this = this;
if (!this.renderer) {
console.log("\n\t\t\t\tThe *kbPages directive is used to render pages efficiently, such that only\n\t\t\t\tpages that are visible are in the DOM. Without this directive, the page\n\t\t\t\tslider will not display anything.\n\t\t\t");
throw new Error('No *kbPages directive found inside kb-page-slider');
}
this.renderer.pageCountChange.subscribe(function (count) {
_this.pageCountChange.emit(count);
});
this.Resize();
this.renderer.Resize(this.pageWidth, this.pageHeight);
window.addEventListener("resize", function () {
_this.Resize();
_this.renderer.Resize(_this.pageWidth, _this.pageHeight);
_this.pageSizeChange.emit([_this.pageWidth, _this.pageHeight]);
});
};
KBPageSliderComponent.prototype.Resize = function () {
this.innerContainer = this.element.nativeElement.querySelector(".inner");
this.innerContainer.style.left = -this.pageWidth + "px";
};
KBPageSliderComponent.prototype.ScrollTo = function (x) {
if (this.locked || this.blockInteraction)
return;
this.pageOffset = this.ClampX(x);
};
KBPageSliderComponent.prototype.AnimateToNextPage = function (momentum) {
var _this = this;
if (this.locked || this.blockInteraction)
return null;
if (this.page == this.renderer.pageCount - 1) {
return this.AnimateToX(1, 0).then(function () { _this.pageOffset = 1; });
}
if (momentum === undefined)
momentum = 0;
return this.AnimateToX(2, momentum).then(function () {
_this.renderer.page++;
_this.pageChange.emit(_this.renderer.page);
_this.pageOffset = 1;
});
};
KBPageSliderComponent.prototype.AnimateToPreviousPage = function (momentum) {
var _this = this;
if (this.locked || this.blockInteraction)
return null;
if (this.page == 0) {
return this.AnimateToX(1, 0).then(function () { _this.pageOffset = 1; });
}
if (momentum === undefined)
momentum = 0;
return this.AnimateToX(0, momentum).then(function () {
_this.renderer.page--;
_this.pageChange.emit(_this.renderer.page);
_this.pageOffset = 1;
});
};
KBPageSliderComponent.prototype.AnimateToX = function (x, momentum) {
var _this = this;
if (this.locked || this.blockInteraction)
return null;
this.blockInteraction = true;
var w = this.pageWidth;
return new animation_1.SlideAnimation(this.innerContainer, // Element to animate
-this.pageOffset * w, // Current position (px)
-x * w, // Destination position (px)
momentum * w, // User scroll momentum (px/s)
this.transitionDuration // Default duration, when momentum = 0
).then(function () {
_this.blockInteraction = false;
});
};
KBPageSliderComponent.prototype.StartScroll = function () { this.scrollStateChange.emit(true); };
KBPageSliderComponent.prototype.EndScroll = function () { this.scrollStateChange.emit(false); };
// OVERSCROLL (iOS STYLE) ===============================================================
// Get X to a reasonable range, taking into account page boundaries
KBPageSliderComponent.prototype.ClampX = function (x) {
if (x < 0)
x = 0;
if (x > 2)
x = 2;
// Allow some overscrolling on the first and last page
if (this.page == 0 && x < 1) {
if (this.enableOverscroll)
x = 1 - this.OverscrollRamp(1 - x);
else
x = 1;
}
if (this.page == this.renderer.pageCount - 1 && x > 1) {
if (this.enableOverscroll)
x = 1 + this.OverscrollRamp(x - 1);
else
x = 1;
}
return x;
};
// Exponential ramp to simulate elastic pressure on overscrolling
KBPageSliderComponent.prototype.OverscrollRamp = function (input) {
return Math.pow(input, 0.5) / 5;
};
return KBPageSliderComponent;
}());
__decorate([
core_3.Input(),
__metadata("design:type", Number),
__metadata("design:paramtypes", [Number])
], KBPageSliderComponent.prototype, "page", null);
__decorate([
core_3.Output(),
__metadata("design:type", Object)
], KBPageSliderComponent.prototype, "pageChange", void 0);
__decorate([
core_3.Output(),
__metadata("design:type", Object)
], KBPageSliderComponent.prototype, "pageSizeChange", void 0);
__decorate([
core_3.Output(),
__metadata("design:type", Object)
], KBPageSliderComponent.prototype, "pageCountChange", void 0);
__decorate([
core_3.Input(),
__metadata("design:type", Boolean)
], KBPageSliderComponent.prototype, "showIndicator", void 0);
__decorate([
core_3.Input(),
__metadata("design:type", Boolean)
], KBPageSliderComponent.prototype, "overlayIndicator", void 0);
__decorate([
core_3.Input(),