mirror of https://github.com/ColorlibHQ/AdminLTE
added: card-widget
parent
675eba15ef
commit
c1ced676ee
|
@ -5,7 +5,7 @@
|
||||||
<head>
|
<head>
|
||||||
@@include('./_head.html', {
|
@@include('./_head.html', {
|
||||||
"path": "..",
|
"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">
|
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
||||||
</head>
|
</head>
|
||||||
|
@ -400,6 +400,93 @@
|
||||||
<!-- ./col -->
|
<!-- ./col -->
|
||||||
</div>
|
</div>
|
||||||
<!-- /.row -->
|
<!-- /.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><!-- /.container-fluid -->
|
||||||
</div>
|
</div>
|
||||||
<!-- /.content -->
|
<!-- /.content -->
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-card-widgett="collapse"] {
|
[data-card-widget="collapse"] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import SidebarHover from './sidebar-hover'
|
||||||
import SidebarOverlay from './sidebar-overlay'
|
import SidebarOverlay from './sidebar-overlay'
|
||||||
import Treeview from './treeview'
|
import Treeview from './treeview'
|
||||||
import DirectChat from './direct-chat'
|
import DirectChat from './direct-chat'
|
||||||
|
import CardWidget from './card-widget'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Layout,
|
Layout,
|
||||||
|
@ -11,7 +12,8 @@ export {
|
||||||
SidebarHover,
|
SidebarHover,
|
||||||
SidebarOverlay,
|
SidebarOverlay,
|
||||||
Treeview,
|
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 {
|
export {
|
||||||
domReady,
|
domReady,
|
||||||
windowReady
|
windowReady,
|
||||||
|
slideUp,
|
||||||
|
slideDown,
|
||||||
|
slideToggle
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue