blob: dc65aa26653ea0d329cc202cad70ce4de25cebc0 [file] [log] [blame]
Robert Lyfd1eb132012-06-08 12:21:15 -07001(function() { // anonymize
2
3var allTags = {};
4var loadedResults = [];
5
6/**
7 * Initialization code run upon the DOM being ready.
8 */
9$(document).ready(function() {
10 // Parse page query parameters.
11 var params = parseParams(document.location.search);
12 params.tag = params.tag ? makeArray(params.tag) : null;
13
14 // Load tag and resource dataset.
15 loadTags();
16 loadResources();
17
18 showResults(params);
19
20 // Watch for keypresses in the keyword filter textbox, and update
21 // search results to reflect the keyword filter.
22 $('#resource-browser-keyword-filter').keyup(function() {
23 // Filter results on screen by keyword.
24 var keywords = $(this).val().split(/\s+/g);
25 for (var i = 0; i < loadedResults.length; i++) {
26 var hide = false;
27 for (var j = 0; j < keywords.length; j++) {
28 if (!resultMatchesKeyword(loadedResults[i].result, keywords[j])) {
29 hide = true;
30 break;
31 }
32 }
33
34 loadedResults[i].node[hide ? 'hide' : 'show']();
35 }
36 });
37});
38
39/**
40 * Returns whether or not the given search result contains the given keyword.
41 */
42function resultMatchesKeyword(result, keyword) {
43 keyword = keyword.toLowerCase();
44 if (result.title &&
45 result.title.en.toLowerCase().indexOf(keyword) >= 0)
46 return true;
47 else if (result.description &&
48 result.description.en.toLowerCase().indexOf(keyword) >= 0)
49 return true;
50 else if (result.topicsHtml &&
51 result.topicsHtml.replace(/\<.*?\>/g,'').toLowerCase().indexOf(keyword) >= 0)
52 return true;
53 return false;
54}
55
56/**
57 * Populates the allTags array with tag data from the ANDROID_TAGS
58 * variable in the resource data JS file.
59 */
60function loadTags() {
61 for (var tagClass in ANDROID_TAGS) {
62 for (var tag in ANDROID_TAGS[tagClass]) {
63 allTags[tag] = {
64 displayTag: ANDROID_TAGS[tagClass][tag],
65 tagClass: tagClass
66 };
67 }
68 }
69}
70
71/**
72 * Massage the ANDROID_RESOURCES resource list in the resource data JS file.
73 */
74function loadResources() {
75 for (var i = 0; i < ANDROID_RESOURCES.length; i++) {
76 var resource = ANDROID_RESOURCES[i];
77
78 // Convert the tags array to a tags hash for easier querying.
79 resource.tagsHash = {};
80 for (var j = 0; j < resource.tags.length; j++)
81 resource.tagsHash[resource.tags[j]] = true;
82
83 // Determine the type and topics of the resource by inspecting its tags.
84 resource.topics = [];
85 for (tag in resource.tagsHash)
86 if (tag in allTags) {
87 if (allTags[tag].tagClass == 'type') {
88 resource.type = tag;
89 } else if (allTags[tag].tagClass == 'topic') {
90 resource.topics.push(tag);
91 }
92 }
93
94 // Add a humanized topics list string.
95 resource.topicsHtml = humanizeList(resource.topics, function(item) {
96 return '<strong>' + allTags[item].displayTag + '</strong>';
97 });
98 }
99}
100
101/**
102 * Loads resources for the given query parameters.
103 */
104function showResults(params) {
105 loadedResults = [];
106 $('#resource-browser-search-params').empty();
107 $('#resource-browser-results').empty();
108
109 var i, j;
110 var searchTags = [];
111 if (params.tag) {
112 for (i = 0; i < params.tag.length; i++) {
113 var tag = params.tag[i];
114 if (tag.toLowerCase() in allTags) {
115 searchTags.push(tag.toLowerCase());
116 }
117 }
118 }
119
120 if (searchTags.length) {
121 // Show query params.
122 var taggedWithHtml = ['Showing technical resources tagged with '];
123 taggedWithHtml.push(humanizeList(searchTags, function(item) {
124 return '<strong>' + allTags[item].displayTag + '</strong>';
125 }));
126 $('#resource-browser-search-params').html(taggedWithHtml.join('') + ':');
127 } else {
128 $('#resource-browser-search-params').html('Showing all technical resources:');
129 }
130
131 var results = [];
132
133 // Create the list of resources to show.
134 for (i = 0; i < ANDROID_RESOURCES.length; i++) {
135 var resource = ANDROID_RESOURCES[i];
136 var skip = false;
137
138 if (searchTags.length) {
139 for (j = 0; j < searchTags.length; j++)
140 if (!(searchTags[j] in resource.tagsHash)) {
141 skip = true;
142 break;
143 }
144
145 if (skip)
146 continue;
147
148 results.push(resource);
149 continue;
150 }
151
152 results.push(resource);
153 }
154
155 // Format and show the list of resource results.
156 if (results.length) {
157 $('#resource-browser-results .no-results').hide();
158 for (i = 0; i < results.length; i++) {
159 var result = results[i];
160 var resultJqNode = $(tmpl('tmpl_resource_browser_result', result));
161 for (tag in result.tagsHash)
162 resultJqNode.addClass('tagged-' + tag);
163 $('#resource-browser-results').append(resultJqNode);
164
165 loadedResults.push({ node: resultJqNode, result: result });
166 }
167 } else {
168 $('#resource-browser-results .no-results').show();
169 }
170}
171
172/**
173 * Formats the given array into a human readable, English string, ala
174 * 'a, b and c', with an optional item formatter/wrapper function.
175 */
176function humanizeList(arr, itemFormatter) {
177 itemFormatter = itemFormatter || function(o){ return o; };
178 arr = arr || [];
179
180 var out = [];
181 for (var i = 0; i < arr.length; i++) {
182 out.push(itemFormatter(arr[i]) +
183 ((i < arr.length - 2) ? ', ' : '') +
184 ((i == arr.length - 2) ? ' and ' : ''));
185 }
186
187 return out.join('');
188}
189
190/**
191 * Parses a parameter string, i.e. foo=1&bar=2 into
192 * a dictionary object.
193 */
194function parseParams(paramStr) {
195 var params = {};
196 paramStr = paramStr.replace(/^[?#]/, '');
197
198 var pairs = paramStr.split('&');
199 for (var i = 0; i < pairs.length; i++) {
200 var p = pairs[i].split('=');
201 var key = p[0] ? decodeURIComponent(p[0]) : p[0];
202 var val = p[1] ? decodeURIComponent(p[1]) : p[1];
203 if (val === '0')
204 val = 0;
205 if (val === '1')
206 val = 1;
207
208 if (key in params) {
209 // Handle array values.
210 params[key] = makeArray(params[key]);
211 params[key].push(val);
212 } else {
213 params[key] = val;
214 }
215 }
216
217 return params;
218}
219
220/**
221 * Returns the argument as a single-element array, or the argument itself
222 * if it's already an array.
223 */
224function makeArray(o) {
225 if (!o)
226 return [];
227
228 if (typeof o === 'object' && 'splice' in o) {
229 return o;
230 } else {
231 return [o];
232 }
233}
234
235})();