1 Star 0 Fork 5

-曾國华-/angular2-layer

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
ng2-layer.ts 15.83 KB
一键复制 编辑 原始数据 按行查看 历史
lw 提交于 2017-01-07 04:57 . README.md
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
import {
Compiler,
Component,
NgModule,
Injectable,
ViewContainerRef,
ApplicationRef,
ReflectiveInjector,
ModuleWithComponentFactories,
ComponentRef,
ViewChild
} from '@angular/core';
export class LayerConfig {
/**
* the new component will be a child of parent, if parent is null,
* new component will be a root component of application.
* valid only for dialog leyer
*/
parent:ViewContainerRef;
/**
* a class for creating new component
* valid only for dialog leyer
*/
dialogComponent:any;
/**
* dialog title
* valid only for dialog leyer
*/
title:string;
/**
* show close button or not.
* valid only for dialog leyer
*/
closeAble:boolean;
/**
* message type of tip layer.
* valid for alert, confirm, tip, loading leyer
*/
message:string;
/**
* text of "ok" button.
* valid for alert or confirm leyer
*/
okText:string;
/**
* text of "cancel" button
* valid only for confirm leyer
*/
cancelText:string;
/**
* position of the layer("top", "center", "bottom"), default to "top"
* valid only for loading or tip leyer
*/
align:string;
/**
* modal window or not
* valid only for loading leyer
*/
isModal:boolean;
/**
* layer will be automatic closed after duration(ms)
* valid only for tip leyer
*/
tipDuration:number;
/**
* defined a popup animation by a class selector
* valid for all type leyer.
*
* existing options:
* rollIn, fallDown, fadeInDown, runIn, bounceIn,
* splatIn, dropDown, vanishIn, spaceIn, jelly, fadeInUp,
*/
inSelector:string;
/**
* defined a closeing animation by a class selector
* valid for all type leyer.
*
* existing options:
* rollOut, fadeOutDown, bounceOut, vanishOut, spaceOut,
* boingOut, fadeOutDown
*/
outSelector:string;
}
export class NgLayerRef {
layerComponent:any;
/**
* destory the layer.
*/
close(){
this.layerComponent.close();
};
/**
* show close button or not
*/
showCloseBtn(show:boolean):NgLayerRef{
this.layerComponent.config.closeAble=show;
return this;
}
/**
* update dialog title. for dialog only
*
* @return {NgLayerRef}
*/
setTitle(title:string):NgLayerRef{
this.layerComponent.config.title=title;
return this;
}
/**
* update message of layer
*
* e.g.
*
* ```typescript
* let tip = this.ly.tip("保存成功", 1000, "top", "warn");
* setTimeout(()=>{
* lyRef.setMessage("successfully saved").setTipType("success");
* lyRef.close();
* }, 2000);
*
* ```
* @return {NgLayerRef}
*/
setMessage(message:string):NgLayerRef{
this.layerComponent.config.message=message;
return this;
}
/**
* if the callBack return ture, the layer will be closed
*
* e.g.
*
* ```typescript
* let lyRef = this.ly.confirm("are you sure?", "yes", "no");
* lyRef.setOnClose(()=>{
* if(...) return true;
* });
* ```
* @return {NgLayerRef}
*/
setOnClose(callBack:()=>boolean):NgLayerRef{
this.layerComponent.onClose = callBack;
return this;
}
/**
* update "ok" button text, for alert layer or confirm layer
*
* e.g.
*
* ```typescript
*let lyRef = this.ly.confirm("are you sure?", "yes", "no");
*lyRef.setOkText("sure");
* ```
* @return {NgLayerRef}
*/
setOkText(ok:string):NgLayerRef{
this.layerComponent.config.okTxt=ok;
return this;
}
/**
* update "cancel" button text, for confirm layer only
*
* e.g.
*
* ```typescript
*let lyRef = this.ly.confirm("are you sure?", "yes", "no");
*lyRef.setCancelText("not sure");
* ```
* @return {NgLayerRef}
*/
setCancelText(cancel:string):NgLayerRef{
this.layerComponent.config.cancelTxt=cancel;
return this;
}
/**
* message type of tip layer
*
* e.g.
*
* ```typescript
*let lyRef = this.ly.tip("saving...", "yes", "no");
*lyRef.setTipType("error");
* ```
* @return {NgLayerRef}
*/
/*setTipType(tipType:string){
this.layerComponent.config.tipType=tipType;
return this;
}*/
/**
* okCallback called on 'ok' button click. for alert layer or confirm layer
*
* e.g.
*
* ```typescript
*let lyRef = this.ly.confirm("are you sure?", "yes", "no");
*lyRef.ok(()=>{
* ...do something...
* });
* ```
* @return {NgLayerRef}
*/
ok(okCallback:()=>boolean):NgLayerRef{
this.layerComponent.onOk=okCallback;
return this;
}
/**
* cancelCallback called on "cancel" button click. for confirm layer only
*
* e.g.
*
* ```typescript
*let lyRef = this.ly.confirm("are you sure?", "yes", "no");
*lyRef.ok(()=>{
* ...do something...
* });
* ```
*
* @return {NgLayerRef}
*/
cancel(cancelCallback:()=>boolean):NgLayerRef{
this.layerComponent.onCancel=cancelCallback;
return this;
}
}
@Injectable()
export class NgLayer {
constructor(private compiler: Compiler, private appRef: ApplicationRef) {}
/**
* open a dialog window
* @return {NgLayerRef}
*/
dialog(config:LayerConfig):NgLayerRef {
let layerId = "layer_"+new Date().getTime()
return this.createComponent_(config, layerId);
}
/**
* open a alert window
*
* @return {NgLayerRef}
*/
alert(config:LayerConfig):NgLayerRef{
return this.confirmOralert_(config, false);
}
/**
* open a confirm window
*
* @return {NgLayerRef}
*/
confirm(config:LayerConfig):NgLayerRef{
return this.confirmOralert_(config, true);
}
/**
* open a message layer
*
* @return {NgLayerRef}
*/
tip(config:LayerConfig):NgLayerRef{
return this.tipOrLoading_(config, true);
}
/**
* open a loading layer
*
* @return {NgLayerRef}
*/
loading(config:LayerConfig):NgLayerRef{
return this.tipOrLoading_(config, false);
}
/**
*
*/
tipOrLoading_(config:LayerConfig, isTip:boolean){
if(!config.outSelector){
config.outSelector = "boingOut";
}
config = this.default_(config);
let temp = '<div class="iconing_tip_body iconing_type_{{layerType}}">{{config.message}}</div>',
layerId = "layer_"+new Date().getTime(),
div = document.createElement("div"),
claz = div.classList,
modalStr;
claz.add("iconing_tip_backdrop");
claz.add(layerId);
if(!config.align || ["center", "bottom", "top"].indexOf(config.align)<0){
config.align = "top";
}
if(config.isModal){
claz.add("iconing_loading_modal");
modalStr = ".iconing_loading_modal";
} else {
modalStr = "";
}
claz.add("iconing_align_"+config.align);
document.body.appendChild(div);
@Component({
selector:".iconing_tip_backdrop."+layerId+".iconing_align_"+config.align+modalStr,
template:temp,
providers:[NgLayerRef]
})
class LayerWraper {
thizRef:ComponentRef<any>;
layerEle:any;
layerType:string = isTip?"tip":"loading";
config:LayerConfig = config;
constructor(private layerRef:NgLayerRef, private self:ViewContainerRef) {
layerRef.layerComponent = this;
this.layerRef = layerRef;
}
ngAfterViewInit(){
this.layerEle = this.self.element.nativeElement.querySelector(".iconing_tip_body");
if(this.config.inSelector){
this.layerEle.classList.add(this.config.inSelector);
}
if(isTip) setTimeout(()=>this.close(), config.tipDuration+this.calCss_());
}
/** */
close(){
if(this.config.outSelector){
let classList = this.layerEle.classList;
classList.remove(this.config.inSelector);
classList.add(this.config.outSelector);
/**
* set a delay for layer closeing so the animation has time to play
*/
setTimeout(()=>{this.thizRef.destroy();}, this.calCss_());
} else {
this.thizRef.destroy();
}
}
calCss_(){
let anima = getComputedStyle(this.layerEle).animationDuration,
trans = getComputedStyle(this.layerEle).animationDuration,
n1 = parseFloat(anima),
n2 = parseFloat(trans);
if(n1){
let unit = anima.replace(n1.toString(), "").toLowerCase();
n1 = unit=="ms"?n1:unit=="s"?n1*1000:0;
}
if(n2){
let unit = anima.replace(n2.toString(), "").toLowerCase();
n2 = unit=="ms"?n2:unit=="s"?n2*1000:0;
}
return Math.max(n1,n2)-5;
}
}
@NgModule({declarations: [LayerWraper]})
class DM {}
/** create layer */
let moduleWithComponentFactories = this.compiler.compileModuleAndAllComponentsSync(DM),
factory = moduleWithComponentFactories.componentFactories[0],
layerWraper = this.appRef.bootstrap(factory);
layerWraper.instance.thizRef = layerWraper;
return layerWraper.instance.layerRef;
}
confirmOralert_(config:LayerConfig, isConfirm:boolean){
let layerId = "layer_"+new Date().getTime(),
div = document.createElement("div");
div.classList.add("iconing_layer_backdrop");
div.classList.add(layerId);
document.body.appendChild(div);
let temp:string = '<div class="iconing_layer_body iconing_alert_body">'+
'<div class="iconing_content">{{config.message}}</div>'+
'<div class="iconing_alert_btn">CANCELBUTTON'+
'<button class="iconing_btn_ok" (click)="ok()">{{config.okText}}</button>'+
'</div>'+
'</div>';
temp = isConfirm?temp.replace("CANCELBUTTON",'<button class="iconing_btn_cancel" (click)="cancel()">{{config.cancelText}}</button>'):temp.replace("CANCELBUTTON","");
let layerWraperType = this.createComponentClass_(config, temp, layerId);
@NgModule({declarations: [layerWraperType]})
class DM {}
/** create layer */
let moduleWithComponentFactories = this.compiler.compileModuleAndAllComponentsSync(DM),
factory = moduleWithComponentFactories.componentFactories[0],
layerWraper = this.appRef.bootstrap(factory);
layerWraper.instance.thizRef = layerWraper;
document.body.appendChild(layerWraper.location.nativeElement);
return layerWraper.instance.layerRef;
}
/**
*
*/
createComponentClass_(
config:LayerConfig,
temp:string,
layerId:string
){
config = this.default_(config);
@Component({
selector:".iconing_layer_backdrop."+layerId,
template:temp,
providers:[NgLayerRef]
})
class layerWraper {
thizRef:ComponentRef<any>;
layerEle:any;
backdropStyle:any;
config:LayerConfig=config;
@ViewChild('iconing_layer_content', {read: ViewContainerRef})
layerView:ViewContainerRef;
/**
*
*/
constructor(private layerRef:NgLayerRef, private compiler: Compiler, private self:ViewContainerRef) {
layerRef.layerComponent = this;
}
/**
* add enter state selector to layer body
*/
ngAfterViewInit(){
let cfg = this.config;
this.layerEle = this.self.element.nativeElement.querySelector(".iconing_layer_body");
if(cfg.inSelector){
this.layerEle.classList.add(cfg.inSelector);
this.backdropStyle.background = "rgba(95, 95, 95, 0.5)";
this.backdropStyle.transition = "background "+this.calCss_(this.layerEle)+"ms";
}
}
/**
*
*/
ngOnInit(){
this.backdropStyle = this.self.element.nativeElement.style;
if(config.dialogComponent){
@NgModule({declarations: [config.dialogComponent]})
class TempModule {}
let moduleWithComponentFactories = this.compiler.compileModuleAndAllComponentsAsync(TempModule);
moduleWithComponentFactories.then((mvcf: ModuleWithComponentFactories <any>)=>{
let injector = ReflectiveInjector.fromResolvedProviders([], this.layerView.injector);
this.layerView.createComponent(mvcf.componentFactories[0], null, injector, []);
});
}
}
/** */
close(){
let cfg = this.config;
if(!this.onClose || this.onClose()) {
if(cfg.outSelector){
let classList = this.layerEle.classList;
classList.remove(cfg.inSelector);
classList.add(cfg.outSelector);
let duration = this.calCss_(this.layerEle);
this.backdropStyle.background = "rgba(138, 138, 138, 0.5)";
this.backdropStyle.transition = "background "+duration+"ms";
/**
* set a delay for layer closeing so the animation has time to play
*/
setTimeout(()=>{this.thizRef.destroy();}, duration);
} else {
this.thizRef.destroy();
}
}
}
cancel(){
if(!this.onCancel || this.onCancel()) this.close();
}
onClose():boolean{return true}
onCancel():boolean{return true}
onOk():boolean{return true}
/**
* alert or confirm layer
*/
ok(){
if(!this.onOk || this.onOk()) this.close();
}
/**
*
*/
calCss_(ele:any){
let anima = getComputedStyle(ele).animationDuration,
trans = getComputedStyle(ele).animationDuration,
n1 = parseFloat(anima),
n2 = parseFloat(trans);
if(n1){
let unit = anima.replace(n1.toString(), "").toLowerCase();
n1 = unit=="ms"?n1:unit=="s"?n1*1000:0;
}
if(n2){
let unit = anima.replace(n2.toString(), "").toLowerCase();
n2 = unit=="ms"?n2:unit=="s"?n2*1000:0;
}
return Math.max(n1,n2);
}
}
return layerWraper;
}
private modifySelector_<T>(clazz:T, contentSelector:string) {
if(!(Reflect && Reflect.getOwnMetadata)){
throw 'reflect-metadata shim is required when using class decorators';
}
let mateData = Reflect.getOwnMetadata("annotations", new clazz().constructor);
let parentMateData = mateData.find(annotation => {
if(annotation.toString()==="@Component") return annotation;
})
if(!parentMateData){
throw 'component type required a @Component decorator';
}
let newMataData = {selector:""};
for(let i of Object.keys(parentMateData)){
newMataData[i]=parentMateData[i];
}
newMataData.selector = '.'+contentSelector;
let clazzTarget = Component(newMataData)(clazz);
return clazzTarget;
}
private createComponent_(config:LayerConfig, layerId:string) {
config.dialogComponent = this.modifySelector_(config.dialogComponent, "iconing_layer_content");
let temp = '<div class="iconing_layer_body">'+
'<div class="iconing_layer_header">'+
'<div class="iconing_layer_title">{{config.title}}</div>'+
'<button (click)="close();" class="iconing_layer_close_btn {{config.closeAble?\'iconing_layer_close_able\':\'\'}}"></button>'+
'</div>'+
'<div #iconing_layer_content></div>'+
'</div>'
let layerWraperType = this.createComponentClass_(config, temp, layerId);
@NgModule({declarations: [layerWraperType]})
class DM {}
/**
* create layer
*/
let moduleWithComponentFactories = this.compiler.compileModuleAndAllComponentsSync(DM),
factory = moduleWithComponentFactories.componentFactories[0],
layerWraper = null;
if(!parent){
layerWraper = this.appRef.bootstrap(factory);
document.body.appendChild(layerWraper.location.nativeElement);
} else {
const injector = ReflectiveInjector.fromResolvedProviders([], config.parent.injector);
layerWraper = config.parent.createComponent(factory, null, injector, []);
layerWraper.instance.thizRef = layerWraper;
document.body.appendChild(layerWraper.location.nativeElement);
}
return layerWraper.instance.layerRef;
}
default_(config:LayerConfig):LayerConfig {
let dfs:LayerConfig = {
title:"",
align:"center",
closeAble:true,
cancelText:"cancel",
okText:"ok",
outSelector:"fadeOutDown",
inSelector:"dropDown",
parent:null,
dialogComponent:null,
isModal:false,
tipDuration:2500,
message:""
};
let keys = Object.keys(dfs), key:string;
for(let i in keys){
key = keys[i];
if(config[key]==undefined){
config[key] = dfs[key];
}
}
return config;
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
TypeScript
1
https://gitee.com/lovemayun/angular2-layer.git
[email protected]:lovemayun/angular2-layer.git
lovemayun
angular2-layer
angular2-layer
master

搜索帮助