Website: start offering GitHub URL-driven suggestions

This commit is contained in:
Thaddee Tyl 2015-01-07 18:40:23 +01:00
parent 871d486f01
commit 2482e02b6b

View File

@ -42,6 +42,7 @@ hr.spacing { border: 0; display: block; height: 3mm; }
border-top: 15px solid #eaeaff;
border-bottom: 15px solid #eaeaff;
}
#suggestButton { display: none; }
table.badge > tbody > tr > td > img { cursor: pointer; }
</style>
@ -53,20 +54,15 @@ table.badge > tbody > tr > td > img { cursor: pointer; }
Pixel-perfect &nbsp; Retina-ready &nbsp; Fast &nbsp; Consistent &nbsp; Hackable &nbsp; No tracking
</p>
<!-- FIXME: search through vendor badges (`/$suggest/v1`, see suggest.js).
It should detect URLs, call an ajax hook in the server that fetches the project
data, return a list of valid badges for the project with copy-and-paste
markdown, html, etc.
If it isn't a URL, search through available badges for keywords corresponding to
the search.
When that is implemented, change the placeholder to 'search / project URL'
-->
<form action='javascript:void 0'>
<input name='projectSearch' id='projectSearch' autofocus placeholder='search'/>
<form id='searchForm' action='javascript:void 0' autocomplete=off>
<input name='projectSearch' id='projectSearch' autofill=off autofocus placeholder='search / project URL'/>
<br>
<button id='suggestButton'> Suggest badges </button>
</form>
<a href='https://gratipay.com/Shields/' style='text-decoration:none;color:rgba(0,0,0,0.1)'>donate</a>
<section id='suggestedBadges'></section>
<h3> Build </h3>
<table class='badge'><tbody>
<tr><th> Travis: </th>
@ -685,18 +681,20 @@ is where the current server got started.
// Search
var searchBadgeDb = {index: [], tr: []};
function searchBadgeDbInit() {
searchBadgeDb = {index: [], tr: []};
var trs = document.querySelectorAll('table.badge tr');
for (var i = 0; i < trs.length; i++) {
var tr = trs[i];
var th = tr.firstElementChild;
searchBadgeDb.index.push(th.textContent + ' ' + th.dataset.keywords);
var keywords = th.dataset.keywords? th.dataset.keywords: '';
searchBadgeDb.index.push(th.textContent + ' ' + keywords);
searchBadgeDb.tr.push(tr);
}
projectSearch.addEventListener('input', searchBadge);
}
function searchBadge(event) {
var query = event.target.value;
var regex = new RegExp(query, 'i');
var regex = new RegExp(query, 'i'); // Case-insensitive
for (var i = 0; i < searchBadgeDb.index.length; i++) {
if (regex.test(searchBadgeDb.index[i])) {
searchBadgeDb.tr[i].removeAttribute('style');
@ -704,10 +702,57 @@ function searchBadge(event) {
searchBadgeDb.tr[i].style.display = 'none';
}
}
// If it has the format of a url, show the suggest button.
if (isUrl(query)) { showSuggestButton();
} else { hideSuggestButton();
}
}
document.addEventListener('DOMContentLoaded', searchBadgeDbInit);
// Suggested badges search
function isUrl(url) {
var http = url.slice(0, 5) === 'http:';
var https = url.slice(0, 6) === 'https:';
return http || https;
}
function showSuggestButton() { suggestButton.style.display = 'inline'; }
function hideSuggestButton() { suggestButton.style.display = 'none'; }
function showSuggestedBadges(badges) {
var html = '<table class="badge"><tbody>';
for (var i = 0; i < badges.length; i++) {
var link = badges[i].link;
var badge = badges[i].badge;
var name = badges[i].name + ':';
html += '<tr><th data-link="' + link + '">' + name + '</th>' +
'<td><img src="' + badge + '"></td>' +
'<td><code>' + badge + '</code></td>' +
'</tr>';
}
html += '</tbody></table>';
suggestedBadges.innerHTML = html;
suggestedBadges.style.display = 'block';
}
function suggestBadges(event) {
var url = event.target.projectSearch.value;
if (isUrl(url)) {
ajax('suggest/v1', {url:url}, function(err, res) {
if (err != null) { return; }
showSuggestedBadges(res.badges);
suggestButton.disabled = false;
searchBadgeDbInit();
markupDialogInit();
});
suggestButton.disabled = true;
}
}
function suggestBadgeInit() {
searchForm.addEventListener('submit', suggestBadges);
}
document.addEventListener('DOMContentLoaded', suggestBadgeInit);
// Markup copier dialog
function markupDialogInit() {
var trs = document.querySelectorAll('table.badge tr');
@ -732,7 +777,10 @@ function markupDialog(tr) {
// Trim the ending colon `:`.
var trname = tr.firstElementChild.textContent.trim().slice(0, -1);
var trimg = tr.querySelector('img').src;
var th = tr.firstElementChild;
var link = th.dataset.link? th.dataset.link: '';
copyForm.img.value = trimg;
copyForm.url.value = link;
// Set up the input listeners.
copyForm.url.removeEventListener('input', copyFormUrlEventListener);
copyForm.img.removeEventListener('input', copyFormUrlEventListener);
@ -795,4 +843,38 @@ function makeImage() {
function escapeField(s) {
return encodeURIComponent(s.replace(/-/g, '--').replace(/_/g, '__'));
}
// Convert object literal to xhr-sendable.
function toXhrSend(data) {
var str = '', start = true;
var jsondata = '';
for (var key in data) {
if (typeof (jsondata = JSON.stringify(data[key])) === 'string') {
str += (start? '': '&');
if (typeof data[key] === 'string') {
str += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]);
} else {
str += encodeURIComponent(key) + '=' + encodeURIComponent(jsondata);
}
start = false;
}
}
return str;
}
function ajax(verb, adverbs, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/$" + verb + '?' + toXhrSend(adverbs), true);
xhr.onload = function (e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
try {
cb(null, JSON.parse(xhr.responseText));
} catch(e) {cb(e);}
}
}
};
xhr.onerror = function (e) { cb(Error(xhr.statusText)); };
xhr.send(null);
}
</script>