Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tabs for search for better information access #45055

Merged
merged 1 commit into from
Oct 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 145 additions & 22 deletions src/librustdoc/html/static/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,17 @@
}
}

function findArg(obj, val) {
if (obj && obj.type && obj.type.inputs.length > 0) {
for (var i = 0; i < obj.type.inputs.length; i++) {
if (obj.type.inputs[i].name === val) {
return true;
}
}
}
return false;
}

function typePassesFilter(filter, type) {
// No filter
if (filter < 0) return true;
Expand Down Expand Up @@ -376,18 +387,28 @@
if (typePassesFilter(typeFilter, searchIndex[i].ty)) {
results.push({id: i, index: -1});
}
} else if (findArg(searchIndex[i], val.toLowerCase()) ||
(searchIndex[i].type &&
searchIndex[i].type.output &&
searchIndex[i].type.output.name === val.toLowerCase())) {
if (typePassesFilter(typeFilter, searchIndex[i].ty)) {
results.push({id: i, index: -1, dontValidate: true});
}
}
if (results.length === max) {
break;
}
}
query.inputs = [val];
query.output = val;
query.search = val;
// searching by type
} else if (val.search("->") > -1) {
var trimmer = function (s) { return s.trim(); };
var parts = val.split("->").map(trimmer);
var input = parts[0];
// sort inputs so that order does not matter
var inputs = input.split(",").map(trimmer).sort().toString();
var inputs = input.split(",").map(trimmer).sort();
var output = parts[1];

for (var i = 0; i < nSearchWords; ++i) {
Expand All @@ -403,12 +424,30 @@

// allow searching for void (no output) functions as well
var typeOutput = type.output ? type.output.name : "";
if ((inputs === "*" || inputs === typeInputs.toString()) &&
(output === "*" || output == typeOutput)) {
results.push({id: i, index: -1, dontValidate: true});
if (output === "*" || output == typeOutput) {
if (input === "*") {
results.push({id: i, index: -1, dontValidate: true});
} else {
var allFound = true;
for (var it = 0; allFound === true && it < inputs.length; it++) {
var found = false;
for (var y = 0; found === false && y < typeInputs.length; y++) {
found = typeInputs[y] === inputs[it];
}
allFound = found;
}
if (allFound === true) {
results.push({id: i, index: -1, dontValidate: true});
}
}
}
}
query.inputs = inputs;
query.output = output;
} else {
query.inputs = [val];
query.output = val;
query.search = val;
// gather matching search results up to a certain maximum
val = val.replace(/\_/g, "");
for (var i = 0; i < split.length; ++i) {
Expand Down Expand Up @@ -437,6 +476,15 @@
lev: lev_distance,
});
}
} else if (findArg(searchIndex[j], val)) {
if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
results.push({
id: j,
index: 0,
// we want lev results to go lower than others
lev: lev_distance,
});
}
}
if (results.length === max) {
break;
Expand Down Expand Up @@ -576,8 +624,7 @@
(parent !== undefined &&
parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
// lastly check to see if the name was a levenshtein match
levenshtein(name.toLowerCase(), keys[i]) <=
MAX_LEV_DISTANCE)) {
levenshtein(name.toLowerCase(), keys[i]) <= MAX_LEV_DISTANCE)) {
return false;
}
}
Expand Down Expand Up @@ -692,18 +739,18 @@
return h1.innerHTML;
}

