mirror of https://github.com/ColorlibHQ/AdminLTE
added: card-widget
parent
675eba15ef
commit
c1ced676ee
|
@ -5,7 +5,7 @@
|
|||
<head>
|
||||
@@include('./_head.html', {
|
||||
"path": "..",
|
||||
"title": "AdminLTE 4 | General Form Elements"
|
||||
"title": "AdminLTE 4 | Widgets"
|
||||
})
|
||||
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
||||
</head>
|
||||
|
@ -400,6 +400,93 @@
|
|||
<!-- ./col -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<h4 class="mb-2 mt-4">Cards</h4>
|
||||
<h5 class="mb-2">Abilities</h5>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="card card-primary collapsed-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Expandable</h3>
|
||||
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- /.card-tools -->
|
||||
</div>
|
||||
<!-- /.card-header -->
|
||||
<div class="card-body">
|
||||
The body of the card
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-md-3">
|
||||
<div class="card card-success">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Collapsable</h3>
|
||||
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- /.card-tools -->
|
||||
</div>
|
||||
<!-- /.card-header -->
|
||||
<div class="card-body">
|
||||
The body of the card
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-md-3">
|
||||
<div class="card card-warning">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Removable</h3>
|
||||
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="remove"><i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- /.card-tools -->
|
||||
</div>
|
||||
<!-- /.card-header -->
|
||||
<div class="card-body">
|
||||
The body of the card
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-md-3">
|
||||
<div class="card card-danger">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Maximizable</h3>
|
||||
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="maximize"><i class="fas fa-expand"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- /.card-tools -->
|
||||
</div>
|
||||
<!-- /.card-header -->
|
||||
<div class="card-body">
|
||||
The body of the card
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</div>
|
||||
<!-- /.content -->
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
overflow: auto;
|
||||
}
|
||||
|
||||
[data-card-widgett="collapse"] {
|
||||
[data-card-widget="collapse"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import SidebarHover from './sidebar-hover'
|
|||
import SidebarOverlay from './sidebar-overlay'
|
||||
import Treeview from './treeview'
|
||||
import DirectChat from './direct-chat'
|
||||
import CardWidget from './card-widget'
|
||||
|
||||
export {
|
||||
Layout,
|
||||
|
@ -11,7 +12,8 @@ export {
|
|||
SidebarHover,
|
||||
SidebarOverlay,
|
||||
Treeview,
|
||||
DirectChat
|
||||
DirectChat,
|
||||
CardWidget
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
/**
|
||||
* --------------------------------------------
|
||||
* AdminLTE card-widget.js
|
||||
* License MIT
|
||||
* --------------------------------------------
|
||||
*/
|
||||
|
||||
import {
|
||||
domReady,
|
||||
slideUp,
|
||||
slideDown
|
||||
} from './util/index'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
const CLASS_NAME_CARD = 'card'
|
||||
const CLASS_NAME_COLLAPSED = 'collapsed-card'
|
||||
const CLASS_NAME_COLLAPSING = 'collapsing-card'
|
||||
const CLASS_NAME_EXPANDING = 'expanding-card'
|
||||
const CLASS_NAME_WAS_COLLAPSED = 'was-collapsed'
|
||||
const CLASS_NAME_MAXIMIZED = 'maximized-card'
|
||||
|
||||
const SELECTOR_DATA_REMOVE = '[data-card-widget="remove"]'
|
||||
const SELECTOR_DATA_COLLAPSE = '[data-card-widget="collapse"]'
|
||||
const SELECTOR_DATA_MAXIMIZE = '[data-card-widget="maximize"]'
|
||||
const SELECTOR_CARD = `.${CLASS_NAME_CARD}`
|
||||
const SELECTOR_CARD_HEADER = '.card-header'
|
||||
const SELECTOR_CARD_BODY = '.card-body'
|
||||
const SELECTOR_CARD_FOOTER = '.card-footer'
|
||||
|
||||
const Default = {
|
||||
animationSpeed: 500,
|
||||
collapseTrigger: SELECTOR_DATA_COLLAPSE,
|
||||
removeTrigger: SELECTOR_DATA_REMOVE,
|
||||
maximizeTrigger: SELECTOR_DATA_MAXIMIZE,
|
||||
collapseIcon: 'fa-minus',
|
||||
expandIcon: 'fa-plus',
|
||||
maximizeIcon: 'fa-expand',
|
||||
minimizeIcon: 'fa-compress'
|
||||
}
|
||||
|
||||
interface Settings {
|
||||
animationSpeed: number;
|
||||
collapseTrigger: string;
|
||||
removeTrigger: string;
|
||||
maximizeTrigger: string;
|
||||
collapseIcon: string;
|
||||
expandIcon: string;
|
||||
maximizeIcon: string;
|
||||
minimizeIcon: string;
|
||||
}
|
||||
|
||||
class CardWidget {
|
||||
_element: HTMLElement
|
||||
_parent: HTMLElement | null
|
||||
_settings: Settings
|
||||
constructor(element: HTMLElement, settings: Settings) {
|
||||
this._element = element
|
||||
this._parent = element.closest(SELECTOR_CARD)
|
||||
|
||||
if (element.classList.contains(CLASS_NAME_CARD)) {
|
||||
this._parent = element
|
||||
}
|
||||
|
||||
this._settings = Object.assign({}, Default, settings)
|
||||
}
|
||||
|
||||
collapse() {
|
||||
this._parent?.classList.add(CLASS_NAME_COLLAPSING)
|
||||
|
||||
const elm = this._parent?.querySelectorAll(`${SELECTOR_CARD_BODY}, ${SELECTOR_CARD_FOOTER}`)
|
||||
|
||||
if (elm !== undefined) {
|
||||
for (const el of elm) {
|
||||
if (el instanceof HTMLElement) {
|
||||
slideUp(el, this._settings.animationSpeed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this._parent?.classList.add(CLASS_NAME_COLLAPSED)
|
||||
this._parent?.classList.remove(CLASS_NAME_COLLAPSING)
|
||||
}, this._settings.animationSpeed)
|
||||
|
||||
const icon = this._parent?.querySelector(`${SELECTOR_CARD_HEADER} ${this._settings.collapseTrigger} .${this._settings.collapseIcon}`)
|
||||
|
||||
icon?.classList.add(this._settings.expandIcon)
|
||||
icon?.classList.remove(this._settings.collapseIcon)
|
||||
}
|
||||
|
||||
expand() {
|
||||
this._parent?.classList.add(CLASS_NAME_EXPANDING)
|
||||
|
||||
const elm = this._parent?.querySelectorAll(`${SELECTOR_CARD_BODY}, ${SELECTOR_CARD_FOOTER}`)
|
||||
|
||||
if (elm !== undefined) {
|
||||
for (const el of elm) {
|
||||
if (el instanceof HTMLElement) {
|
||||
slideDown(el, this._settings.animationSpeed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this._parent?.classList.remove(CLASS_NAME_COLLAPSED)
|
||||
this._parent?.classList.remove(CLASS_NAME_EXPANDING)
|
||||
}, this._settings.animationSpeed)
|
||||
|
||||
const icon = this._parent?.querySelector(`${SELECTOR_CARD_HEADER} ${this._settings.collapseTrigger} .${this._settings.expandIcon}`)
|
||||
|
||||
icon?.classList.add(this._settings.collapseIcon)
|
||||
icon?.classList.remove(this._settings.expandIcon)
|
||||
}
|
||||
|
||||
remove() {
|
||||
if (this._parent) {
|
||||
slideUp(this._parent, this._settings.animationSpeed)
|
||||
}
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if (this._parent?.classList.contains(CLASS_NAME_COLLAPSED)) {
|
||||
this.expand()
|
||||
return
|
||||
}
|
||||
|
||||
this.collapse()
|
||||
}
|
||||
|
||||
maximize() {
|
||||
if (this._parent) {
|
||||
const maxElm = this._parent.querySelector(`${this._settings.maximizeTrigger} .${this._settings.maximizeIcon}`)
|
||||
maxElm?.classList.add(this._settings.minimizeIcon)
|
||||
maxElm?.classList.remove(this._settings.maximizeIcon)
|
||||
|
||||
this._parent.style.height = `${this._parent.scrollHeight}px`
|
||||
this._parent.style.width = `${this._parent.scrollWidth}px`
|
||||
this._parent.style.transition = 'all .15s'
|
||||
|
||||
setTimeout(() => {
|
||||
document.querySelector('html')?.classList.add(CLASS_NAME_MAXIMIZED)
|
||||
this._parent?.classList.add(CLASS_NAME_MAXIMIZED)
|
||||
if (this._parent?.classList.contains(CLASS_NAME_COLLAPSED)) {
|
||||
this._parent.classList.add(CLASS_NAME_WAS_COLLAPSED)
|
||||
}
|
||||
}, 150)
|
||||
}
|
||||
}
|
||||
|
||||
minimize() {
|
||||
if (this._parent) {
|
||||
const minElm = this._parent.querySelector(`${this._settings.maximizeTrigger} .${this._settings.minimizeIcon}`)
|
||||
|
||||
minElm?.classList.add(this._settings.maximizeIcon)
|
||||
minElm?.classList.remove(this._settings.minimizeIcon)
|
||||
|
||||
this._parent.style.cssText = `height: ${this._parent.style.height} !important; width: ${this._parent.style.width} !important; transition: all .15s;`
|
||||
// console.log('🚀 ~ file: card-widget.ts ~ line 164 ~ CardWidget ~ minimize ~ this._parent.style.height', this._parent.style.height)
|
||||
|
||||
setTimeout(() => {
|
||||
document.querySelector('html')?.classList.remove(CLASS_NAME_MAXIMIZED)
|
||||
if (this._parent) {
|
||||
this._parent.classList.remove(CLASS_NAME_MAXIMIZED)
|
||||
|
||||
if (this._parent?.classList.contains(CLASS_NAME_WAS_COLLAPSED)) {
|
||||
this._parent.classList.remove(CLASS_NAME_WAS_COLLAPSED)
|
||||
}
|
||||
}
|
||||
}, 10)
|
||||
}
|
||||
}
|
||||
|
||||
toggleMaximize() {
|
||||
if (this._parent?.classList.contains(CLASS_NAME_MAXIMIZED)) {
|
||||
this.minimize()
|
||||
return
|
||||
}
|
||||
|
||||
this.maximize()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Data Api implementation
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
domReady(() => {
|
||||
const collapseBtn = document.querySelectorAll(SELECTOR_DATA_COLLAPSE)
|
||||
|
||||
for (const btn of collapseBtn) {
|
||||
btn.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
const target = event.target as HTMLElement
|
||||
const data = new CardWidget(target, Default)
|
||||
data.toggle()
|
||||
})
|
||||
}
|
||||
|
||||
const removeBtn = document.querySelectorAll(SELECTOR_DATA_REMOVE)
|
||||
|
||||
for (const btn of removeBtn) {
|
||||
btn.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
const target = event.target as HTMLElement
|
||||
const data = new CardWidget(target, Default)
|
||||
data.remove()
|
||||
})
|
||||
}
|
||||
|
||||
const maxBtn = document.querySelectorAll(SELECTOR_DATA_MAXIMIZE)
|
||||
|
||||
for (const btn of maxBtn) {
|
||||
btn.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
const target = event.target as HTMLElement
|
||||
const data = new CardWidget(target, Default)
|
||||
data.toggleMaximize()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export default CardWidget
|
|
@ -14,7 +14,85 @@ const windowReady = (callBack: () => void): void => {
|
|||
}
|
||||
}
|
||||
|
||||
/* SLIDE UP */
|
||||
const slideUp = (target: HTMLElement, duration = 500) => {
|
||||
target.style.transitionProperty = 'height, margin, padding'
|
||||
target.style.transitionDuration = `${duration}ms`
|
||||
target.style.boxSizing = 'border-box'
|
||||
target.style.height = `${target.offsetHeight}px`
|
||||
target.style.overflow = 'hidden'
|
||||
|
||||
window.setTimeout(() => {
|
||||
target.style.height = '0'
|
||||
target.style.paddingTop = '0'
|
||||
target.style.paddingBottom = '0'
|
||||
target.style.marginTop = '0'
|
||||
target.style.marginBottom = '0'
|
||||
}, 1)
|
||||
|
||||
window.setTimeout(() => {
|
||||
target.style.display = 'none'
|
||||
target.style.removeProperty('height')
|
||||
target.style.removeProperty('padding-top')
|
||||
target.style.removeProperty('padding-bottom')
|
||||
target.style.removeProperty('margin-top')
|
||||
target.style.removeProperty('margin-bottom')
|
||||
target.style.removeProperty('overflow')
|
||||
target.style.removeProperty('transition-duration')
|
||||
target.style.removeProperty('transition-property')
|
||||
}, duration)
|
||||
}
|
||||
|
||||
/* SLIDE DOWN */
|
||||
const slideDown = (target: HTMLElement, duration = 500) => {
|
||||
target.style.removeProperty('display')
|
||||
let {display} = window.getComputedStyle(target)
|
||||
if (display === 'none') {
|
||||
display = 'block'
|
||||
}
|
||||
|
||||
target.style.display = display
|
||||
const height = target.offsetHeight
|
||||
target.style.overflow = 'hidden'
|
||||
target.style.height = '0'
|
||||
target.style.paddingTop = '0'
|
||||
target.style.paddingBottom = '0'
|
||||
target.style.marginTop = '0'
|
||||
target.style.marginBottom = '0'
|
||||
|
||||
window.setTimeout(() => {
|
||||
target.style.boxSizing = 'border-box'
|
||||
target.style.transitionProperty = 'height, margin, padding'
|
||||
target.style.transitionDuration = `${duration}ms`
|
||||
target.style.height = `${height}px`
|
||||
target.style.removeProperty('padding-top')
|
||||
target.style.removeProperty('padding-bottom')
|
||||
target.style.removeProperty('margin-top')
|
||||
target.style.removeProperty('margin-bottom')
|
||||
}, 1)
|
||||
|
||||
window.setTimeout(() => {
|
||||
target.style.removeProperty('height')
|
||||
target.style.removeProperty('overflow')
|
||||
target.style.removeProperty('transition-duration')
|
||||
target.style.removeProperty('transition-property')
|
||||
}, duration)
|
||||
}
|
||||
|
||||
/* TOOGLE */
|
||||
const slideToggle = (target: HTMLElement, duration = 500) => {
|
||||
if (window.getComputedStyle(target).display === 'none') {
|
||||
slideDown(target, duration)
|
||||
return
|
||||
}
|
||||
|
||||
slideUp(target, duration)
|
||||
}
|
||||
|
||||
export {
|
||||
domReady,
|
||||
windowReady
|
||||
windowReady,
|
||||
slideUp,
|
||||
slideDown,
|
||||
slideToggle
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue