236 lines
6.1 KiB
JavaScript
236 lines
6.1 KiB
JavaScript
|
(function() { // anonymize
|
||
|
|
||
|
var allTags = {};
|
||
|
var loadedResults = [];
|
||
|
|
||
|
/**
|
||
|
* Initialization code run upon the DOM being ready.
|
||
|
*/
|
||
|
$(document).ready(function() {
|
||
|
// Parse page query parameters.
|
||
|
var params = parseParams(document.location.search);
|
||
|
params.tag = params.tag ? makeArray(params.tag) : null;
|
||
|
|
||
|
// Load tag and resource dataset.
|
||
|
loadTags();
|
||
|
loadResources();
|
||
|
|
||
|
showResults(params);
|
||
|
|
||
|
// Watch for keypresses in the keyword filter textbox, and update
|
||
|
// search results to reflect the keyword filter.
|
||
|
$('#resource-browser-keyword-filter').keyup(function() {
|
||
|
// Filter results on screen by keyword.
|
||
|
var keywords = $(this).val().split(/\s+/g);
|
||
|
for (var i = 0; i < loadedResults.length; i++) {
|
||
|
var hide = false;
|
||
|
for (var j = 0; j < keywords.length; j++) {
|
||
|
if (!resultMatchesKeyword(loadedResults[i].result, keywords[j])) {
|
||
|
hide = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
loadedResults[i].node[hide ? 'hide' : 'show']();
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
/**
|
||
|
* Returns whether or not the given search result contains the given keyword.
|
||
|
*/
|
||
|
function resultMatchesKeyword(result, keyword) {
|
||
|
keyword = keyword.toLowerCase();
|
||
|
if (result.title &&
|
||
|
result.title.en.toLowerCase().indexOf(keyword) >= 0)
|
||
|
return true;
|
||
|
else if (result.description &&
|
||
|
result.description.en.toLowerCase().indexOf(keyword) >= 0)
|
||
|
return true;
|
||
|
else if (result.topicsHtml &&
|
||
|
result.topicsHtml.replace(/\<.*?\>/g,'').toLowerCase().indexOf(keyword) >= 0)
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Populates the allTags array with tag data from the ANDROID_TAGS
|
||
|
* variable in the resource data JS file.
|
||
|
*/
|
||
|
function loadTags() {
|
||
|
for (var tagClass in ANDROID_TAGS) {
|
||
|
for (var tag in ANDROID_TAGS[tagClass]) {
|
||
|
allTags[tag] = {
|
||
|
displayTag: ANDROID_TAGS[tagClass][tag],
|
||
|
tagClass: tagClass
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Massage the ANDROID_RESOURCES resource list in the resource data JS file.
|
||
|
*/
|
||
|
function loadResources() {
|
||
|
for (var i = 0; i < ANDROID_RESOURCES.length; i++) {
|
||
|
var resource = ANDROID_RESOURCES[i];
|
||
|
|
||
|
// Convert the tags array to a tags hash for easier querying.
|
||
|
resource.tagsHash = {};
|
||
|
for (var j = 0; j < resource.tags.length; j++)
|
||
|
resource.tagsHash[resource.tags[j]] = true;
|
||
|
|
||
|
// Determine the type and topics of the resource by inspecting its tags.
|
||
|
resource.topics = [];
|
||
|
for (tag in resource.tagsHash)
|
||
|
if (tag in allTags) {
|
||
|
if (allTags[tag].tagClass == 'type') {
|
||
|
resource.type = tag;
|
||
|
} else if (allTags[tag].tagClass == 'topic') {
|
||
|
resource.topics.push(tag);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add a humanized topics list string.
|
||
|
resource.topicsHtml = humanizeList(resource.topics, function(item) {
|
||
|
return '<strong>' + allTags[item].displayTag + '</strong>';
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Loads resources for the given query parameters.
|
||
|
*/
|
||
|
function showResults(params) {
|
||
|
loadedResults = [];
|
||
|
$('#resource-browser-search-params').empty();
|
||
|
$('#resource-browser-results').empty();
|
||
|
|
||
|
var i, j;
|
||
|
var searchTags = [];
|
||
|
if (params.tag) {
|
||
|
for (i = 0; i < params.tag.length; i++) {
|
||
|
var tag = params.tag[i];
|
||
|
if (tag.toLowerCase() in allTags) {
|
||
|
searchTags.push(tag.toLowerCase());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (searchTags.length) {
|
||
|
// Show query params.
|
||
|
var taggedWithHtml = ['Showing technical resources tagged with '];
|
||
|
taggedWithHtml.push(humanizeList(searchTags, function(item) {
|
||
|
return '<strong>' + allTags[item].displayTag + '</strong>';
|
||
|
}));
|
||
|
$('#resource-browser-search-params').html(taggedWithHtml.join('') + ':');
|
||
|
} else {
|
||
|
$('#resource-browser-search-params').html('Showing all technical resources:');
|
||
|
}
|
||
|
|
||
|
var results = [];
|
||
|
|
||
|
// Create the list of resources to show.
|
||
|
for (i = 0; i < ANDROID_RESOURCES.length; i++) {
|
||
|
var resource = ANDROID_RESOURCES[i];
|
||
|
var skip = false;
|
||
|
|
||
|
if (searchTags.length) {
|
||
|
for (j = 0; j < searchTags.length; j++)
|
||
|
if (!(searchTags[j] in resource.tagsHash)) {
|
||
|
skip = true;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (skip)
|
||
|
continue;
|
||
|
|
||
|
results.push(resource);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
results.push(resource);
|
||
|
}
|
||
|
|
||
|
// Format and show the list of resource results.
|
||
|
if (results.length) {
|
||
|
$('#resource-browser-results .no-results').hide();
|
||
|
for (i = 0; i < results.length; i++) {
|
||
|
var result = results[i];
|
||
|
var resultJqNode = $(tmpl('tmpl_resource_browser_result', result));
|
||
|
for (tag in result.tagsHash)
|
||
|
resultJqNode.addClass('tagged-' + tag);
|
||
|
$('#resource-browser-results').append(resultJqNode);
|
||
|
|
||
|
loadedResults.push({ node: resultJqNode, result: result });
|
||
|
}
|
||
|
} else {
|
||
|
$('#resource-browser-results .no-results').show();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Formats the given array into a human readable, English string, ala
|
||
|
* 'a, b and c', with an optional item formatter/wrapper function.
|
||
|
*/
|
||
|
function humanizeList(arr, itemFormatter) {
|
||
|
itemFormatter = itemFormatter || function(o){ return o; };
|
||
|
arr = arr || [];
|
||
|
|
||
|
var out = [];
|
||
|
for (var i = 0; i < arr.length; i++) {
|
||
|
out.push(itemFormatter(arr[i]) +
|
||
|
((i < arr.length - 2) ? ', ' : '') +
|
||
|
((i == arr.length - 2) ? ' and ' : ''));
|
||
|
}
|
||
|
|
||
|
return out.join('');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Parses a parameter string, i.e. foo=1&bar=2 into
|
||
|
* a dictionary object.
|
||
|
*/
|
||
|
function parseParams(paramStr) {
|
||
|
var params = {};
|
||
|
paramStr = paramStr.replace(/^[?#]/, '');
|
||
|
|
||
|
var pairs = paramStr.split('&');
|
||
|
for (var i = 0; i < pairs.length; i++) {
|
||
|
var p = pairs[i].split('=');
|
||
|
var key = p[0] ? decodeURIComponent(p[0]) : p[0];
|
||
|
var val = p[1] ? decodeURIComponent(p[1]) : p[1];
|
||
|
if (val === '0')
|
||
|
val = 0;
|
||
|
if (val === '1')
|
||
|
val = 1;
|
||
|
|
||
|
if (key in params) {
|
||
|
// Handle array values.
|
||
|
params[key] = makeArray(params[key]);
|
||
|
params[key].push(val);
|
||
|
} else {
|
||
|
params[key] = val;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return params;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the argument as a single-element array, or the argument itself
|
||
|
* if it's already an array.
|
||
|
*/
|
||
|
function makeArray(o) {
|
||
|
if (!o)
|
||
|
return [];
|
||
|
|
||
|
if (typeof o === 'object' && 'splice' in o) {
|
||
|
return o;
|
||
|
} else {
|
||
|
return [o];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
})();
|