Skip to content

Commit

Permalink
Merge pull request #520 from oduwsdl/reconstructive
Browse files Browse the repository at this point in the history
Reposition banner and persist position and datetime display preferences
  • Loading branch information
machawk1 authored Aug 19, 2018
2 parents 1d51f3d + 5feac17 commit 29784bf
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 32 deletions.
103 changes: 72 additions & 31 deletions ipwb/reconstructive-banner.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
* It is an unobtrusive archival replay banner to make [mementos](http://mementoweb.org/about/) interactive and surface on-demand metadata about the archived resource.
* The banner houses a customizable branding logo that links to the replay home.
* It provides a pre-populated text input to navigate the replay to a different URI-R.
* A brief phrase describes the age of the current memento.
* A brief phrase describes the rough age of the current memento, but can be toggled with the absolute date and time of capture by repeatedly clicking on it.
* User's preference on absolute or relative datetime display persists across the session.
* Navigational links to the first, last, previous, and next mementos are also provided when present.
* In its default floating action bar (FAB) mode it auto-hides after a set duration of inactivity if the banner is not in focus and reappears on any user activity on the page such as scroll, mousemove, or keypress.
* The FAB can be dragged to repostion it on the page, which then persists across the session unless relocated again.
* It provides controls to expand, collapse, or completely close the banner.
* The expanded mode has much more real estate available to house detailed archival metadata and visualizations.
* Use it in an HTML page as illustrated below:
Expand Down Expand Up @@ -66,8 +68,6 @@ class ReconstructiveBanner extends HTMLElement {

this.nextDatetime = this.getAttribute('next-datetime') || '';

this.focused = false;

this.autoHideDelay = 2000;

this.displayDatetime = (() => {
Expand Down Expand Up @@ -118,9 +118,8 @@ class ReconstructiveBanner extends HTMLElement {
}
#wrapper.fab {
position: fixed;
bottom: 10px;
right: 10px;
transition: all 0.5s ease-in;
top: calc(100vh - 100px);
left: 20px;
}
#wrapper.expanded {
position: fixed;
Expand All @@ -130,7 +129,6 @@ class ReconstructiveBanner extends HTMLElement {
width: 100%;
height: 100%;
background: rgba(100, 100, 100, 0.6);
transition: all 0.5s ease-out;
}
#wrapper.hidden {
opacity: 0;
Expand All @@ -149,17 +147,15 @@ class ReconstructiveBanner extends HTMLElement {
padding: 5px;
box-shadow: 0 0 20px;
display: grid;
grid-template-columns: fit-content(300px) 20px 20px 1fr 20px 20px 20px;
grid-template-columns: 10px fit-content(300px) 20px 20px 1fr 20px 20px 20px;
grid-template-rows: 20px 20px 1fr;
grid-gap: 2px 10px;
box-sizing: border-box;
min-height: 50px;
transition: all 0.5s ease-in;
}
.expanded #container {
height: calc(100vh - 20px);
box-shadow: none;
transition: all 0.5s ease-out;
}
.fab #collapse, .fab #meta, .expanded #expand {
display: none;
Expand All @@ -178,24 +174,34 @@ class ReconstructiveBanner extends HTMLElement {
.icon {
width: 20px;
}
#logo {
#drag {
grid-column: 1;
grid-row: 1 / 3;
border: #1B4869 3px dotted;
cursor: move;
}
.expanded #drag {
opacity: 0.4;
cursor: default;
}
#logo {
grid-column: 2;
grid-row: 1 / 3;
}
#urir {
grid-column: 2 / 7;
grid-column: 3 / 8;
grid-row: 1;
}
#first {
grid-column: 2;
grid-column: 3;
grid-row: 2;
}
#prev {
grid-column: 3;
grid-column: 4;
grid-row: 2;
}
#current {
grid-column: 4;
grid-column: 5;
grid-row: 2;
margin: 0 5px;
font-size: 16px;
Expand All @@ -218,27 +224,27 @@ class ReconstructiveBanner extends HTMLElement {
display: initial;
}
#next {
grid-column: 5;
grid-column: 6;
grid-row: 2;
}
#last {
grid-column: 6;
grid-column: 7;
grid-row: 2;
}
#close {
grid-column: 7;
grid-column: 8;
grid-row: 1;
}
#expand {
grid-column: 7;
grid-column: 8;
grid-row: 2;
}
#collapse {
grid-column: 7;
grid-column: 8;
grid-row: 2;
}
#meta {
grid-column: 1 / 8;
grid-column: 1 / 9;
grid-row: 3;
overflow: auto;
padding: 10px;
Expand All @@ -247,8 +253,9 @@ class ReconstructiveBanner extends HTMLElement {
grid-template-rows: auto auto auto 130px 1fr;
}
</style>
<div id="wrapper" class="fab">
<div id="wrapper" class="fab" style="${localStorage.getItem('bannerPosition') || ''}">
<div id="container">
<div id="drag"></div>
<a id="home" title="Go to home" href="${this.homeHref}" rel="noreferrer">
<img id="logo" class="branding" src="${this.logoSrc}" alt="Reconstructive Banner Logo">
</a>
Expand All @@ -261,7 +268,7 @@ class ReconstructiveBanner extends HTMLElement {
<a id="prev" class="icon" title="${this.prevDatetime}" href="${this.prevUrim}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M8 28v-24h4v11l10-10v22l-10-10v11z"></path></svg>
</a>
<p id="current" class="datetime" title="${this.mementoDatetime}">
<p id="current" class="datetime ${localStorage.getItem('datetimeDisplay') || ''}" title="${this.mementoDatetime}">
<span class="relative">${this.displayDatetime.relative}</span>
<span class="absolute">${this.displayDatetime.absolute}</span>
</p>
Expand Down Expand Up @@ -291,13 +298,14 @@ class ReconstructiveBanner extends HTMLElement {
const container = this.shadow.getElementById('container');
const wrapper = this.shadow.getElementById('wrapper');

container.onmouseover = () => this.focused = true;
container.onmouseout = () => this.focused = false;
let bannerFocused = false;
container.onmouseover = () => bannerFocused = true;
container.onmouseout = () => bannerFocused = false;
let focusTimer;
const resetTimer = () => {
wrapper.classList.remove('hidden');
clearTimeout(focusTimer);
focusTimer = setTimeout(() => !this.focused && wrapper.classList.contains('fab') && wrapper.classList.add('hidden'), this.autoHideDelay);
focusTimer = setTimeout(() => !bannerFocused && wrapper.classList.contains('fab') && wrapper.classList.add('hidden'), this.autoHideDelay);
};
window.addEventListener('load', resetTimer);
window.addEventListener('mousemove', resetTimer);
Expand All @@ -311,25 +319,58 @@ class ReconstructiveBanner extends HTMLElement {
wrapper.classList.remove('fab', 'expanded');
wrapper.classList.add('closed');
};
this.shadow.getElementById('collapse').onclick = e => {
e.preventDefault();
wrapper.classList.replace('expanded', 'fab');
};
this.shadow.getElementById('expand').onclick = e => {
e.preventDefault();
wrapper.classList.replace('fab', 'expanded');
wrapper.style.removeProperty('top');
wrapper.style.removeProperty('left');
};
this.shadow.getElementById('collapse').onclick = e => {
e.preventDefault();
wrapper.classList.replace('expanded', 'fab');
wrapper.style.cssText = localStorage.getItem('bannerPosition') || '';
};
wrapper.onclick = e => {
if (e.target == wrapper) {
wrapper.classList.replace('expanded', 'fab');
wrapper.style.cssText = localStorage.getItem('bannerPosition') || '';
}
};

const datetimeDisplay = this.shadow.getElementById('current');
datetimeDisplay.onclick = e => {
datetimeDisplay.classList.toggle('precision');
if (datetimeDisplay.classList.toggle('precision')) {
localStorage.setItem('datetimeDisplay', 'precision');
} else {
localStorage.removeItem('datetimeDisplay');
}
};

let draggable = false;
let offset = { x: 0, y: 0 };
this.shadow.getElementById('drag').onmousedown = e => {
if (wrapper.classList.contains('fab')) {
draggable = true;
offset = {
x: wrapper.offsetLeft - e.clientX,
y: wrapper.offsetTop - e.clientY
};
}
};
window.addEventListener('mouseup', e => {
if (draggable && wrapper.classList.contains('fab')) {
draggable = false;
localStorage.setItem('bannerPosition', `left: ${wrapper.offsetLeft}px; top: ${wrapper.offsetTop}px;`);
}
});
window.addEventListener('mousemove', e => {
e.preventDefault();
if (draggable && wrapper.classList.contains('fab')) {
wrapper.style.left = Math.max(Math.min(e.clientX + offset.x, window.innerWidth - 45), 10) + 'px';
wrapper.style.top = Math.max(Math.min(e.clientY + offset.y, window.innerHeight - 85), 10) + 'px';
}
});

this.shadow.getElementById('lookup').onsubmit = e => {
e.preventDefault();
const urir = this.shadow.getElementById('urir').value;
Expand Down
2 changes: 1 addition & 1 deletion ipwb/reconstructive.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Reconstructive {
constructor(config) {
this.NAME = 'Reconstructive';

this.VERSION = '0.6.3';
this.VERSION = '0.7.0';

this.id = `${this.NAME}:${this.VERSION}`;

Expand Down

0 comments on commit 29784bf

Please sign in to comment.