UNPKG

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
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) ? "&rsaquo;" : "&lsaquo;"; }, 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(),