added: card-widget

pull/3891/head
Daniel 2021-06-02 08:51:06 +05:30
parent 675eba15ef
commit c1ced676ee
5 changed files with 399 additions and 4 deletions

View File

@ -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 -->

View File

@ -44,7 +44,7 @@
overflow: auto;
}
[data-card-widgett="collapse"] {
[data-card-widget="collapse"] {
display: none;
}

View File

@ -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
}
//

228
src/ts/card-widget.ts Normal file
View File

@ -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

View File

@ -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
}