Improve element gallery header (#6239)
* Improve header of Element Gallery. * Add click to copy url to screenshot header and each screenshot row.
This commit is contained in:
parent
496595f20d
commit
e951d188fb
2 changed files with 160 additions and 16 deletions
|
|
@ -60,11 +60,14 @@ br {
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
|
|
@ -72,7 +75,13 @@ input {
|
||||||
}
|
}
|
||||||
|
|
||||||
#width_input {
|
#width_input {
|
||||||
width: 80px;
|
width: 60px;
|
||||||
|
height: 32px;
|
||||||
|
background: #21262e;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #30363d;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#screenshots_container {
|
#screenshots_container {
|
||||||
|
|
@ -98,6 +107,7 @@ input {
|
||||||
background: #101318;
|
background: #101318;
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
z-index: 100;
|
||||||
}
|
}
|
||||||
#header {
|
#header {
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
@ -114,6 +124,7 @@ input {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fullstop--green {
|
.fullstop--green {
|
||||||
|
|
@ -162,3 +173,81 @@ a {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.multiselect {
|
||||||
|
width: 200px;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectBox {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectBox select {
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
background: #21262e;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #30363d;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overSelect {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#checkboxes {
|
||||||
|
display: none;
|
||||||
|
border: 1px solid #30363d;
|
||||||
|
background-color: #161b22;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 600px;
|
||||||
|
overflow-y: auto;
|
||||||
|
box-shadow: 0 8px 16px rgba(0,0,0,0.5);
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#checkboxes label {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 8px 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#checkboxes label:hover {
|
||||||
|
background-color: #0DBD8B;
|
||||||
|
}
|
||||||
|
|
||||||
|
#checkboxes input {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lines {
|
||||||
|
margin-left: 16px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-message {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 60px;
|
||||||
|
right: 20px;
|
||||||
|
background-color: #0DBD8B;
|
||||||
|
color: white;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border: 1px solid #30363d;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 16px;
|
||||||
|
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ const dataLanguages = screenshots[0];
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
|
||||||
// Get the wanted languages from the url params, or default to "de" and "fr", and ensure "en" is always there
|
// Get the wanted languages from the url params, or default to "de" and "fr", and ensure "en" is always there
|
||||||
const wantedLanguages = (urlParams.get(URL_PARAM_LANGUAGES) ? urlParams.get(URL_PARAM_LANGUAGES).split(',') : ['de', 'fr']) + ["en"];
|
const wantedLanguages = [...new Set((urlParams.get(URL_PARAM_LANGUAGES) ? urlParams.get(URL_PARAM_LANGUAGES).split(',') : ['de', 'fr']).concat('en'))];
|
||||||
// Map dataLanguages to visibleLanguages, set to 1 if the language is in wantedLanguages, 0 otherwise
|
// Map dataLanguages to visibleLanguages, set to 1 if the language is in wantedLanguages, 0 otherwise
|
||||||
let visibleLanguages = dataLanguages.map((language) => wantedLanguages.includes(language) ? 1 : 0);
|
let visibleLanguages = dataLanguages.map((language) => wantedLanguages.includes(language) ? 1 : 0);
|
||||||
// Read width from the url params, and ensure it's a multiple of 25 and is between 75 and 500
|
// Read width from the url params, and ensure it's a multiple of 25 and is between 75 and 500
|
||||||
|
|
@ -45,7 +45,7 @@ if (width) {
|
||||||
imageWidth = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, Math.round(width / WIDTH_STEP) * WIDTH_STEP));
|
imageWidth = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, Math.round(width / WIDTH_STEP) * WIDTH_STEP));
|
||||||
}
|
}
|
||||||
// Read showAllScreenshots from the url params
|
// Read showAllScreenshots from the url params
|
||||||
let showAllScreenshots = urlParams.get(URL_PARAM_ALL_SCREENSHOTS) === 1;
|
let showAllScreenshots = urlParams.get(URL_PARAM_ALL_SCREENSHOTS) === "1";
|
||||||
// Read the minimum date of modification from the url params
|
// Read the minimum date of modification from the url params
|
||||||
let minModifiedDayTime = urlParams.get(URL_PARAM_IF_MODIFIED_AFTER);
|
let minModifiedDayTime = urlParams.get(URL_PARAM_IF_MODIFIED_AFTER);
|
||||||
|
|
||||||
|
|
@ -81,17 +81,40 @@ function updatePageUrl() {
|
||||||
function addForm() {
|
function addForm() {
|
||||||
// Insert the form into the div with id form_container
|
// Insert the form into the div with id form_container
|
||||||
const form = document.createElement('form');
|
const form = document.createElement('form');
|
||||||
const languageLabel = document.createElement('label');
|
|
||||||
languageLabel.textContent = 'Languages:';
|
const multiSelectDiv = document.createElement('div');
|
||||||
form.appendChild(languageLabel);
|
multiSelectDiv.className = 'multiselect';
|
||||||
// Add a check box per entry in the dataLanguages
|
form.appendChild(multiSelectDiv);
|
||||||
|
|
||||||
|
const selectBoxDiv = document.createElement('div');
|
||||||
|
selectBoxDiv.className = 'selectBox';
|
||||||
|
selectBoxDiv.onclick = () => {
|
||||||
|
const checkboxes = document.getElementById("checkboxes");
|
||||||
|
checkboxes.style.display = checkboxes.style.display === "block" ? "none" : "block";
|
||||||
|
};
|
||||||
|
multiSelectDiv.appendChild(selectBoxDiv);
|
||||||
|
|
||||||
|
const select = document.createElement('select');
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.textContent = "Select languages";
|
||||||
|
select.appendChild(option);
|
||||||
|
selectBoxDiv.appendChild(select);
|
||||||
|
|
||||||
|
const overSelectDiv = document.createElement('div');
|
||||||
|
overSelectDiv.className = 'overSelect';
|
||||||
|
selectBoxDiv.appendChild(overSelectDiv);
|
||||||
|
|
||||||
|
const checkboxesDiv = document.createElement('div');
|
||||||
|
checkboxesDiv.id = 'checkboxes';
|
||||||
|
multiSelectDiv.appendChild(checkboxesDiv);
|
||||||
|
|
||||||
for (let i = 0; i < dataLanguages.length; i++){
|
for (let i = 0; i < dataLanguages.length; i++){
|
||||||
const label = document.createElement('label');
|
const label = document.createElement('label');
|
||||||
const text = document.createTextNode(dataLanguages[i]);
|
|
||||||
const input = document.createElement('input');
|
const input = document.createElement('input');
|
||||||
input.type = 'checkbox';
|
input.type = 'checkbox';
|
||||||
input.disabled = i == 0;
|
const language = dataLanguages[i];
|
||||||
input.name = dataLanguages[i];
|
input.disabled = language === "en";
|
||||||
|
input.name = language;
|
||||||
input.checked = visibleLanguages[i] == 1;
|
input.checked = visibleLanguages[i] == 1;
|
||||||
input.onchange = (e) => {
|
input.onchange = (e) => {
|
||||||
if (e.target.checked) {
|
if (e.target.checked) {
|
||||||
|
|
@ -103,14 +126,12 @@ function addForm() {
|
||||||
addTable();
|
addTable();
|
||||||
};
|
};
|
||||||
label.appendChild(input);
|
label.appendChild(input);
|
||||||
label.appendChild(text);
|
label.appendChild(document.createTextNode(` ${language}`));
|
||||||
form.appendChild(label);
|
checkboxesDiv.appendChild(label);
|
||||||
}
|
}
|
||||||
// Add a break line
|
|
||||||
form.appendChild(document.createElement('br'));
|
|
||||||
// Add a label with the text "Width"
|
// Add a label with the text "Width"
|
||||||
const label = document.createElement('label');
|
const label = document.createElement('label');
|
||||||
label.textContent = 'Screenshots width:';
|
label.textContent = 'Width:';
|
||||||
form.appendChild(label);
|
form.appendChild(label);
|
||||||
// Add a input text to input the width of the image
|
// Add a input text to input the width of the image
|
||||||
const widthInput = document.createElement('input');
|
const widthInput = document.createElement('input');
|
||||||
|
|
@ -128,7 +149,7 @@ function addForm() {
|
||||||
form.appendChild(widthInput);
|
form.appendChild(widthInput);
|
||||||
// Add a label with the text "Show all screenshots"
|
// Add a label with the text "Show all screenshots"
|
||||||
const label2 = document.createElement('label');
|
const label2 = document.createElement('label');
|
||||||
label2.textContent = 'Show all screenshots:';
|
label2.textContent = 'Show all:';
|
||||||
label2.title = 'Show all screenshots, including those with no translated versions.';
|
label2.title = 'Show all screenshots, including those with no translated versions.';
|
||||||
const input2 = document.createElement('input');
|
const input2 = document.createElement('input');
|
||||||
input2.type = 'checkbox';
|
input2.type = 'checkbox';
|
||||||
|
|
@ -211,6 +232,34 @@ function createImageElement(fullFile, modifiedDayTime) {
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateUrlAndScrollTo(id) {
|
||||||
|
// If the current URL already contains the fragment id, remove it, otherwise add it
|
||||||
|
if (window.location.hash === id) {
|
||||||
|
history.replaceState(null, '', window.location.pathname + window.location.search);
|
||||||
|
} else {
|
||||||
|
history.replaceState(null, '', `${window.location.pathname}${window.location.search}#${id}`);
|
||||||
|
}
|
||||||
|
const element = document.getElementById(id);
|
||||||
|
if (element) {
|
||||||
|
element.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
// Also copy the URL to the clipboard
|
||||||
|
navigator.clipboard.writeText(window.location.href);
|
||||||
|
// And show a message that the URL has been copied to the clipboard
|
||||||
|
// First check if there is already a message, if so, remove it, or the shadow will accumulate.
|
||||||
|
const existingMessage = document.querySelector('.copy-message');
|
||||||
|
if (existingMessage) {
|
||||||
|
document.body.removeChild(existingMessage);
|
||||||
|
}
|
||||||
|
const message = document.createElement('div');
|
||||||
|
message.className = 'copy-message';
|
||||||
|
message.textContent = 'URL copied to clipboard!';
|
||||||
|
document.body.appendChild(message);
|
||||||
|
setTimeout(() => {
|
||||||
|
document.body.removeChild(message);
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
function addTable() {
|
function addTable() {
|
||||||
var linesCounter = 0;
|
var linesCounter = 0;
|
||||||
// Remove any previous table
|
// Remove any previous table
|
||||||
|
|
@ -244,6 +293,9 @@ function addTable() {
|
||||||
}
|
}
|
||||||
const tr = document.createElement('tr');
|
const tr = document.createElement('tr');
|
||||||
tr.id = niceName + screenshotCounter;
|
tr.id = niceName + screenshotCounter;
|
||||||
|
tr.onclick = () => {
|
||||||
|
updateUrlAndScrollTo(tr.id);
|
||||||
|
}
|
||||||
let hasTranslatedFiles = false;
|
let hasTranslatedFiles = false;
|
||||||
for (let languageIndex = 0; languageIndex < dataLanguages.length; languageIndex++) {
|
for (let languageIndex = 0; languageIndex < dataLanguages.length; languageIndex++) {
|
||||||
if (visibleLanguages[languageIndex] == 0) {
|
if (visibleLanguages[languageIndex] == 0) {
|
||||||
|
|
@ -284,6 +336,9 @@ function addTable() {
|
||||||
currentHeaderValue = niceName;
|
currentHeaderValue = niceName;
|
||||||
const trHead = document.createElement('tr');
|
const trHead = document.createElement('tr');
|
||||||
trHead.id = niceName;
|
trHead.id = niceName;
|
||||||
|
trHead.onclick = () => {
|
||||||
|
updateUrlAndScrollTo(trHead.id);
|
||||||
|
}
|
||||||
const tdHead = document.createElement('td');
|
const tdHead = document.createElement('td');
|
||||||
tdHead.colSpan = numVisibleLanguages;
|
tdHead.colSpan = numVisibleLanguages;
|
||||||
tdHead.className = "view-header";
|
tdHead.className = "view-header";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue