UNPKG

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)

391 lines (325 loc) 12.4 kB
// I will made use of polymer instead of materialyze for the main // layout because materialyse dosen't react to well with the shadow doom. import '@polymer/iron-icon/iron-icon.js'; import '@polymer/iron-icons/social-icons' import '@polymer/iron-icons/iron-icons.js'; import '@polymer/paper-ripple/paper-ripple.js'; import '@polymer/paper-input/paper-input.js'; import '@polymer/paper-card/paper-card.js'; import '@polymer/paper-button/paper-button.js'; import '@polymer/paper-checkbox/paper-checkbox.js'; import '@polymer/paper-tooltip/paper-tooltip.js'; import { Model } from '../Model'; import { ApplicationView } from '../ApplicationView'; /** * Login/Register functionality. */ export class Menu extends HTMLElement { // attributes. // Create the view. constructor(id, icon, text) { super() this.id = id; this.icon = icon; this.keepOpen = false; this.hideMenuDiv = false; // Set the shadow dom. this.attachShadow({ mode: 'open' }); // Innitialisation of the layout. this.shadowRoot.innerHTML = ` <style> .sidemenu-btn{ padding: 8px; margin:0px; width: 100%; transition: background 0.2s ease,padding 0.8s linear; background: var(--palette-background-default); border-radius: 4px; } .sidemenu-btn:hover{ -webkit-filter: invert(10%); filter: invert(10%); } #${this.id}_div { display: flex; position: relative; background: transparent; } .menu-btn{ margin-right: 10px; display: flex; } .btn_{ display: flex; justify-content: center; align-items: center; position: relative; } .btn_:hover{ cursor: pointer; } .left{ right: 47px; top: 0px; } .bottom{ right: -16px; top: 54px; } #overflow_menu_div{ background-color: var(--palette-background-default); } #${this.id}_menu_div{ display: flex; flex-direction: column; color: var(--palette-text-accent); position: absolute; background-color: var(--palette-background-paper); } #${this.id}_img{ width: 32px; height: 32px; border-radius: 16px; border: 1px solid transparent; display: none; } #${this.id}_img:hover{ cursor: pointer; } #${this.id}_icon{ display: none; } .big { --iron-icon-height: 24px; --iron-icon-width: 24px; } .label{ display: none; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-family: "Roboto","Arial",sans-serif; font-size: 1.2rem; line-height: 2rem; font-weight: 400; flex: 1; flex-basis: 1e-9px; margin-left: 24px; } element.style { } paper-card{ background-color: var(--palette-background-paper); color: var(--palette-text-primary); } paper-card h1 { font-size: 1.65rem; } </style> <div id="${this.id}_div" class="menu-btn"> <div id="${this.id}_picture_div" class="btn_"> <iron-icon id="${this.id}_icon" icon="${this.icon}"></iron-icon> <img id="${this.id}_img"></img> <span class="label" id="${this.id}_label">${text}</span> <paper-ripple class="circle" recenters></paper-ripple> </div> <paper-tooltip id="${this.id}_tooltip" for="${this.id}_picture_div" style="font-size: 10pt;">${text}</paper-tooltip> <paper-card id="${this.id}_menu_div" class="menu-div bottom"> <slot name="${this.id}"></slot> </paper-card> </div> ` // this is execute each time the element is connect in the dom. this.parentNode_ = this.parentNode // Get the menu div this.menu = this.shadowRoot.getElementById(this.id + "_menu_div") // Remove it from the layout... this.menu.parentNode.removeChild(this.menu) // Can be use to change the onclick default handler. this.onclick = null; // Move the menu in it parent if the window resize. window.addEventListener("resize", (evt) => { if (!ApplicationView) { return; } if (this.hideMenuDiv) { return; } let w = ApplicationView.layout.width(); // TODO try to set it in the css propertie instead... if (this.menu) { if (this.menu.parentNode) { if (w < 700) { Model.eventHub.publish("_display_workspace_content_event_", this.menu, true) } else { let menuDiv = this.shadowRoot.getElementById(this.id + "_div") menuDiv.appendChild(this.menu) } } } }) } // The connection callback. connectedCallback() { let img = this.shadowRoot.getElementById(this.id + "_img") let ico = this.shadowRoot.getElementById(this.id + "_icon") if (img.src.length == 0) { ico.style.display = "block"; } let menuPictureDiv = this.shadowRoot.getElementById(this.id + "_picture_div") // Remove the menu if the the mouse is not over the button or the menu. let handler = (evt) => { var menu = this.shadowRoot.getElementById(this.id + "_menu_div") if (menu != null) { var rectMenu = menu.getBoundingClientRect(); var overMenu = evt.x > rectMenu.x && evt.x < rectMenu.right && evt.y > rectMenu.y && evt.y < rectMenu.bottom var btn = this.shadowRoot.getElementById(this.id + "_picture_div") var rectBtn = btn.getBoundingClientRect(); var overBtn = evt.x > rectBtn.x && evt.x < rectBtn.right && evt.y > rectBtn.y && evt.y < rectBtn.bottom if (!overBtn && !overMenu && !this.keepOpen) { document.removeEventListener("click", handler) let icon = this.getIconDiv().querySelector("iron-icon") if (img.src.length == 0) { icon.style.removeProperty("--iron-icon-fill-color") } menu.parentNode.removeChild(menu) } } }; // The menu logic... menuPictureDiv.onclick = (evt) => { // hide the icon div if image is not undefined. let img = this.shadowRoot.getElementById(this.id + "_img") let ico = this.shadowRoot.getElementById(this.id + "_icon") let icon = this.getIconDiv().querySelector("iron-icon") if (img.src.length == 0) { ico.style.display = "block"; } // test if the menu is set. let menu = this.shadowRoot.getElementById(this.id + "_menu_div"); // simply remove it if it already exist. if (menu != undefined) { var rectMenu = menu.getBoundingClientRect(); var overMenu = evt.x > rectMenu.x && evt.x < rectMenu.right && evt.y > rectMenu.y && evt.y < rectMenu.bottom if (!overMenu) { document.removeEventListener("click", handler) menu.parentNode.removeChild(menu) if (img.src.length == 0) { icon.style.removeProperty("--iron-icon-fill-color") } } return; } if (!this.hideMenuDiv) { let w = ApplicationView.layout.width(); if (w < 700) { Model.eventHub.publish("_display_workspace_content_event_", this.menu, true) } else { let menuDiv = this.shadowRoot.getElementById(this.id + "_div") menuDiv.appendChild(this.menu) } } if (this.onshow) { this.onshow() } // set the handler. document.addEventListener("click", handler); ApplicationView.layout.appDrawer.close() } } /** * Return the body of the menu. */ getMenuDiv() { return this.menu } /** * Return the icon div. */ getIconDiv() { return this.shadowRoot.getElementById(this.id + "_picture_div") } getLabel() { return this.shadowRoot.getElementById(this.id + "_label") } /** * Return the image div. */ getImage() { return this.shadowRoot.getElementById(this.id + "_img") } /** * Return the image div. */ getIcon() { return this.shadowRoot.getElementById(this.id + "_icon") } /** * Hide the menu. */ hide() { if (this.parentNode != undefined) { this.parentNode_ = this.parentNode } if (this.parentNode_ != undefined) { if (this.parentNode_.contains(this)) { this.parentNode_.removeChild(this) } } } /** * Show the menu. */ show() { if (this.parentNode_ != undefined) { this.parentNode_.appendChild(this) } } /** * Display the label beside the menu */ expand() { if (!this.getMenuDiv()) { return } this.getMenuDiv().classList.remove("left"); this.getMenuDiv().classList.add("bottom"); this.getIcon().classList.remove("big") this.getLabel().style.display = "none" this.getIconDiv().classList.remove("sidemenu-btn") this.shadowRoot.querySelector("paper-tooltip").style.display = "block" this.shadowRoot.querySelector("paper-ripple").classList.add("circle") } /** * not display the label. */ shrink() { if (!this.getMenuDiv()) { return } this.getIconDiv().classList.add("sidemenu-btn") this.getMenuDiv().classList.remove("bottom"); this.getMenuDiv().classList.add("left"); this.getIcon().classList.add("big") this.getLabel().style.display = "block" this.shadowRoot.querySelector("paper-tooltip").style.display = "none" this.shadowRoot.querySelector("paper-ripple").classList.remove("circle") } // Set account information. init() { /** Nothing to do here... */ // On logout I must reset the icon and the image. Model.eventHub.subscribe("logout_event_", (uuid) => { }, () => { let ico = this.shadowRoot.getElementById(this.id + "_icon") let img = this.shadowRoot.getElementById(this.id + "_img") if (img != undefined) { img.src = ""; img.style.display = "none"; ico.style.display = "block"; } }, true, this) } }