diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 2385fdbb..451da03b 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -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",
diff --git a/popup.html b/popup.html
index 3ab9a22e..d90375fd 100644
--- a/popup.html
+++ b/popup.html
@@ -1,3 +1,4 @@
+
@@ -88,53 +89,49 @@
-
-
+
+
-
- ◄
+ ◄
- -
+ -
/
- -
+ -
- ►
+ ►
@@ -219,10 +216,10 @@
diff --git a/popup/search-results.css b/popup/search-results.css
index 70746ff0..0e1f4403 100755
--- a/popup/search-results.css
+++ b/popup/search-results.css
@@ -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 {
diff --git a/popup/search-results.js b/popup/search-results.js
index 69cdc6ab..8d556a08 100755
--- a/popup/search-results.js
+++ b/popup/search-results.js
@@ -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;
- }
});