simplify inline search DOM structure
This commit is contained in:
parent
3a82a66954
commit
1d9ec09d62
|
@ -202,6 +202,10 @@
|
|||
"message": "Cannot function properly because of a known bug in this version of Firefox: chrome.extension.getBackgroundPage() doesn't return a valid result",
|
||||
"description": "Displayed in style manager when unable to connect to the background page"
|
||||
},
|
||||
"genericErrorOccurred": {
|
||||
"message": "An error occured:",
|
||||
"description": "Used in various places to indicate some error occured. The error message is shown on the next line."
|
||||
},
|
||||
"genericDisabledLabel": {
|
||||
"message": "Disabled",
|
||||
"description": "Used in various lists/options to indicate that something is disabled"
|
||||
|
@ -726,13 +730,25 @@
|
|||
"message": "Use /re/ syntax for regexp search",
|
||||
"description": "Label after the search input field in the editor shown on Ctrl-F"
|
||||
},
|
||||
"searchResultWeeklyCount": {
|
||||
"message": "Weekly installs",
|
||||
"description": "Text for label that shows the number of times a search result was installed during last week"
|
||||
},
|
||||
"searchResultInstallCount": {
|
||||
"message": "Total installs",
|
||||
"description": "Text for label that shows the number of times a search result was installed"
|
||||
},
|
||||
"searchResultNoneFound": {
|
||||
"message": "No styles found for this site.",
|
||||
"description": "Error text in the popup when inline search didn't find any site-specific styles"
|
||||
},
|
||||
"searchResultRating": {
|
||||
"message": "Rating",
|
||||
"description": "Text for label that shows the search result's rating"
|
||||
},
|
||||
"searchResultInstallCount": {
|
||||
"message": "Installs",
|
||||
"description": "Text for label that shows the number of times a search result was installed"
|
||||
"searchResultUpdated": {
|
||||
"message": "Updated",
|
||||
"description": "Text for label that shows the search result's last update date"
|
||||
},
|
||||
"searchStyles": {
|
||||
"message": "Search contents",
|
||||
|
|
63
popup.html
63
popup.html
|
@ -1,3 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<html id="stylus">
|
||||
|
||||
<head>
|
||||
|
@ -88,53 +89,49 @@
|
|||
<a class="search-result-title"><span></span></a>
|
||||
<div class="search-result-info">
|
||||
<img class="search-result-screenshot" i18n-title="installButton">
|
||||
<div class="actions">
|
||||
<button class="search-result-install" i18n-text="installButton" hidden></button>
|
||||
<div class="search-result-actions">
|
||||
<button class="search-result-install hidden" i18n-text="installButton"></button>
|
||||
<button class="search-result-uninstall hidden" i18n-text="deleteStyleLabel"></button>
|
||||
<button class="search-result-customize hidden"
|
||||
i18n-text="configureStyle"
|
||||
i18n-title="configureStyleOnHomepage"></button>
|
||||
</div>
|
||||
<div class="search-result-overlay">
|
||||
<div class="search-result-meta">
|
||||
<div class="search-result-author">
|
||||
<span i18n-text="author"></span>
|
||||
<a class="search-result-author-link" target="_blank" i18n-title="author"></a>
|
||||
</div>
|
||||
<div class="search-result-meta-rating">
|
||||
<span i18n-text="searchResultRating"></span>
|
||||
<span class="search-result-rating" i18n-title="searchResultRating"></span>
|
||||
</div>
|
||||
<div class="search-result-meta-updated">
|
||||
<span></span>
|
||||
<time class="search-result-updated"></time>
|
||||
</div>
|
||||
<div class="search-result-meta-weekly-count">
|
||||
<span i18n-text="searchResultInstallCount"></span>
|
||||
<span class="search-result-weekly-count" i18n-title="searchResultInstallCount"></span>
|
||||
</div>
|
||||
<div class="search-result-meta-install-count">
|
||||
<span i18n-text="searchResultInstallCount"></span>
|
||||
<span class="search-result-install-count" i18n-title="searchResultInstallCount"></span>
|
||||
</div>
|
||||
<dl class="search-result-meta">
|
||||
<div data-type="author">
|
||||
<dt i18n-text="author"></dt>
|
||||
<dd><a target="_blank" i18n-title="author"></a></dd>
|
||||
</div>
|
||||
<div class="search-result-description-group">
|
||||
<div class="search-result-description"></div>
|
||||
<div data-type="rating">
|
||||
<dt i18n-text="searchResultRating"></dt>
|
||||
<dd i18n-title="searchResultRating"></dd>
|
||||
</div>
|
||||
</div>
|
||||
<div data-type="updated">
|
||||
<dt i18n-text="searchResultUpdated"></dt>
|
||||
<dd i18n-title="searchResultUpdated"><time></time></dd>
|
||||
</div>
|
||||
<div data-type="weekly">
|
||||
<dt i18n-text="searchResultWeeklyCount"></dt>
|
||||
<dd i18n-title="searchResultWeeklyCount"></dd>
|
||||
</div>
|
||||
<div data-type="total">
|
||||
<dt i18n-text="searchResultInstallCount"></dt>
|
||||
<dd i18n-title="searchResultInstallCount"></dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div class="search-result-description"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template data-id="searchNav">
|
||||
<div>
|
||||
<button data-role="prev" i18n-title="paginationPrevious" disabled>◄</button>
|
||||
<button data-type="prev" i18n-title="paginationPrevious" disabled>◄</button>
|
||||
<label>
|
||||
<span data-role="page" i18n-title="paginationCurrent">-</span>
|
||||
<span data-type="page" i18n-title="paginationCurrent">-</span>
|
||||
/
|
||||
<span data-role="total" i18n-title="paginationTotal">-</span>
|
||||
<span data-type="total" i18n-title="paginationTotal">-</span>
|
||||
</label>
|
||||
<button data-role="next" i18n-title="paginationNext" disabled>►</button>
|
||||
<button data-type="next" i18n-title="paginationNext" disabled>►</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -219,10 +216,10 @@
|
|||
</div>
|
||||
|
||||
<div id="search-results" class="hidden">
|
||||
<div id="search-results-nav-top"></div>
|
||||
<div class="search-results-nav" data-type="top"></div>
|
||||
<div id="search-results-error" class="hidden"></div>
|
||||
<div id="search-results-list"></div>
|
||||
<div id="search-results-nav-bottom"></div>
|
||||
<div class="search-results-nav" data-type="bottom"></div>
|
||||
</div>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none !important;">
|
||||
|
|
|
@ -1,11 +1,24 @@
|
|||
body.search-results-shown {
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
background-color: #aaa;
|
||||
}
|
||||
|
||||
#search-results:before {
|
||||
background-image: linear-gradient(transparent, rgba(0, 0, 0, .3) 200px);
|
||||
content: "";
|
||||
top: -50px;
|
||||
left: -1000px;
|
||||
right: -1000px;
|
||||
bottom: -12px;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
animation: fadein 1s;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
#search-results {
|
||||
position: relative;
|
||||
margin-top: -1em;
|
||||
}
|
||||
|
||||
#search-results-error {
|
||||
|
@ -18,13 +31,13 @@ body.search-results-shown {
|
|||
|
||||
#search-results-list {
|
||||
position: relative;
|
||||
min-height: 200px;
|
||||
min-height: 224px;
|
||||
}
|
||||
|
||||
.search-result,
|
||||
.search-result-empty {
|
||||
position: relative;
|
||||
padding: 8px 8px 24px;
|
||||
padding: 8px 8px 21px;
|
||||
min-height: 160px;
|
||||
}
|
||||
|
||||
|
@ -66,12 +79,12 @@ body.search-results-shown {
|
|||
.search-result-title {
|
||||
margin-bottom: .5em;
|
||||
display: block;
|
||||
color: #666;
|
||||
color: #555;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.search-result-title span {
|
||||
font-size: 1.2em;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
|
@ -83,47 +96,56 @@ body.search-results-shown {
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.search-result-info > div {
|
||||
/* opacity: 0; */
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
transition: opacity .25s ease-in-out;
|
||||
}
|
||||
|
||||
.search-result:hover .actions {
|
||||
.search-result:hover .search-result-actions {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.search-result-overlay {
|
||||
bottom: -24px;
|
||||
}
|
||||
|
||||
.search-result-info > .actions {
|
||||
bottom: 15px;
|
||||
.search-result-actions {
|
||||
bottom: 20px;
|
||||
text-align: center;
|
||||
z-index: 10;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
transition: opacity .5s;
|
||||
}
|
||||
|
||||
.search-result-info > .actions > button {
|
||||
#search-results .search-result-actions button {
|
||||
background-color: #fff;
|
||||
box-shadow: 2px 2px 20px #000;
|
||||
white-space: nowrap;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
.search-result-info > .actions > button:hover {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.search-result-overlay > * {
|
||||
.search-result-meta {
|
||||
background-color: hsla(0, 0%, 93%, 0.75);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
line-height: 16px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.search-result-author {
|
||||
max-width: 20%;
|
||||
.search-result:hover .search-result-meta {
|
||||
background-color: hsla(0, 0%, 100%, 0.75);
|
||||
}
|
||||
|
||||
.search-result-author-link {
|
||||
.search-result-meta dt {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.search-result-meta dd {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.search-result-meta [data-type="author"] {
|
||||
max-width: 30%;
|
||||
}
|
||||
|
||||
.search-result-meta [data-type="author"] a {
|
||||
color: inherit;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
|
@ -132,107 +154,82 @@ body.search-results-shown {
|
|||
display: block;
|
||||
}
|
||||
|
||||
.search-result-description-group {
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
font-size: 90%;
|
||||
line-height: 24px;
|
||||
min-height: 5px;
|
||||
}
|
||||
|
||||
.search-result-description {
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.search-result-meta {
|
||||
background-color: hsla(0, 0%, 93%, 0.76);
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.search-result:hover .search-result-meta {
|
||||
background-color: hsla(0, 0%, 100%, 0.76);
|
||||
}
|
||||
|
||||
.search-result-meta > * > :first-child {
|
||||
display: none;
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
.search-result-meta-rating {
|
||||
.search-result-meta [data-type="rating"] dd {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.search-result-meta-install-count {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.search-result-rating {
|
||||
font-weight: 600;
|
||||
padding: 1px 2px 1px 2px;
|
||||
}
|
||||
|
||||
.search-result-rating.good {
|
||||
.search-result-meta [data-type="rating"][data-class="good"] dd {
|
||||
color: darkgreen;
|
||||
}
|
||||
|
||||
.search-result-rating.okay {
|
||||
color: chocolate;
|
||||
.search-result-meta [data-type="rating"][data-class="okay"] dd {
|
||||
color: darkgreen;
|
||||
}
|
||||
|
||||
.search-result-rating.bad {
|
||||
.search-result-meta [data-type="rating"][data-class="bad"] dd {
|
||||
color: darkred;
|
||||
}
|
||||
|
||||
.search-result-rating.none {
|
||||
.search-result-meta [data-type="rating"][data-class="none"] dd {
|
||||
}
|
||||
|
||||
.search-result-install-count {
|
||||
font-weight: 600;
|
||||
.search-result-meta [data-type="weekly"],
|
||||
.search-result-meta [data-type="total"] {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.search-result-install, .search-result-customize, .search-result-uninstall {
|
||||
margin: 3px;
|
||||
.search-result-meta [data-type="weekly"] dd,
|
||||
.search-result-meta [data-type="total"] dd {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#search-results-nav-top,
|
||||
#search-results-nav-bottom {
|
||||
.search-result-description {
|
||||
padding: 0;
|
||||
font-size: 90%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.search-results-nav {
|
||||
flex-direction: row;
|
||||
text-align: center;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
#search-results-nav-top {
|
||||
padding-top: 4px;
|
||||
margin-bottom: 8px;
|
||||
.search-results-nav[data-type="top"] {
|
||||
padding-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#search-results-nav-bottom {
|
||||
margin-top: -14px;
|
||||
margin-bottom: 16px;
|
||||
.search-results-nav[data-type="bottom"] {
|
||||
margin-top: -1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#search-results-nav-top button,
|
||||
#search-results-nav-bottom button {
|
||||
-webkit-appearance: none;
|
||||
#search-results .search-results-nav button {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: .25rem 1rem;
|
||||
margin: 0 .5rem;
|
||||
color: #eee;
|
||||
text-shadow: 0 1px 3px rgba(0, 0, 0, .5);
|
||||
font-size: 250%;
|
||||
font-size: 200%;
|
||||
line-height: 24px;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#search-results-nav-top button:hover,
|
||||
#search-results-nav-bottom button:hover {
|
||||
text-shadow: 0 1px 3px #000;
|
||||
#search-results .search-results-nav button:disabled {
|
||||
cursor: auto;
|
||||
opacity: .5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#search-results .search-results-nav button:not(:disabled):hover {
|
||||
text-shadow: 0 1px 4px rgba(0, 0, 0, .5);
|
||||
}
|
||||
|
||||
#find-styles-inline-group label {
|
||||
|
|
|
@ -98,13 +98,13 @@ window.addEventListener('showStyles:done', function _() {
|
|||
dom.nav = {};
|
||||
const navOnClick = {prev, next};
|
||||
for (const place of ['top', 'bottom']) {
|
||||
const nav = $('#search-results-nav-' + place);
|
||||
const nav = $(`.search-results-nav[data-type="${place}"]`);
|
||||
nav.appendChild(template.searchNav.cloneNode(true));
|
||||
dom.nav[place] = nav;
|
||||
for (const child of $$('[data-role]', nav)) {
|
||||
const role = child.dataset.role;
|
||||
child.onclick = navOnClick[role];
|
||||
nav['_' + role] = child;
|
||||
for (const child of $$('[data-type]', nav)) {
|
||||
const type = child.dataset.type;
|
||||
child.onclick = navOnClick[type];
|
||||
nav['_' + type] = child;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,14 +179,10 @@ window.addEventListener('showStyles:done', function _() {
|
|||
* @param {string} message Message to display to user.
|
||||
*/
|
||||
function error(reason) {
|
||||
let message;
|
||||
if (reason === 404) {
|
||||
// TODO: i18n message
|
||||
message = 'No results found';
|
||||
} else {
|
||||
message = 'Error loading search results: ' + reason;
|
||||
}
|
||||
dom.error.textContent = message;
|
||||
dom.error.textContent =
|
||||
reason === 404 ?
|
||||
t('searchResultNoneFound') :
|
||||
t('genericErrorOccurred') + '\n' + reason;
|
||||
dom.error.classList.remove('hidden');
|
||||
}
|
||||
|
||||
|
@ -320,13 +316,17 @@ window.addEventListener('showStyles:done', function _() {
|
|||
showSpinner(entry);
|
||||
}
|
||||
plantAt++;
|
||||
if (!processedResults.length) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (dom.list.children.length > maxResults) {
|
||||
dom.list.lastElementChild.remove();
|
||||
}
|
||||
|
||||
if (scrollToFirstResult && dom.list.children[0]) {
|
||||
if (scrollToFirstResult &&
|
||||
dom.container.getBoundingClientRect().bottom > window.innerHeight * 2) {
|
||||
scrollToFirstResult = false;
|
||||
if (!FIREFOX || FIREFOX >= 55) {
|
||||
setTimeout(() => {
|
||||
|
@ -386,22 +386,19 @@ window.addEventListener('showStyles:done', function _() {
|
|||
}
|
||||
|
||||
const description = result.description
|
||||
.replace(/<[^>]*>/g, '')
|
||||
.replace(/([^.]\.)(\s)/g, '$1\n$2')
|
||||
.replace(/[\r\n]{3,}/g, '\n\n');
|
||||
.replace(/<[^>]*>/g, ' ')
|
||||
.replace(/([^.][.。?!]|[\s,].{50,70})\s+/g, '$1\n')
|
||||
.replace(/([\r\n]\s*){3,}/g, '\n\n');
|
||||
Object.assign($('.search-result-description', entry), {
|
||||
textContent: description,
|
||||
title: description,
|
||||
});
|
||||
|
||||
Object.assign($('.search-result-author-link', entry), {
|
||||
Object.assign($('[data-type="author"] a', entry), {
|
||||
textContent: result.user.name,
|
||||
title: result.user.name,
|
||||
href: BASE_URL + '/users/' + result.user.id,
|
||||
onclick(event) {
|
||||
event.stopPropagation();
|
||||
handleEvent.openURLandHide.call(this, event);
|
||||
}
|
||||
onclick: handleEvent.openURLandHide,
|
||||
});
|
||||
|
||||
let ratingClass;
|
||||
|
@ -419,11 +416,10 @@ window.addEventListener('showStyles:done', function _() {
|
|||
ratingClass = 'bad';
|
||||
ratingValue = ratingValue.toFixed(1);
|
||||
}
|
||||
Object.assign($('.search-result-rating', entry), {
|
||||
textContent: ratingValue,
|
||||
className: 'search-result-rating ' + ratingClass
|
||||
});
|
||||
Object.assign($('.search-result-meta-updated', entry), {
|
||||
$('[data-type="rating"]', entry).dataset.class = ratingClass;
|
||||
$('[data-type="rating"] dd', entry).textContent = ratingValue;
|
||||
|
||||
Object.assign($('[data-type="updated"] time', entry), {
|
||||
dateTime: result.updated,
|
||||
textContent: tryCatch(lang => {
|
||||
const date = new Date(result.updated);
|
||||
|
@ -434,17 +430,26 @@ window.addEventListener('showStyles:done', function _() {
|
|||
});
|
||||
}, [UI_LANG, 'en']) || '',
|
||||
});
|
||||
Object.assign($('.search-result-weekly-count', entry), {
|
||||
textContent: result.weekly_install_count.toLocaleString()
|
||||
});
|
||||
Object.assign($('.search-result-install-count', entry), {
|
||||
textContent: result.total_install_count.toLocaleString()
|
||||
});
|
||||
|
||||
|
||||
$('[data-type="weekly"] dd', entry).textContent = formatNumber(result.weekly_install_count);
|
||||
$('[data-type="total"] dd', entry).textContent = formatNumber(result.total_install_count);
|
||||
|
||||
renderActionButtons(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
function formatNumber(num) {
|
||||
return (
|
||||
num > 1e9 ? (num / 1e9).toFixed(1) + 'B' :
|
||||
num > 10e6 ? (num / 1e6).toFixed(0) + 'M' :
|
||||
num > 1e6 ? (num / 1e6).toFixed(1) + 'M' :
|
||||
num > 10e3 ? (num / 1e3).toFixed(0) + 'k' :
|
||||
num > 1e3 ? (num / 1e3).toFixed(1) + 'k' :
|
||||
num
|
||||
);
|
||||
}
|
||||
|
||||
function renderActionButtons(entry) {
|
||||
const screenshot = $('.search-result-screenshot', entry);
|
||||
screenshot.onclick = entry._result.installed ? onUninstallClicked : onInstallClicked;
|
||||
|
@ -724,14 +729,4 @@ window.addEventListener('showStyles:done', function _() {
|
|||
}
|
||||
|
||||
//endregion
|
||||
|
||||
function objectPick(obj, keys) {
|
||||
const result = {};
|
||||
for (const k in obj) {
|
||||
if (keys.includes(k)) {
|
||||
result[k] = obj[k];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user