function showResults(results) {
var output, shown, query = getQuery();

currentResults = query.id;
output = '<h1>Results for ' + escape(query.query) +
(query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>';
output += '<table class="search-results">';
function addTab(array, query, display) {
var extraStyle = '';
if (display === false) {
extraStyle = ' style="display: none;"';
}

if (results.length > 0) {
shown = [];
var output = '';
if (array.length > 0) {
output = `<table class="search-results"${extraStyle}>`;
var shown = [];

results.forEach(function(item) {
array.forEach(function(item) {
var name, type, href, displayPath;

if (shown.indexOf(item) !== -1) {
Expand Down Expand Up @@ -752,13 +799,32 @@
'<span class="desc">' + escape(item.desc) +
'&nbsp;</span></a></td></tr>';
});
output += '</table>';
} else {
output += 'No results :( <a href="https://duckduckgo.com/?q=' +
output = `<div class="search-failed"${extraStyle}>No results :(<br/>` +
'Try on <a href="https://duckduckgo.com/?q=' +
encodeURIComponent('rust ' + query.query) +
'">Try on DuckDuckGo?</a>';
'">DuckDuckGo</a>?</div>';
}
return output;
}

function showResults(results) {
var output, query = getQuery();

currentResults = query.id;
output = '<h1>Results for ' + escape(query.query) +
(query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>' +
'<div id="titles">' +
'<div class="selected">Types/modules</div>' +
'<div>As parameters</div>' +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe

As a parameter

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can look for multiple parameters at once (String, usize -> *).

'<div>As return value</div></div><div id="results">';

output += addTab(results['others'], query);
output += addTab(results['in_args'], query, false);
output += addTab(results['returned'], query, false);
output += '</div>';

output += "</p>";
addClass(document.getElementById('main'), 'hidden');
var search = document.getElementById('search');
removeClass(search, 'hidden');
Expand All @@ -773,13 +839,17 @@
e.style.width = width + 'px';
});
initSearchNav();
var elems = document.getElementById('titles').childNodes;
elems[0].onclick = function() { printTab(0); };
elems[1].onclick = function() { printTab(1); };
elems[2].onclick = function() { printTab(2); };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Protip:

elems[2].onclick = function() { printTab(2); };

can be

elems[2].onclick = printTab.bind(null, 2)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it less readable. :-/

}

function search(e) {
var query,
filterdata = [],
obj, i, len,
results = [],
results = {"in_args": [], "returned": [], "others": []},
maxResults = 200,
resultIndex;
var params = getQueryStringParams();
Expand Down Expand Up @@ -810,11 +880,43 @@
len = resultIndex.length;
for (i = 0; i < len; ++i) {
if (resultIndex[i].id > -1) {
var added = false;
obj = searchIndex[resultIndex[i].id];
filterdata.push([obj.name, obj.ty, obj.path, obj.desc]);
results.push(obj);
if (obj.type) {
if (results['returned'].length < maxResults &&
obj.type.output &&
obj.type.output.name.toLowerCase() === query.output) {
results['returned'].push(obj);
added = true;
}
if (results['in_args'].length < maxResults && obj.type.inputs.length > 0) {
var all_founds = true;
for (var it = 0;
all_founds === true && it < query.inputs.length;
it++) {
var found = false;
for (var y = 0;
found === false && y < obj.type.inputs.length;
y++) {
found = query.inputs[it] === obj.type.inputs[y].name;
}
all_founds = found;
}
if (all_founds === true) {
results['in_args'].push(obj);
added = true;
}
}
}
if (results['others'].length < maxResults &&
((query.search && obj.name.indexOf(query.search)) || added === false)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this condition not just results['others'].length < maxResults? I just checked out your PR and didn't see any difference between the longer form you have here and taking these extra conditions out. What is this trying to do?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case the only thing(s ?) match are the arguments or the returned type, I don't want to add extra information. For me, the 'others' tab is also about the type/function/module's name so it seems logical to not add everything (even if the filter is pretty light).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some checking, it seems like it won't stop things getting into results if their name matches as well as having a parameter type that matches (e.g. "Result" will show Try::into_result on both the "As return value" tab as well as the "Types/modules" tab) so i'll retract this concern.

results['others'].push(obj);
}
}
if (results.length >= maxResults) {
if (results['others'].length >= maxResults &&
results['in_args'].length >= maxResults &&
results['returned'].length >= maxResults) {
break;
}
}
Expand Down Expand Up @@ -1290,6 +1392,27 @@
return wrapper;
}

// In the search display, allows to switch between tabs.
function printTab(nb) {
var nb_copy = nb;
onEach(document.getElementById('titles').childNodes, function(elem) {
if (nb_copy === 0) {
addClass(elem, 'selected');
} else {
removeClass(elem, 'selected');
}
nb_copy -= 1;
});
onEach(document.getElementById('results').childNodes, function(elem) {
if (nb === 0) {
elem.style.display = '';
} else {
elem.style.display = 'none';
}
nb -= 1;
});
}

onEach(document.getElementById('main').getElementsByTagName('pre'), function(e) {
onEach(e.getElementsByClassName('attributes'), function(i_e) {
i_e.parentNode.insertBefore(createToggleWrapper(), i_e);
Expand Down
26 changes: 26 additions & 0 deletions src/librustdoc/html/static/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -866,3 +866,29 @@ span.since {
pre.rust {
position: relative;
}

.search-failed {
text-align: center;
margin-top: 20px;
}

#titles {
height: 35px;
}

#titles > div {
float: left;
width: 33.3%;
text-align: center;
border-bottom: 1px solid #ccc;
font-size: 18px;
cursor: pointer;
}

#titles > div.selected {
border-bottom: 3px solid #0078ee;
}

#titles > div:hover {
border-bottom: 3px solid #0089ff;
}
4 changes: 4 additions & 0 deletions src/librustdoc/html/static/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,7 @@ pre.ignore:hover, .information:hover + pre.ignore {
.information > .ignore:hover {
color: rgba(255,142,0,1);
}

.search-failed > a {
color: #0089ff;
}