UNPKG

jsdk-offical

Version:

JSDK is the most comprehensive TypeScript framework, like JDK.

219 lines (193 loc) 8.02 kB
/** * @project JSDK * @license MIT * @website https://github.com/fengboyue/jsdk * * @version 2.0.0 * @author Frank.Feng */ /// <reference path="Widget.ts"/> module JS { export namespace fx { /** * @type CarouselItem */ export type CarouselItem = { src: string; caption?: string; desc?: string; imgAlt?: string; } export class CarouselConfig extends WidgetConfig<Carousel> { items?: Array<CarouselItem>; /** * The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle. * * @default 5000 */ interval?: number | false = 5000 //5 seconds /** * Actived item index */ activeIndex?: number = 0; listeners?: CarouselListeners; } export type CarouselEvents = WidgetEvents | 'transiting' | 'transited'; /** * [fromIndex,toIndex] */ export type CarouselEventHandler_Transiting<W> = EventHandler2<W, number, number>; /** * [fromIndex,toIndex] */ export type CarouselEventHandler_Transited<W> = EventHandler2<W, number, number>; export interface CarouselListeners extends WidgetListeners<Carousel> { transiting?: CarouselEventHandler_Transiting<Carousel> transited?: CarouselEventHandler_Transited<Carousel> } @widget('JS.fx.Carousel') export class Carousel extends Widget { constructor(cfg: CarouselConfig) { super(cfg) } public prev(): Carousel { this.widgetEl.carousel('prev'); return this; } public next(): Carousel { this.widgetEl.carousel('next'); return this; } public pause(): Carousel { this.widgetEl.carousel('pause'); return this; } public cycle(): Carousel { this.widgetEl.carousel('cycle'); return this; } /** * Slide index from 0. * @param num */ public goto(num: number): Carousel { this.widgetEl.carousel(num); return this; } protected _destroy() { this.widgetEl.carousel('dispose'); super._destroy(); } public length() { let items = (<CarouselConfig>this._config).items; return !items ? 0 : items.length } public add(item: CarouselItem, from?: number) { let size = this.length(); if (!Types.isDefined(from) || from >= size) from = size-1; let cfg = <CarouselConfig>this._config; cfg.items = cfg.items||[]; cfg.items.add([item], from); this._renderItems(from); return this } public remove(num: number) { if (!Types.isDefined(num) || num < 0) return this; let size = this.length(); if (size == 0 || num >= size) return this; let cfg = <CarouselConfig>this._config; if (!cfg.items) cfg.items = []; cfg.items.remove(num); this._renderItems(num>=0?num:0); return this } public clear() { this.widgetEl.find('.carousel-indicators').empty(); this.widgetEl.find('.carousel-inner').empty(); (<CarouselConfig>this._config).items = null; } private _limitActive() { let cfg = <CarouselConfig>this._config, size = this.length(); cfg.activeIndex = cfg.activeIndex >= (size-1) ? (size-1) : (cfg.activeIndex <= 0 ? 0 : cfg.activeIndex); } private _indHtml(i: number) { let is = (<CarouselConfig>this._config).activeIndex == i; return `<li data-target="#${this.id}" data-slide-to="${i}" class="${is ? 'active' : ''}"></li>` } private _itemHtml(item: CarouselItem, i: number) { let is = (<CarouselConfig>this._config).activeIndex == i; let capHtml = ''; if (item.caption || item.desc) { capHtml = `<div class="carousel-caption d-md-block"> <h5>${item.caption || ''}</h5> <p>${item.desc || ''}</p> </div>` } return ` <div class="carousel-item ${is ? 'active' : ''}" jsfx-index="${i}"> <img class="d-block w-100" src="${item.src}" style="height:${CssTool.normValue(this._config.height, '100%')};" alt="${item.imgAlt || ''}"> ${capHtml} </div> ` } private _renderItems(num:number) { this._limitActive(); let cfg = <CarouselConfig>this._config, indsHtml = '', itemsHtml = ''; if (cfg.items) cfg.items.forEach((item, i) => { indsHtml += this._indHtml(i); itemsHtml += this._itemHtml(item, i); }) this.pause(); this.widgetEl.find('.carousel-indicators').html(indsHtml); this.widgetEl.find('.carousel-inner').html(itemsHtml); this.widgetEl.carousel({ interval: <number>cfg.interval }); this.goto(num); } protected _render() { this._limitActive(); let cfg = <CarouselConfig>this._config, indsHtml = '', itemsHtml = ''; if (cfg.items) cfg.items.forEach((item, i) => { indsHtml += this._indHtml(i); itemsHtml += this._itemHtml(item, i); }) let html = ` <ol class="carousel-indicators"> ${indsHtml} </ol> <div class="carousel-inner" style="height:${CssTool.normValue(cfg.height,'100%')}"> ${itemsHtml} </div> <a class="carousel-control-prev" href="#${this.id}" role="button" data-slide="prev"> <span class="carousel-control-prev-icon" aria-hidden="true"></span> </a> <a class="carousel-control-next" href="#${this.id}" role="button" data-slide="next"> <span class="carousel-control-next-icon" aria-hidden="true"></span> </a> ` this.widgetEl.attr('data-ride', 'carousel'); this.widgetEl.addClass('carousel slide bg-light'); this.widgetEl.css({ 'width': CssTool.normValue(cfg.width,'100%') }) this.widgetEl.html(html); this.widgetEl.on('slide.bs.carousel', (e) => { let from = e.from, to = e.to; if (from != -1 && to != -1) this._fire('transiting', [from, to])//BUGFIX: bootstrap has repeat event when from/to=-1 }) this.widgetEl.on('slid.bs.carousel', (e) => { let from = e.from, to = e.to; this._fire('transited', [from, to]) }) this.widgetEl.carousel({ interval: <number>cfg.interval }); } } } } import Carousel = JS.fx.Carousel; import CarouselEvents = JS.fx.CarouselEvents; import CarouselListeners = JS.fx.CarouselListeners; import CarouselConfig = JS.fx.CarouselConfig; import CarouselItem = JS.fx.CarouselItem;