Add a configurable limit to tags initially displayed in search results

When the limit is reached, a button allow expanding/collapsing remaining
tags.

When this feature is activated without a limit to the number of
displayed tags, when encountering search results with a very large
number of keywords, the results page can become almost unusable (very
long vertical scrollbar)
pull/135/head
luccioman 8 years ago
parent f8c7d0265e
commit dbff7b14fc

@ -860,6 +860,8 @@ search.result.noreferrer=false
# search result lines may show additional information for each search hit
# these information pieces may be switched on or off
search.result.show.keywords = false
# Maximum number of keywords initially displayed. The eventual remaining ones can then be expanded.
search.result.keywords.firstMaxCount = 100
search.result.show.date = true
search.result.show.size = false
search.result.show.metadata = false

@ -237,7 +237,13 @@ var solr= $.getJSON("solr/collection1/select?q=*:*&defType=edismax&start=0&rows=
<a href="yacysearch.html" id="urlhash" target="LayouTest">http://url-of-the-search-result.net</a>
</p>
<p class="tags">
<input type="checkbox" name="search.result.show.keywords" aria-labelledby="tagsTitle" value="true" #(search.result.show.keywords)#::checked="checked" #(/search.result.show.keywords)# /> <span id="tagsTitle">Tags</span>: <span class="tag label label-default">keyword</span> <span class="tag label label-default">subject</span> <span class="tag label label-default">keyword2</span> <span class="tag label label-default">keyword3</span>
<input type="checkbox" name="search.result.show.keywords" aria-labelledby="tagsTitle" value="true" #(search.result.show.keywords)#::checked="checked" #(/search.result.show.keywords)# />
<span id="tagsTitle">Tags</span>: <span class="tag label label-default">keyword</span> <span class="tag label label-default">subject</span> <span class="tag label label-default">keyword2</span> <span class="tag label label-default">keyword3</span>
<label>
Max. tags initially displayed
<input type="number" name="search.result.keywords.firstMaxCount" value="#[search.result.keywords.firstMaxCount]#" min="1" max="2147483647"/>
(remaining can then be expanded)
</label>
</p>
<div class="urlinfo">
<table style="border-width:0">

@ -32,6 +32,7 @@ import java.io.IOException;
import java.sql.Date;
import java.util.Map;
import java.util.Properties;
import net.yacy.cora.date.GenericFormatter;
import net.yacy.cora.protocol.RequestHeader;
import net.yacy.cora.util.ConcurrentLog;
@ -69,7 +70,15 @@ public class ConfigSearchPage_p {
sb.setConfig("search.video", post.getBoolean("search.video"));
sb.setConfig("search.app", post.getBoolean("search.app"));
sb.setConfig("search.result.show.keywords", post.getBoolean("search.result.show.keywords"));
sb.setConfig(SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS, post.getBoolean(SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS));
// maximum number of initially displayed keywords/tags
int keywordsFirstMaxCount = post.getInt(SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT,
SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT_DEFAULT);
if (keywordsFirstMaxCount > 0) {
sb.setConfig(SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT, keywordsFirstMaxCount);
}
sb.setConfig("search.result.show.date", post.getBoolean("search.result.show.date"));
sb.setConfig("search.result.show.size", post.getBoolean("search.result.show.size"));
sb.setConfig("search.result.show.metadata", post.getBoolean("search.result.show.metadata"));
@ -160,7 +169,12 @@ public class ConfigSearchPage_p {
sb.setConfig("search.audio", config.getProperty("search.audio","false"));
sb.setConfig("search.video", config.getProperty("search.video","false"));
sb.setConfig("search.app", config.getProperty("search.app","false"));
sb.setConfig("search.result.show.keywords", config.getProperty("search.result.show.keywords","false"));
sb.setConfig(SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS,
config.getProperty(SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS,
Boolean.toString(SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS_DEFAULT)));
sb.setConfig(SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT,
config.getProperty(SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT,
String.valueOf(SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT_DEFAULT)));
sb.setConfig("search.result.show.date", config.getProperty("search.result.show.date","true"));
sb.setConfig("search.result.show.size", config.getProperty("search.result.show.size","false"));
sb.setConfig("search.result.show.metadata", config.getProperty("search.result.show.metadata","false"));
@ -198,7 +212,14 @@ public class ConfigSearchPage_p {
prop.put("search.video", sb.getConfigBool("search.video", false) ? 1 : 0);
prop.put("search.app", sb.getConfigBool("search.app", false) ? 1 : 0);
prop.put("search.result.show.keywords", sb.getConfigBool("search.result.show.keywords", false) ? 1 : 0);
prop.put(SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS,
sb.getConfigBool(SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS,
SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS_DEFAULT) ? 1 : 0);
prop.put(SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT,
sb.getConfigInt(SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT,
SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT_DEFAULT));
prop.put("search.result.show.date", sb.getConfigBool("search.result.show.date", false) ? 1 : 0);
prop.put("search.result.show.size", sb.getConfigBool("search.result.show.size", false) ? 1 : 0);
prop.put("search.result.show.metadata", sb.getConfigBool("search.result.show.metadata", false) ? 1 : 0);

@ -423,6 +423,22 @@ p.tags {
line-height: 1.4;
}
/* Button to expand/collapse tags beyond the initial number of tags display limit */
.expandKeywordsBtn {
margin-top: 0.2em;
}
.expandKeywordsBtn[aria-expanded="true"] .glyphicon:before {
/* Repeated same char as in the glyphicon-chevron-left class */
content: "\e079\e079";
}
.expandKeywordsBtn[aria-expanded="false"] .glyphicon:before {
/* Repeated same char as in the glyphicon-chevron-right class */
content: "\e080\e080";
}
div.bookmark p {
margin:1px;
}

@ -264,4 +264,25 @@ function statistics(offset, itemscount, itemsperpage, totalcount, localIndexCoun
}
}
/**
* Toggle visibility on a block of tags (keywords) beyond the initial limit of tags to display.
* @param {HTMLButtonElement} button the button used to expand the tags
* @param {String} moreTagsId the id of the container of tags which visibility has to be toggled
*/
function toggleMoreTags(button, moreTagsId) {
var moreTagsContainer = document.getElementById(moreTagsId);
if(button != null && moreTagsContainer != null) {
if(button.getAttribute("aria-expanded") == "true") {
/* Additionnaly we modify the aria-expanded state for improved accessiblity */
button.setAttribute("aria-expanded", "false");
button.title = "Show all";
moreTagsContainer.className = "hidden";
} else {
/* Additionnaly we modify the aria-expanded state for improved accessiblity */
button.setAttribute("aria-expanded", "true");
button.title = "Show only the first elements";
moreTagsContainer.className = "";
}
}
}

@ -25,7 +25,18 @@
</div>
<p class="snippet"><span class="snippetLoaded" id="h#[urlhash]#">#[description]#</span></p>
<p class="url"><a href="#[link]#" id="url#[urlhash]#" target="#[target]#" #(noreferrer)#::rel="noreferrer"#(/noreferrer)#>#[urlname]#</a></p>
#(showKeywords)#::<p class="tags">Tags: #{keywords}#<span class="tag label label-default"><a href="#[tagurl]#" style="color: inherit; text-decoration: inherit;">#[tagword]#</a></span> #{/keywords}#</p>#(/showKeywords)#
#(showKeywords)#::<p class="tags">Tags: #{keywords}#<span class="tag label label-default"><a href="#[tagurl]#" style="color: inherit; text-decoration: inherit;">#[tagword]#</a></span> #{/keywords}#
#(moreKeywords)#::<span id="moreKeywords#[urlhash]#" class="hidden">
#{keywords}#<span class="tag label label-default"><a href="#[tagurl]#" style="color: inherit; text-decoration: inherit;">#[tagword]#</a></span> #{/keywords}#
</span>
<button class="expandKeywordsBtn btn btn-default btn-xs" type="button"
aria-controls="moreKeywords#[urlhash]#" aria-expanded="false" title="Show all"
onclick="toggleMoreTags(this, 'moreKeywords#[urlhash]#')">
<span class="glyphicon"></span>
</button>
#(/moreKeywords)#
</p>
#(/showKeywords)#
<p class="urlinfo">
#(showDate)#::#[date]##(/showDate)#
#(showEvent)#::on #[date]##(/showEvent)#

@ -250,7 +250,8 @@ public class yacysearchitem {
prop.put("content_showEvent", showEvent ? 1 : 0);
Collection<File> snapshotPaths = sb.getConfigBool("search.result.show.snapshots", true) ? Transactions.findPaths(result.url(), null, State.ANY) : null;
if (fileType == FileType.HTML) { // html template specific settings
boolean showKeywords = (sb.getConfigBool("search.result.show.keywords", false) && !result.dc_subject().isEmpty());
boolean showKeywords = (sb.getConfigBool(SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS,
SwitchboardConstants.SEARCH_RESULT_SHOW_KEYWORDS_DEFAULT) && !result.dc_subject().isEmpty());
prop.put("content_showKeywords", showKeywords);
prop.put("content_showDate", sb.getConfigBool("search.result.show.date", true) && !showEvent ? 1 : 0);
prop.put("content_showSize", sb.getConfigBool("search.result.show.size", true) ? 1 : 0);
@ -267,13 +268,16 @@ public class yacysearchitem {
if (showEvent) prop.put("content_showEvent_date", GenericFormatter.RFC1123_SHORT_FORMATTER.format(events[0]));
if (showKeywords) { // tokenize keywords
StringTokenizer stoc = new StringTokenizer(result.dc_subject()," ");
final StringTokenizer stoc = new StringTokenizer(result.dc_subject()," ");
String rawNavQueryModifier;
Navigator navi = theSearch.navigatorPlugins.get("keywords");
boolean naviAvail = navi != null;
final int firstMaxKeywords = sb.getConfigInt(SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT,
SwitchboardConstants.SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT_DEFAULT);
int i = 0;
while (stoc.hasMoreTokens()) {
String word = stoc.nextToken();
while (stoc.hasMoreTokens()
&& i < firstMaxKeywords) {
final String word = stoc.nextToken();
prop.putHTML("content_showKeywords_keywords_" + i + "_tagword", word);
if (naviAvail) { // use query modifier if navigator available
rawNavQueryModifier = navi.getQueryModifier(word);
@ -285,6 +289,24 @@ public class yacysearchitem {
i++;
}
prop.put("content_showKeywords_keywords", i);
if(stoc.hasMoreTokens()) {
prop.put("content_showKeywords_moreKeywords", "1");
prop.put("content_showKeywords_moreKeywords_urlhash", urlhash);
i = 0;
while (stoc.hasMoreTokens()) {
final String word = stoc.nextToken();
prop.putHTML("content_showKeywords_moreKeywords_keywords_" + i + "_tagword", word);
if (naviAvail) { // use query modifier if navigator available
rawNavQueryModifier = navi.getQueryModifier(word);
} else { // otherwise just use the keyword as additional query word
rawNavQueryModifier = word;
}
prop.put("content_showKeywords_moreKeywords_keywords_" + i + "_tagurl", QueryParams.navurl(fileType, 0,
theSearch.query, rawNavQueryModifier, naviAvail, authenticated).toString());
i++;
}
prop.put("content_showKeywords_moreKeywords_keywords", i);
}
}
prop.put("content_showDate_date", GenericFormatter.RFC1123_SHORT_FORMATTER.format(result.moddate()));
prop.putHTML("content_showSize_sizename", RSSMessage.sizename(result.filesize()));

@ -571,6 +571,18 @@ public final class SwitchboardConstants {
/** Default setting value controlling whether the ranking score value should be displayed for each search result in the HTML results page */
public static final boolean SEARCH_RESULT_SHOW_RANKING_DEFAULT = false;
/** Key of the setting controlling whether a tags/keywords list should be displayed for each search result in the HTML results page */
public static final String SEARCH_RESULT_SHOW_KEYWORDS = "search.result.show.keywords";
/** Default setting value controlling whether the ranking score value should be displayed for each search result in the HTML results page */
public static final boolean SEARCH_RESULT_SHOW_KEYWORDS_DEFAULT = false;
/** Key of the setting controlling the maximum number of tags/keywords initially displayed for each search result in the HTML results page (the eventual remaining ones can then be expanded) */
public static final String SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT = "search.result.keywords.firstMaxCount";
/** Default setting value controlling the maximum number of tags/keywords initially displayed for each search result in the HTML results page (the eventual remaining ones can then be expanded) */
public static final int SEARCH_RESULT_KEYWORDS_FISRT_MAX_COUNT_DEFAULT = 100;
/**
* ranking+evaluation
*/

Loading…
Cancel
Save