| (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]; |
| } |
| } |
| |
| })(); |