Skip to content
Snippets Groups Projects
myuw-profile.html 10.4 KiB
Newer Older
<!DOCTYPE html>
<template id="myuw-profile-template">
Scott Berg's avatar
Scott Berg committed
    :host([hidden]) {
        display: none;
    }

    #myuw-profile-login {
        font-family: var( --myuw-profile-font, var(--myuw-font, 'Montserrat', 'Roboto', Arial, sans-serif) );
        text-transform: uppercase;
        text-decoration: none;
        color: var( --myuw-profile-login-color, var(--myuw-primary-color, white) );
        padding: 10px 13px;
        font-weight: bold;
        letter-spacing: 0px;
        font-size: 14px;
        position: relative;
        display: inline-block;
    }

    #myuw-profile-login.hidden {
        display: none;
    }

    #myuw-profile-circle {
        position: relative;
        display: inline-block;
        width: 40px;
        height: 40px;
        border-radius: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        cursor: pointer;
    }

    #myuw-profile-circle-initial {
        padding: 0;
        margin: 0;
        font-weight: 500;
        font-size: 18px;
        font-family: var( --myuw-profile-font, var(--myuw-font, 'Montserrat', 'Roboto', Arial, sans-serif) );
        user-select: none;
        color: white;
        text-transform: capitalize;
    }

    #myuw-profile-wrapper {
        position: relative;
        display: inline-block;
    }

    #myuw-profile-wrapper.hidden {
        display: none;
    }

    #myuw-profile-nav {
        position: absolute;
        top: 45px;
        right: 0;
        min-width: 320px;
        color: black;
        list-style: none;
        margin: 0;
        padding: 0;
        font-size: 14px;

        transform-origin: top right;
        transform: scale(0);
        opacity: 0;
        transition: opacity .25s cubic-bezier(0.0, 0.0, 0.2, 1), transform .25s cubic-bezier(0.0, 0.0, 0.2, 1);

        -webkit-box-shadow: 0px 0px 7px 0px rgba(50, 50, 50, 0.75);
        -moz-box-shadow:    0px 0px 7px 0px rgba(50, 50, 50, 0.75);
        box-shadow:         0px 0px 7px 0px rgba(50, 50, 50, 0.75);
    }

    #myuw-profile-nav.open-right {
        left: 0;
        right: inherit;
        transform-origin: top left;
    }

    #myuw-profile-nav.visible {
        transform: scale(1);
        opacity: 1;
    }

    #myuw-profile-nav p {
        padding: 0;
        margin: 0;
    }

    #myuw-profile-nav a,
    #myuw-profile-nav p,
    ::slotted(a),
    ::slotted(p){
        transition: all .3s ease;
        position: relative;
        font-size: 15px;
        font-family: var( --myuw-profile-font, var(--myuw-font, 'Montserrat', 'Roboto', Arial, sans-serif) );
        display: block;
        padding: 14px 16px;
        color: black;
        text-decoration: none;
        background-color: #f9f9f9;
        border-bottom: solid 1px #e5e5e5;
        user-select: none;
    }

    #myuw-profile-nav a:first-child,
    #myuw-profile-nav p:first-child {
        padding: 14px 16px;
        font-weight: bold;
        background-color: white;
    }

    #myuw-profile-nav a:first-child:hover,
    #myuw-profile-nav p:first-child:hover {
        background-color: white;
    }

    #myuw-profile-nav a:hover,
    #myuw-profile-nav p:hover,
    ::slotted(a:hover),
    ::slotted(p:hover)  {
        background-color: rgba(158,158,158,0.2);
    <a href="#" id="myuw-profile-login" class="hidden">Login</a>
    <div id="myuw-profile-wrapper" class="hidden">
            <div id="myuw-profile-circle">
                <p id="myuw-profile-circle-initial">B</p>
            </div>

            <div id="myuw-profile-nav">
                <p id="myuw-profile-nav-user">Bucky</p>
                <slot name="nav-item"></slot>
                <a href="#">Settings</a>
                <a id="myuw-profile-logout" href="#">Logout</a>
            </div>
    </div>

</template>
<script>
class MyUWProfile extends HTMLElement {
    constructor() {
        super();

        // Create a shadowroot for this element
        this.attachShadow({mode: 'open'});

        // Append the custom HTML to the shadowroot
        this.shadowRoot.appendChild(MyUWProfile.template.content.cloneNode(true));
    static get observedAttributes() {return ['login-url', 'logout-url', 'open-right']; }

    attributeChangedCallback(name, oldValue, newValue){
        // Update the attribute internally
        this[name] = newValue;

        // Update the component with new att value
        this.updateAttribute(name);
    }

    connectedCallback(){
        // Get all attributes
        this['login-url']           = this.getAttribute('login-url');
        this['logout-url']          = this.getAttribute('logout-url');
        this['session-endpoint']    = this.getAttribute('session-endpoint');
        if(this.getAttribute('open-right') !== null){
            this['open-right'] = true;
        }
        // If the session endpoint is set, fetch session info
        if(this['session-endpoint']){
            fetch(this['session-endpoint'])
            .then(res => {

                // Check if the request was valid
                if(res.status === 200){
                    res.json()
                    .then( data => {
                        // If data.person is not set, return.
                        if(!data.person){ return; }

                        // Set user data to the component
                        this.user = data.person;
                        this.componentReady();
                    })
                } else {
                    this.componentReady();
                }
            })
            .catch( e => {
                console.log(e);
                // Show login button if we couldn't get session info
                this.componentReady();
            } );
            throw Error('No session endpoint has been defiend. Please set the "session-endpoint" attribute URL into the myuw-profile element!');
        /*
            Add an on click event to the window.
            This allows us to close the menu if the user
            clicks anywhere but on the menu.
        */
        window.addEventListener('click', e => {
            let nav = this.shadowRoot.getElementById('myuw-profile-nav');

            if(nav.classList.contains('visible')){
                nav.classList.remove('visible')
            }
        /*
            Add an on click event to the profile nav menu.
            We need to do this in order to stop the propagation
            of click events on the menu specifically.

            If a user clicks on the nav menu, the window on click
            event will not fire, and it will not close the nav menu
        */
        this.shadowRoot.getElementById('myuw-profile-nav').addEventListener('click', e => {
            e.stopPropagation();
        });

        /*
            Add an on click event to profile bubble
            We need to make sure that we stop propagation on
            this event or else the window on click will always fire
            and the menu will never open.
        */
        this.shadowRoot.getElementById('myuw-profile-circle').addEventListener('click', e => {
            e.stopPropagation();
            this.shadowRoot.getElementById('myuw-profile-nav').classList.toggle('visible');
        });

        // Update the component to use the new attributes
        this.updateAttribute('login-url');
        this.updateAttribute('logout-url');
        this.updateAttribute('session-endpoint');
        this.updateAttribute('open-right');
    // Update the component with attribute values
    updateAttribute(att){
        switch(att){
            case 'login-url':
                this.shadowRoot.getElementById('myuw-profile-login').setAttribute('href', this['login-url']);
                break;
            case 'logout-url':
                this.shadowRoot.getElementById('myuw-profile-logout').setAttribute('href', this['logout-url']);
                break;
            case 'open-right':
                if(this['open-right']){
                    this.shadowRoot.getElementById('myuw-profile-nav').classList.add('open-right');
                }
                break;
        }
    }

    /*
        Function to run after the session endpoint
        has been hit and the component has all the
        data that it needs to render.
        If user data was returned from the endpoint,
        the profile bubble will show.

        If not, the login button will show.
    */
    componentReady() {
            // Add user's name to first menu item
            this.shadowRoot.getElementById('myuw-profile-nav-user').innerHTML = this.user.firstName;
            // Change the letter in the profile circle
            this.shadowRoot.getElementById('myuw-profile-circle-initial').innerHTML = this.user.firstName.substring(0,1);

            this.setProfileColor();

            this.showProfileBubble();
            if (this['login-url'] !== null) {
                this.showLoginButton();
            } else {
                this.hidden = true;
            }

    /*
        Programmatically select a profile background
        color based on the length of the users first name
        and the first letter of their first name
    */
    setProfileColor() {
        const colors = [
            '#093145',
            '#107896',
            '#829356',
            '#00A996',
            '#BCA136',
            '#744196'
        ];

        const firstName = this.user.firstName.length;
        const initial = this.user.firstName.substring(0,1).charCodeAt();
        const colorIndex = (initial + firstName) % colors.length;

        this.shadowRoot.getElementById('myuw-profile-circle').style.backgroundColor = colors[colorIndex];

    }

    showLoginButton() {
        // Show Login Button
        this.shadowRoot.getElementById('myuw-profile-login').classList.remove('hidden');
        // Hide profile Circle
        this.shadowRoot.getElementById('myuw-profile-wrapper').classList.add('hidden');
    }

    showProfileBubble() {
        // Hide login button
        this.shadowRoot.getElementById('myuw-profile-login').classList.add('hidden');
        // Show Profile circle
        this.shadowRoot.getElementById('myuw-profile-wrapper').classList.remove('hidden');
    }

MyUWProfile.template = (document._currentScript || document.currentScript).ownerDocument.getElementById('myuw-profile-template');
window.customElements.define('myuw-profile', MyUWProfile);
</script>