Newer
Older
<!DOCTYPE html>
<template id="myuw-profile-template">
#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) );
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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) );
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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);
}
</style>
<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 id="myuw-profile-logout" href="#">Logout</a>
</div>
</div>
</template>
<script>
class MyUWProfile extends HTMLElement {
constructor() {
super();
// Get the script document
MyUWProfile.document = (document._currentScript || document.currentScript).ownerDocument;
this['open-right'] = false;
// Create a shadowroot for this element
this.attachShadow({mode: 'open'});
// Get the template and extract the HTML content
const template = MyUWProfile.document.getElementById('myuw-profile-template');
// Append the custom HTML to the shadowroot
this.shadowRoot.appendChild(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');
this['user'] = false;
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(){
if(this.user){
// 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();
this.showLoginButton();
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
/*
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');
}
}
window.customElements.define('myuw-profile', MyUWProfile);
</script>