jsdk-offical
Version:
JSDK is the most comprehensive TypeScript framework, like JDK.
219 lines (193 loc) • 8.02 kB
text/typescript
/**
* @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>
}
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;