Changeset View
Changeset View
Standalone View
Standalone View
webroot/rsrc/js/core/behavior-search-typeahead.js
Show First 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | function transform(object) { | ||||
object.display = render; | object.display = render; | ||||
return object; | return object; | ||||
} | } | ||||
datasource.setTransformer(transform); | datasource.setTransformer(transform); | ||||
// Sort handler that orders results by type (e.g., applications, users) | |||||
// and then selects for good matches on the "priority" substrings if they | |||||
// exist (for instance, username matches are preferred over real name | |||||
// matches, and application name matches are preferred over application | |||||
// flavor text matches). | |||||
var sort_handler = function(value, list, cmp) { | var sort_handler = function(value, list, cmp) { | ||||
var priority_hits = {}; | // First, sort all the results normally. | ||||
var type_priority = { | JX.bind(this, JX.Prefab.sortHandler, {}, value, list, cmp)(); | ||||
'jump' : 1, | |||||
'apps' : 2, | |||||
'proj' : 3, | |||||
'user' : 4, | |||||
'repo' : 5, | |||||
'symb' : 6 | |||||
}; | |||||
var tokens = this.tokenize(value); | |||||
// Now we're going to apply some special rules to order results by type, | |||||
// so applications always appear near the top, then users, etc. | |||||
var ii; | var ii; | ||||
for (ii = 0; ii < list.length; ii++) { | |||||
var item = list[ii]; | |||||
for (var jj = 0; jj < tokens.length; jj++) { | var type_order = [ | ||||
if (item.name.indexOf(tokens[jj]) === 0) { | 'jump', | ||||
priority_hits[item.id] = true; | 'apps', | ||||
} | 'proj', | ||||
'user', | |||||
'repo', | |||||
'symb', | |||||
'misc' | |||||
]; | |||||
var type_map = {}; | |||||
for (ii = 0; ii < type_order.length; ii++) { | |||||
type_map[type_order[ii]] = true; | |||||
} | } | ||||
if (!item.priority) { | var buckets = {}; | ||||
continue; | for (ii = 0; ii < list.length; ii++) { | ||||
} | var item = list[ii]; | ||||
for (var hh = 0; hh < tokens.length; hh++) { | var type = item.priorityType; | ||||
if (item.priority.substr(0, tokens[hh].length) == tokens[hh]) { | if (!type_map.hasOwnProperty(type)) { | ||||
priority_hits[item.id] = true; | type = 'misc'; | ||||
} | } | ||||
} | |||||
} | |||||
list.sort(function(u, v) { | |||||
var u_type = type_priority[u.priorityType] || 999; | |||||
var v_type = type_priority[v.priorityType] || 999; | |||||
if (u_type != v_type) { | if (!buckets.hasOwnProperty(type)) { | ||||
return u_type - v_type; | buckets[type] = []; | ||||
} | } | ||||
if (priority_hits[u.id] != priority_hits[v.id]) { | buckets[type].push(item); | ||||
return priority_hits[v.id] ? 1 : -1; | |||||
} | } | ||||
return cmp(u, v); | |||||
}); | |||||
// If we have more results than fit, limit each type of result to 3, so | // If we have more results than fit, limit each type of result to 3, so | ||||
// we show 3 applications, then 3 users, etc. For jump items, we show only | // we show 3 applications, then 3 users, etc. For jump items, we show only | ||||
// one result. | // one result. | ||||
var type_count = 0; | |||||
var current_type = null; | var jj; | ||||
for (ii = 0; ii < list.length; ii++) { | var results = []; | ||||
if (list[ii].type != current_type) { | for (ii = 0; ii < type_order.length; ii++) { | ||||
current_type = list[ii].type; | var current_type = type_order[ii]; | ||||
type_count = 1; | var type_list = buckets[current_type] || []; | ||||
} else { | for (jj = 0; jj < type_list.length; jj++) { | ||||
type_count++; | |||||
// Skip this item if: | // Skip this item if: | ||||
// - it's a jump nav item, and we already have at least one jump | // - it's a jump nav item, and we already have at least one jump | ||||
// nav item; or | // nav item; or | ||||
// - we have more items than will fit in the typeahead, and this | // - we have more items than will fit in the typeahead, and this | ||||
// is the 4..Nth result of its type. | // is the 4..Nth result of its type. | ||||
var skip = ((current_type == 'jump') && (type_count > 1)) || | var skip = ((current_type == 'jump') && (jj > 1)) || | ||||
((list.length > config.limit) && (type_count > 3)); | ((list.length > config.limit) && (type_count > 3)); | ||||
if (skip) { | if (skip) { | ||||
list.splice(ii, 1); | continue; | ||||
ii--; | |||||
} | } | ||||
results.push(type_list[jj]); | |||||
} | } | ||||
} | } | ||||
// Replace the list in place with the results. | |||||
list.splice.apply(list, [0, list.length].concat(results)); | |||||
}; | }; | ||||
datasource.setSortHandler(JX.bind(datasource, sort_handler)); | datasource.setSortHandler(JX.bind(datasource, sort_handler)); | ||||
datasource.setFilterHandler(JX.Prefab.filterClosedResults); | |||||
datasource.setMaximumResultCount(config.limit); | datasource.setMaximumResultCount(config.limit); | ||||
var typeahead = new JX.Typeahead(JX.$(config.id), JX.$(config.input)); | var typeahead = new JX.Typeahead(JX.$(config.id), JX.$(config.input)); | ||||
typeahead.setDatasource(datasource); | typeahead.setDatasource(datasource); | ||||
typeahead.setPlaceholder(config.placeholder); | typeahead.setPlaceholder(config.placeholder); | ||||
typeahead.listen('choose', function(r) { | typeahead.listen('choose', function(r) { | ||||
JX.$U(r.href).go(); | JX.$U(r.href).go(); | ||||
▲ Show 20 Lines • Show All 129 Lines • Show Last 20 Lines |