-
-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathdropdown.ts
More file actions
126 lines (111 loc) · 3.74 KB
/
dropdown.ts
File metadata and controls
126 lines (111 loc) · 3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import {
AfterViewInit, Component, ElementRef, HostListener, OnDestroy, Renderer2,
ViewChild,
} from '@angular/core'
import { SafeStyle, DomSanitizer } from '@angular/platform-browser'
import { Value } from './dropdown.item'
import { ElDropdownProps } from './dropdown.props'
import { dropAnimation } from './animation'
import { DocumentWrapper } from '../shared/services'
@Component({
selector: 'el-dropdown',
template: `
<ng-template #content>
<ng-content></ng-content>
</ng-template>
<div class="el-dropdown">
<ng-container *ngIf="splitButton">
<el-button [type]="type" [size]="size" (click)="openMenu($event)">
<span>
<ng-template [ngTemplateOutlet]="content"></ng-template>
<i class="el-icon-caret-bottom el-icon--right"></i>
</span>
</el-button>
</ng-container>
<ng-container *ngIf="!splitButton">
<span class="el-dropdown-link" (click)="openMenu($event)" style="cursor: pointer;">
<ng-template [ngTemplateOutlet]="content"></ng-template>
<i class="el-icon-caret-bottom el-icon--right"></i>
</span>
</ng-container>
<div [style]="makeListStyles()">
<ul class="el-dropdown-menu" #list [@dropAnimation]="showMenu">
<el-dropdown-item *ngFor="let item of model" [model]="item" (selected)="selectHandle()">
</el-dropdown-item>
</ul>
</div>
</div>
`,
animations: [dropAnimation],
styles: ['.el-dropdown-menu { overflow: hidden; }'],
})
export class ElDropdown extends ElDropdownProps implements OnDestroy, AfterViewInit {
@ViewChild('list') list: any
showMenu: boolean = false
timer: any
slideToBottom: boolean = true
listHeight: number
globalListenFunc: Function
globalScrollFunc: Function
@HostListener('mouseleave') mouseleave = () => {
if (this.trigger !== 'hover') return
this.timer = setTimeout(() => {
this.closeMenu()
clearTimeout(this.timer)
}, 400)
}
@HostListener('mouseenter') mouseenter = () => {
if (this.trigger !== 'hover') return
this.timer && clearTimeout(this.timer)
!this.showMenu && this.visibleChange.emit()
this.showMenu = true
}
constructor(
private renderer: Renderer2,
private sanitizer: DomSanitizer,
private document: DocumentWrapper,
private el: ElementRef,
) {
super()
}
openMenu(event?: Event): void {
event && event.stopPropagation()
this.showMenu = !this.showMenu
this.visibleChange.emit()
this.globalListenFunc = this.renderer.listen(
'document',
'click',
() => this.closeMenu()
)
}
closeMenu(): void {
this.showMenu = false
this.visibleChange.emit()
this.globalListenFunc && this.globalListenFunc()
}
selectHandle(model: Value): void {
this.selected.emit(model)
// select and hide menu (props)
this.hideOnClick && this.closeMenu()
}
makeListStyles(): SafeStyle {
const styles = `top: ${this.slideToBottom ? '100%' : (0 - this.listHeight) + 'px' };` +
`${this.menuAlign === 'end' ? 'right' : 'left'}: 0; position: absolute; min-width: 100px;`
return this.sanitizer.bypassSecurityTrustStyle(styles)
}
ngAfterViewInit(): void {
this.listHeight = this.list.nativeElement.offsetHeight + 12
this.globalScrollFunc = this.renderer.listen(
'window', 'scroll', () => {
const top = this.el.nativeElement.getBoundingClientRect().top
const nextValue = this.document.documentElement.clientHeight - top > this.listHeight
if (nextValue !== this.slideToBottom) {
this.slideToBottom = nextValue
}
})
}
ngOnDestroy(): void {
this.globalListenFunc && this.globalListenFunc()
this.globalScrollFunc && this.globalScrollFunc()
}
}