Cleaning things up; still doesn't install but does everything else.

This commit is contained in:
derv82 2017-11-19 02:54:20 -08:00
parent f1830c3768
commit 0a8274a04f
4 changed files with 99 additions and 38 deletions

View File

@ -337,13 +337,13 @@
"message": "Load Styles",
"description": "Text for a link that loads styles within the popup"
},
"remoteStyleInstall": {
"searchResultInstall": {
"message": "Install",
"description": "Text for a button that installs a remote style"
"description": "Text for a button that installs a search result"
},
"remoteStyleInstallTooltip": {
"message": "Install this style permanently",
"description": "Tooltip for a button that installs a remote style"
"searchResultInstallTooltip": {
"message": "Install this search result",
"description": "Tooltip for a button that installs a search result"
},
"findStylesForSite": {
"message": "Find more styles for this site",

View File

@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<link rel="stylesheet" href="popup/popup.css">
<link rel="stylesheet" href="popup/remoteStyles.css">
<link rel="stylesheet" href="popup/searchResults.css">
<style id="firefox-transitions-bug-suppressor">
/* restrict to FF */
@ -90,7 +90,7 @@
<a class="searchResult-authorLink" target="_blank"></a>
</div>
<div class="actions">
<button class="remote-style-install" i18n-text="remoteStyleInstall" i18n-title="remoteStyleInstallTooltip"></button>
<button class="searchResult-install" i18n-text="searchResultInstall" i18n-title="searchResultInstallTooltip"></button>
</div>
</div>
</template>
@ -101,7 +101,7 @@
<script src="js/prefs.js"></script>
<script src="content/apply.js"></script>
<script src="popup/popup.js"></script>
<script src="popup/remoteStyles.js"></script>
<script src="popup/searchResults.js"></script>
</head>
<body id="stylus-popup">
@ -128,9 +128,9 @@
<label id="disableAll-label" for="disableAll" i18n-text="disableAllStyles"></label>
</div>
</div>
<div id="remote-styles" class="hidden">
<div id="searchResults" class="hidden">
<h3>Search Results for <span id="searchResults-terms">-</span></h3>
<div id="searchResults"></div>
<div id="searchResults-list"></div>
<div id="searchResultsNav">
<button id="searchResultsNav-prev" title="Previous page" disabled>Prev</button>
<label>
@ -143,8 +143,8 @@
</div>
<div class="left-gutter"></div>
<div class="main-controls">
<div id="load-remote-styles">
<a id="load-remote-styles-link" href="#"
<div id="load-search-results">
<a id="load-search-results-link" href="#"
i18n-text="loadStylesForSite"></a>
</div>
<div id="find-styles">

View File

@ -3,12 +3,17 @@
margin-bottom: 5px;
}
#remote-styles.hidden,
#load-remote-styles.hidden {
#searchResults,
#load-search-results {
display: block;
}
#searchResults.hidden,
#load-search-results.hidden {
display: none;
}
#remote-styles, #searchResults {
#searchResults, #searchResults-list {
max-width: 200px;
overflow: hidden;
}
@ -57,6 +62,10 @@
text-align: center;
}
.searchResult-install {
width: 100%;
}
#searchResultsNav-prev[disabled],
#searchResultsNav-next[disabled] {
cursor: not-allowed;

View File

