globular-mvc
Version:
Generic template to create web-application that made use of globular as backend and materialize as css (wrap in web-component's)
460 lines (366 loc) • 13.8 kB
JavaScript
import { ApplicationView } from "../ApplicationView"
import { fireResize } from "./utility"
var mininizeableBar = null
/**
* That function is use to manage windows on the desktop.
*
* @param {*} onMinimize The function must contain the title and the thumbnail of the window.
*/
export function setMinimizeable(header, element, id, name, icon, onMinimize, onMaximize) {
if (mininizeableBar == null) {
mininizeableBar = new MininizeableBar()
}
// append it to the workspace.
ApplicationView.layout.workspace().appendChild(mininizeableBar)
// first of all I will find the close button
let buttons = header.querySelectorAll("paper-icon-button")
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].icon) {
if (buttons[i].icon == "icons:close") {
// append minimizeable element to the bar...
let group = mininizeableBar.insertMinimizable(element, id, name, icon)
// Set the minimize listener...
element.onMinimize = ()=>{
group.showContent()
setTimeout(()=>{
group.hideContent()
}, 3500)
}
let maximizeBtn = document.createElement("paper-icon-button")
maximizeBtn.style.position = "absolute"
maximizeBtn.style.top = "0px"
maximizeBtn.style.right = "0px"
maximizeBtn.style.display = "none"
maximizeBtn.style.setProperty("--iron-icon-fill-color", "var(--palette-text-accent)")
maximizeBtn.setAttribute("icon", "icons:add")
let closeBtn = buttons[i];
closeBtn.insertAdjacentHTML('afterend', `<paper-icon-button id="minimize-btn" icon="icons:remove" style="min-width: 40px; --iron-icon-fill-color: var(--palette-text-accent);"></paper-icon-button>`)
closeBtn.addEventListener("click", (evt) => {
mininizeableBar.removeMinimizable(id, name)
})
// Here will add the maximize button...
maximizeBtn.addEventListener("click", (evt) => {
evt.stopPropagation()
if (element.isMinimized) {
maximizeBtn.style.display = "none"
group.maximize(id)
// set back the close button to it original place.
closeBtn.style.position = ""
closeBtn.style.top = ""
closeBtn.style.left = ""
header.insertBefore(closeBtn, header.firstChild)
if (group.children.length == 0) {
group.parentNode.style.display = "none"
} else if (group.children.length == 1) {
if (group.children[0].children.length == 0) {
group.parentNode.style.display = "none"
}
}
closeBtn.style.background = ""
maximizeBtn.style.background = ""
minimizeBtn.style.background = ""
closeBtn.style.fill = ""
maximizeBtn.style.fill = ""
minimizeBtn.style.fill = ""
if(onMaximize){
onMaximize()
}
}
})
// The onclick event...
let minimizeBtn = header.querySelector("#minimize-btn")
minimizeBtn.onclick = () => {
maximizeBtn.style.display = "block"
group.parentNode.style.display = ""
mininizeableBar.minimize(id, name)
// set the close btn
closeBtn.style.position = "absolute"
closeBtn.style.top = "0px"
closeBtn.style.left = "0px"
element.appendChild(closeBtn)
closeBtn.style.background = "rgba(0, 0, 0, .5)"
maximizeBtn.style.background = "rgba(0, 0, 0, .5)"
minimizeBtn.style.background = "rgba(0, 0, 0, .5)"
closeBtn.style.fill = "white"
maximizeBtn.style.fill = "white"
minimizeBtn.style.fill = "white"
if(onMinimize){
onMinimize()
}
}
element.style.position = "relative"
element.appendChild(maximizeBtn)
break
}
}
}
}
/**
* Help to managed windows on a descktop.
*/
export class MininizeableBar extends HTMLElement {
// attributes.
// Create the applicaiton view.
constructor() {
super()
// Set the shadow dom.
this.attachShadow({ mode: 'open' });
// Keep track of minimized elements.
this.minimizeables = {}
// Innitialisation of the layout.
this.shadowRoot.innerHTML = `
<style>
#container{
display: flex;
z-index: 10;
}
::slotted(globular-minimizeable-group){
margin-left: 6px;
margin-top: 6px;
}
::slotted(globular-minimizeable-group:hover){
cursor: pointer;
}
</style>
<div id="container">
<slot></slot>
</div>
`
// give the focus to the input.
window.addEventListener('resize', () => {
// set the postion to 0, 0
let w = ApplicationView.layout.width();
let container = this.shadowRoot.querySelector("#container")
if (w < 500) {
container.style.flexDirection = "column"
for (var i = 0; i < this.children.length; i++) {
this.children[i].setVertical()
}
} else {
container.style.flexDirection = "row"
for (var i = 0; i < this.children.length; i++) {
this.children[i].setHorizontal()
}
}
})
}
connectedCallback() {
fireResize()
}
/**
* Add minizable window in the bar.
* @param {*} element
* @param {*} onMinimize
* @param {*} onMaximize
* @param {*} onClose
* @param {*} onPreview
*/
insertMinimizable(element, id, name, icon) {
let minimizeables = this.querySelector("#" + name)
if (!minimizeables) {
// Here I will create the minimizables group...
minimizeables = new MinimizeableGroup(name, icon)
minimizeables.id = name
this.appendChild(minimizeables)
fireResize() // set the group direction...
}
minimizeables.insertMinimizable(element, id, name, icon)
return minimizeables
}
removeMinimizable(id, name) {
let minimizeables = this.querySelector("#" + name)
minimizeables.removeMinimizable(id, name)
if (this.children.length == 0) {
this.parentNode.removeChild(this)
}
}
minimize(id, name) {
// Hide the div...
let minimizeables = this.querySelector("#" + name)
minimizeables.minimize(id)
}
}
customElements.define('globular-mininizeable-bar', MininizeableBar)
/**
* Minimizable elements group
*/
export class MinimizeableGroup extends HTMLElement {
// attributes.
// Create the applicaiton view.
constructor(name, icon) {
super()
// Set the shadow dom.
this.attachShadow({ mode: 'open' });
this.id = name
// Innitialisation of the layout.
this.shadowRoot.innerHTML = `
<style>
#container{
background-color: var(--palette-primary-accent);
color: var(--palette-text-primary);
box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px;
border-radius: 3px;
display: none;
}
.big{
--iron-icon-height: 24px;
--iron-icon-width: 24px;
}
.active{
border-bottom: 1px solid rgb(12, 72, 98);
}
#content{
display: flex;
position: absolute;
}
</style>
<div id="container">
<div style="position: relative;">
<iron-icon style="padding: 5px;" class="big" icon="${icon}"></iron-icon>
<paper-ripple style="border-radius: 3px;" recenters></paper-ripple>
<div id="content">
<slot><slot>
</div>
</div>
</div>
`
// give the focus to the input.
let container = this.shadowRoot.querySelector("#container")
container.onclick = () => {
let isVisible = this.isContentVisible()
let groups = document.getElementsByTagName("globular-minimizeable-group")
for (var i = 0; i < groups.length; i++) {
groups[i].resetActive()
groups[i].hideContent()
}
if (!isVisible) {
this.showContent()
this.setActive();
} else {
this.hideContent()
}
}
}
isVisible() {
let container = this.shadowRoot.querySelector("#container")
return container.style.display != "none"
}
isContentVisible() {
let content = this.shadowRoot.querySelector("#content")
return content.style.display != "none"
}
hide() {
let container = this.shadowRoot.querySelector("#container")
container.style.display = "none"
}
show() {
let container = this.shadowRoot.querySelector("#container")
container.style.display = "block"
}
hideContent() {
let content = this.shadowRoot.querySelector("#content")
content.style.display = "none"
}
showContent() {
let content = this.shadowRoot.querySelector("#content")
content.style.display = "block"
}
setActive() {
let container = this.shadowRoot.querySelector("#container")
container.classList.add("active")
}
resetActive() {
let container = this.shadowRoot.querySelector("#container")
container.classList.remove("active")
}
// insert the minimizable element.
insertMinimizable(element, id, onMinimize, onMaximize, onClose, onPreview) {
if (!this.querySelector("#" + id)) {
let minimizable = new MinimizeableElement(element, id, onMinimize, onMaximize, onClose, onPreview)
minimizable.id = id
this.appendChild(minimizable)
}
}
removeMinimizable(id) {
let minimizeable = this.querySelector("#" + id)
if (minimizeable) {
minimizeable.parentNode.removeChild(minimizeable)
}
// no more item to display...
if (this.children.length == 0) {
this.parentNode.removeChild(this)
}
}
minimize(id) {
let minimizeableElement = this.querySelector("#" + id)
minimizeableElement.style.display = "";
minimizeableElement.minimize()
let groups = document.getElementsByTagName("globular-minimizeable-group")
for (var i = 0; i < groups.length; i++) {
if (this.id != groups[i].id)
groups[i].hideContent()
groups[i].resetActive()
}
this.resetActive()
this.show()
this.showContent()
setTimeout(() => {
this.hideContent()
}, 3500)
}
maximize(id) {
let minimizeableElement = this.querySelector("#" + id)
minimizeableElement.style.display = "none";
minimizeableElement.maximize()
}
setVertical() {
let content = this.shadowRoot.querySelector("#content")
content.style.flexDirection = "column"
content.style.bottom = ""
content.style.left = "40px"
content.style.top = "0px"
}
setHorizontal() {
let content = this.shadowRoot.querySelector("#content")
content.style.flexDirection = "row"
content.style.bottom = "40px"
content.style.left = "0px"
content.style.top = ""
}
}
customElements.define('globular-minimizeable-group', MinimizeableGroup)
/**
* Minimizable element
*/
export class MinimizeableElement extends HTMLElement {
// attributes.
// Create the applicaiton view.
constructor(element, id) {
super()
// Set the shadow dom.
this.attachShadow({ mode: 'open' });
this.element = element;
this.id = id
// Innitialisation of the layout.
this.shadowRoot.innerHTML = `
<style>
#container{
}
</style>
<div id="container">
<slot><slot>
</div>
`
// give the focus to the input.
let container = this.shadowRoot.querySelector("#container")
}
minimize() {
this.element.minimize()
this.appendChild(this.element)
}
maximize(){
this.element.maximize()
this.element.style.display = ""
}
}
customElements.define('globular-minimizeable-element', MinimizeableElement)