@ -4,23 +4,35 @@ let currentPage = 1;
let hostname;
/**
* Fetches and parses search results (in JSON) from userstyles.org
* @return {Object} Search results from userstyles.org
* Fetches JSON object from userstyles.org API
* @param {string} path Path on userstyles.org (e.g. /api/v1/styles)
* @param {string} queryParams Query parameters to send in search request.
* @return {Object} API response object from userstyles.org
*/
function fetchSearchResults(queryParams) {
function fetchUserstylesAPI(path, queryParams) {
return new Promise(function(resolve, reject) {
const TIMEOUT = 10000;
const headers = {
'Content-type': 'application/json',
'Accept': '*/*'
};
const url = 'https://userstyles.org/api/v1/styles/search?' + queryParams;
let url = 'https://userstyles.org' + path;
if (queryParams) {
url += "?" + queryParams;
}
const xhr = new XMLHttpRequest();
xhr.timeout = TIMEOUT;
xhr.onload = () => (xhr.status === 200 || url.protocol === 'file:'
? resolve(JSON.parse(xhr.responseText))
: reject(xhr.status));
xhr.onload = () => {
if (xhr.status === 200 || url.protocol === 'file:') {
try {
resolve(JSON.parse(xhr.responseText));
} catch (err) {
reject("Failed to parse JSON from " + url + "\nJSON Text: " + xhr.responseText);
}
} else {
reject(xhr.status);
}
};
xhr.onerror = reject;
xhr.open('GET', url, true);
for (const key of Object.keys(headers)) {
@ -31,13 +43,12 @@ function fetchSearchResults(queryParams) {
}
/**
*
* Adds an entry to the Search Results DOM
* @param {Object} searchResult The JSON object from userstyles.org representing a search result.
*/
function createSearchResultElement(searchResult) {
/*
searchResult format:
{
searchResult format: {
id: 100835,
name: "Reddit Flat Dark",
screenshot_url: "19339_after.png",
@ -87,7 +98,29 @@ function createSearchResultElement(searchResult) {
onclick: handleEvent.openURLandHide
});
$('#searchResults').appendChild(entry);
// TODO: Total & Weekly Install Counts
// TODO: Rating
const install = $('.searchResult-install', entry);
const name = searchResult.name;
Object.assign(install, {
onclick: (event) => {
event.preventDefault();
// TODO: Install style
fetchUserstylesAPI("/api/v1/styles/" + searchResult.id)
.then( styleObject => {
console.log("TODO: Install style ID", searchResult.id);
console.log("Full styleObject:", styleObject);
alert("TODO: Install style ID #" + searchResult.id + " name '" + searchResult.name + "'");
})
.catch(reason => {
throw reason;
});
return true;
}
});
$('#searchResults-list').appendChild(entry);
}
function updateSearchResultsNav(currentPage, totalPages) {
@ -106,11 +139,13 @@ function updateSearchResultsNav(currentPage, totalPages) {
} else {
$('#searchResultsNav-prev').removeAttribute('disabled');
}
// Update current/total counts
$('#searchResultsNav-currentPage').textContent = currentPage;
$('#searchResultsNav-totalPages').textContent = totalPages;
}
function insertRemoteStyles(searchResults) {
function processSearchResults(searchResults) {
/*
searchResults: {
data: [...],
@ -125,8 +160,21 @@ function insertRemoteStyles(searchResults) {
searchResults.data.forEach(createSearchResultElement);
}
function loadRemoteStyles(event) {
function loadNextPage(event) {
currentPage += 1;
loadSearchResults(event);
}
function loadPrevPage(event) {
currentPage = Math.max(1, currentPage - 1);
loadSearchResults(event);
}
function loadSearchResults(event) {
event.preventDefault();
// Clear search results
$('#searchResults-list').innerHTML = "";
// Find styles for the current active tab
getActiveTab().then(tab => {
hostname = new URL(tab.url).hostname;
const queryParams = [
@ -135,11 +183,17 @@ function loadRemoteStyles(event) {
'per_page=3'
].join('&');
$('#searchresults-terms').textContent = hostname;
$('#remote-styles').classList.remove("hidden");
$('#load-remote-styles').classList.add("hidden");
fetchSearchResults(queryParams)
.then(insertRemoteStyles)
// Hide load button
$('#load-search-results').classList.add("hidden");
// Display results container
$('#searchResults').classList.remove("hidden");
$('#searchResults-terms').textContent = hostname;
fetchUserstylesAPI("/api/v1/styles/search", queryParams)
.then(code => {
processSearchResults(code);
})
.catch(reason => {
throw reason;
});
@ -147,10 +201,8 @@ function loadRemoteStyles(event) {
return false;
}
function initRemoteStyles() {
$('#load-remote-styles-link').onclick = loadRemoteStyles;
}
onDOMready().then(() => {
initRemoteStyles();
$('#load-search-results-link').onclick = loadSearchResults;
$('#searchResultsNav-prev').onclick = loadPrevPage;
$('#searchResultsNav-next').onclick = loadNextPage;
});