You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
498 lines
18 KiB
498 lines
18 KiB
/*
|
|
* YaCy Portalsearch
|
|
*
|
|
* @author Stefan Förster (apfelmaennchen) <sof@gmx.de>
|
|
* @version 1.2
|
|
*
|
|
* Dual licensed under the MIT and GPL licenses:
|
|
* http://www.opensource.org/licenses/mit-license.php
|
|
* http://www.gnu.org/licenses/gpl.html
|
|
*
|
|
* Date: 10-Nov-2011
|
|
*
|
|
*/
|
|
|
|
var portalsearch = {
|
|
ynavigators: null,
|
|
ycurr: '',
|
|
startRecord: 0,
|
|
maximumRecords: 10,
|
|
submit: false,
|
|
load_status: 0,
|
|
loading: null,
|
|
fetchingResults: false
|
|
};
|
|
|
|
function statuscheck() {
|
|
if(portalsearch.load_status < 5) {
|
|
return;
|
|
} else {
|
|
window.clearInterval(portalsearch.loading);
|
|
yrun();
|
|
}
|
|
}
|
|
|
|
$(document).ready(function() {
|
|
portalsearch.ynavigators = new Array();
|
|
$.ajaxSetup({
|
|
timeout: 5000,
|
|
cache: true
|
|
});
|
|
// apply default properties
|
|
portalsearch.ycurr = '';
|
|
portalsearch.startRecord = 0;
|
|
portalsearch.maximumRecords = 10;
|
|
portalsearch.submit = false;
|
|
portalsearch.fetchingResults = false;
|
|
yconf = $.extend({
|
|
url : '',
|
|
'global' : false,
|
|
theme : 'start',
|
|
title : 'YaCy Search Widget',
|
|
logo : yconf.url + '/yacy/ui/img/yacy-logo.png',
|
|
link : 'http://yacy.net',
|
|
width : 640,
|
|
height : 640,
|
|
position : [150,50],
|
|
modal : false,
|
|
resizable: true,
|
|
show : '',
|
|
hide : '',
|
|
load_js : true,
|
|
load_css : true
|
|
}, yconf);
|
|
|
|
$('<div id="ypopup" class="classic"></div>').appendTo("#yacylivesearch");
|
|
|
|
if(yconf.load_css) {
|
|
var style1 = yconf.url + '/portalsearch/yacy-portalsearch.css';
|
|
var style2 = yconf.url + '/jquery/themes/'+yconf.theme+'/jquery-ui-1.8.16.custom.css';
|
|
var style3 = yconf.url + '/jquery/css/jquery-ui-combobox.css';
|
|
|
|
var head = document.getElementsByTagName('head')[0];
|
|
|
|
$(document.createElement('link'))
|
|
.attr({type:'text/css', href: style1, rel:'stylesheet', media:'screen'})
|
|
.appendTo(head);
|
|
$(document.createElement('link'))
|
|
.attr({type:'text/css', href: style2, rel:'stylesheet', media:'screen'})
|
|
.appendTo(head);
|
|
$(document.createElement('link'))
|
|
.attr({type:'text/css', href: style3, rel:'stylesheet', media:'screen'})
|
|
.appendTo(head);
|
|
}
|
|
|
|
portalsearch.load_status = 0;
|
|
portalsearch.loading = window.setInterval("statuscheck()", 200);
|
|
if(yconf.load_js) {
|
|
var script1 = yconf.url + '/jquery/js/jquery.query-2.1.7.js';
|
|
var script2 = yconf.url + '/jquery/js/jquery.form-2.73.js';
|
|
var script3 = yconf.url + '/jquery/js/jquery.field-0.9.2.min.js';
|
|
var script4 = yconf.url + '/jquery/js/jquery-ui-1.8.16.custom.min.js';
|
|
var script5 = yconf.url + '/jquery/js/jquery-ui-combobox.js';
|
|
|
|
$.getScript(script1, function(){ portalsearch.load_status++; });
|
|
$.getScript(script2, function(){ portalsearch.load_status++; });
|
|
$.getScript(script3, function(){ portalsearch.load_status++; });
|
|
$.getScript(script4, function(){ portalsearch.load_status++; });
|
|
$.getScript(script5, function(){ portalsearch.load_status++; });
|
|
} else {
|
|
yrun();
|
|
}
|
|
});
|
|
|
|
function yrun() {
|
|
portalsearch.maximumRecords = parseInt($("#ysearch input[name='maximumRecords']").getValue());
|
|
global = yconf.global;
|
|
|
|
$("#ypopup").dialog({
|
|
autoOpen: false,
|
|
height: yconf.height,
|
|
width: yconf.width,
|
|
minWidth: yconf.width,
|
|
position: yconf.position,
|
|
modal: yconf.modal,
|
|
resizable: yconf.resizable,
|
|
title: yconf.title,
|
|
show: yconf.show,
|
|
hide: yconf.hide,
|
|
drag: function(event, ui) {
|
|
var position = $("#ypopup").parent(".ui-dialog").position();
|
|
var left = $("#ypopup").parent(".ui-dialog").width()+5+position.left;
|
|
$("#yside").dialog('option', 'position', [left,position.top+32]);
|
|
},
|
|
dragStop: function(event, ui) {
|
|
var position = $("#ypopup").parent(".ui-dialog").position();
|
|
var left = $("#ypopup").parent(".ui-dialog").width()+5+position.left;
|
|
$("#yside").dialog('option', 'position', [left,position.top+32]);
|
|
},
|
|
resizeStop: function(event, ui) {
|
|
var position = $("#ypopup").parent(".ui-dialog").position();
|
|
var height = $("#ypopup").parent(".ui-dialog").height()-55;
|
|
var left = $("#ypopup").parent(".ui-dialog").width()+5+position.left;
|
|
$("#yside").dialog('option', 'height', height);
|
|
$("#yside").dialog('option', 'position', [left,position.top+32]);
|
|
},
|
|
close: function(event, ui) {
|
|
$("#yquery").setValue('');
|
|
$("#yside").dialog('destroy');
|
|
$('#yside').remove();
|
|
},
|
|
open: function(event, ui) {
|
|
$('<div id="yside" style="padding:0px;"></div>').insertAfter("#ypopup").parent(".ui-dialog-content");
|
|
var position = $("#ypopup").parent(".ui-dialog").position();
|
|
$("#yside").dialog({
|
|
title: 'Navigation',
|
|
autoOpen: false,
|
|
draggable: false,
|
|
resizable: false,
|
|
width: 220,
|
|
height: $("#ypopup").parent(".ui-dialog").height()-55,
|
|
minHeight: $("#ypopup").parent(".ui-dialog").height()-55,
|
|
show: 'slide',
|
|
hide: 'slide',
|
|
position : [position.left+$("#ypopup").parent(".ui-dialog").width()+5,position.top+32],
|
|
open: function(event, ui) {
|
|
$('div.ui-widget-shadow').remove();
|
|
$('#ypopup').dialog( 'moveToTop' );
|
|
}
|
|
});
|
|
$('.ui-widget-shadow').remove();
|
|
$('div[aria-labelledby="ui-dialog-title-yside"] div.ui-dialog-titlebar').remove();
|
|
|
|
$("#ypopup").bind("scroll", function(e){
|
|
p1 = $("#ypopup h3 :last").position().top;
|
|
if(p1-$("#ypopup").dialog( "option", "height" ) < 0 && !portalsearch.fetchingResults) {
|
|
portalsearch.startRecord = portalsearch.startRecord + portalsearch.maximumRecords;
|
|
yacysearch(false);
|
|
}
|
|
});
|
|
|
|
|
|
}
|
|
});
|
|
|
|
$('#ysearch').keyup(function(e) { // React to keyboard input
|
|
|
|
if(e.which == 27) { // Close popup on ESC
|
|
$("#ypopup").dialog('close');
|
|
$("#yquery").setValue("");
|
|
}
|
|
|
|
if(e.which == 18) { // Global search on ALT
|
|
global = true;
|
|
ycurr = $("#yquery").getValue();
|
|
yacysearch(true);
|
|
}
|
|
|
|
if(portalsearch.ycurr == $("#yquery").getValue()) { // Do nothing if search term hasn't changed
|
|
return false;
|
|
}
|
|
|
|
global = yconf.global; // As this is a new search, revert to default resource
|
|
|
|
if ($("#yquery").getValue() == '') { // If search term is empty reset to default resource and close popup
|
|
if($("#ypopup").dialog('isOpen'))
|
|
$("#ypopup").dialog('close');
|
|
} else { // Else fire up a search request and remeber the current search term
|
|
portalsearch.ycurr = $("#yquery").getValue();
|
|
debouncedYacysearch(true);
|
|
}
|
|
return false;
|
|
});
|
|
|
|
$('#ysearch').submit(function() { // Submit a search request
|
|
portalsearch.ycurr = $("#yquery").getValue();
|
|
|
|
if (!$("#ypopup").dialog('isOpen'))
|
|
$("#ypopup").dialog('open');
|
|
else
|
|
if ($("#yside").dialog('isOpen'))
|
|
$("#yside").dialog('close');
|
|
|
|
$("#yquery").focus();
|
|
|
|
yacysearch(true);
|
|
return false;
|
|
});
|
|
}
|
|
|
|
var suggestTimeoutId = null;
|
|
|
|
/**
|
|
* Debounce wrapper to limit the rate of calls to the backend search service.
|
|
* @param clear when true, clear the results popup
|
|
*/
|
|
function debouncedYacysearch(clear) {
|
|
if(suggestTimeoutId != null) {
|
|
/* Remove delayed call not yet done */
|
|
clearTimeout(suggestTimeoutId);
|
|
}
|
|
|
|
/* Limit the rate of calls to the search API by adding a delay before effective call */
|
|
suggestTimeoutId = setTimeout(function() {
|
|
yacysearch(clear);
|
|
}, 400);
|
|
}
|
|
|
|
function yacysearch(clear) {
|
|
var url = yconf.url + '/yacysearch.json?callback=?' // JSONP (cross domain) request URL
|
|
//var url = yconf.url + '/solr/select?wt=yjson&callback=?' // JSONP (cross domain) request URL
|
|
|
|
if(clear) {
|
|
$('#ypopup').empty();
|
|
var loading = "<div class='yloading'><h3 class='linktitle'><em>Loading: "+yconf.url+"</em><br/>";
|
|
var loadimg = "<img src='"+yconf.url+"/yacy/ui/img/loading2.gif' align='absmiddle'/></h3></div>";
|
|
$('#ypopup').append(loading+loadimg);
|
|
|
|
if (!$("#ypopup").dialog('isOpen'))
|
|
$("#ypopup").dialog('open');
|
|
else
|
|
if ($("#yside").dialog('isOpen'))
|
|
$("#yside").dialog('close');
|
|
|
|
$("#yquery").focus();
|
|
}
|
|
|
|
var param = []; // Generate search request parameters from HTML form
|
|
$("#ysearch input").each(function(i){
|
|
var item = { name : $(this).attr('name'), value : $(this).attr('value') };
|
|
if(item.name == 'resource') { // Set parameter for resource according to global
|
|
if(global)
|
|
item.value = 'global';
|
|
else {
|
|
item.value = 'local'
|
|
}
|
|
}
|
|
if(item.name == 'query' || item.name == 'search') {
|
|
item.value = $.trim(item.value); // remove heading and trailing white spaces from querey
|
|
if(item.value != portalsearch.ycurr) // in case of fast typing ycurr needs to be updated
|
|
portalsearch.ycurr = item.value;
|
|
}
|
|
param[i] = item;
|
|
});
|
|
param[param.length] = { name : 'startRecord', value : portalsearch.startRecord };
|
|
portalsearch.ycurr = portalsearch.ycurr.replace("<"," ").replace(">"," ");
|
|
|
|
$.ajaxSetup({
|
|
timeout: 10000,
|
|
error: function(x,e,ex) {
|
|
portalsearch.fetchingResults = false;
|
|
var err = 'Unknow Error: '+x.responseText;
|
|
if(x.status==0) {
|
|
err = 'Unknown Network Error! I try to reload...';
|
|
yacysearch(true);
|
|
} else if(x.status==404) {
|
|
err = x.status + ' - Requested URL not found.';
|
|
} else if(x.status==500) {
|
|
err = x.status + ' - Internel Server Error.';
|
|
} else if(e=='parsererror') {
|
|
err = 'Parsing JSON Request failed:' + ex;
|
|
} else if(e=='timeout') {
|
|
err = 'Request Time out.';
|
|
};
|
|
if (clear) $('#ypopup').empty();
|
|
var favicon = "<img src='"+yconf.url+"/yacy/ui/img-2/stop.png' class='favicon'/>";
|
|
var title = "<h3 class='linktitle'>"+favicon+" "+err+"</h3>";
|
|
var url = "<p class='url'><a href=''>Current search terms: "+portalsearch.ycurr+"</a></p>"
|
|
$(title+url).appendTo("#ypopup");
|
|
}
|
|
});
|
|
|
|
portalsearch.fetchingResults = true;
|
|
$.getJSON(url, param,
|
|
function(json, status) {
|
|
portalsearch.fetchingResults = false;
|
|
if (json[0]) data = json[0];
|
|
else data = json;
|
|
|
|
var searchTerms = "";
|
|
searchTerms = data.channels[0].searchTerms.replace("<"," ").replace(">"," ");;
|
|
|
|
if($.trim(portalsearch.ycurr.replace(/ /g,"+")) != searchTerms) {
|
|
return false;
|
|
}
|
|
if(clear) {
|
|
$('#ypopup').empty();
|
|
}
|
|
|
|
var total = data.channels[0].totalResults;
|
|
|
|
if(global) var result = 'global';
|
|
else var result = 'local';
|
|
|
|
var count = 0;
|
|
$.each (
|
|
data.channels[0].items,
|
|
function(i,item) {
|
|
if (item) {
|
|
var favicon = "<img src='" + yconf.url + "/" +item.faviconUrl+"' class='favicon'/>";
|
|
var title = "<h3 class='linktitle'>"+favicon+"<a href='"+item.link+"' target='_blank'>"+item.title+"</a></h3>";
|
|
var url = "<p class='url'><a href='"+item.link+"' target='_blank'>"+item.link+"</a></p>"
|
|
var desc = "<p class='desc'>"+item.description+"</p>";
|
|
var date = "<p class='date'>"+item.pubDate.substring(0,16);
|
|
var size = " | "+item.sizename+"</p>";
|
|
$(title+desc+url+date+size).appendTo("#ypopup");
|
|
}
|
|
count++;
|
|
}
|
|
);
|
|
|
|
if(count == 0) {
|
|
if (clear) $('#ypopup').empty();
|
|
var favicon = "<img src='"+yconf.url+"/yacy/ui/img-2/stop.png' class='favicon'/>";
|
|
var title = "<h3 class='linktitle'>"+favicon+"No search results!</h3>";
|
|
var url = "<p class='url'><a href=''>Current search terms: "+searchTerms+"</a></p>"
|
|
var desc = "<p class='desc'>You could restate your search, release some navigators or switch to global search...</p>";
|
|
$(title+desc+url).appendTo("#ypopup");
|
|
}
|
|
|
|
if(clear) {
|
|
$('#yside').empty();
|
|
|
|
var ylogo = "<a href='"+yconf.link+"' target='_blank'><img style='padding-left: 24px;' src='"+yconf.logo+"' alt='"+yconf.logo+"' title='"+yconf.logo+"' /></a>";
|
|
var ymsg= "Total "+result+" results: "+total;
|
|
$("<div class='ymsg'><table><tr><td width='55px'>"+ylogo+"</td><td id='yresult'>"+ymsg+"</td></tr></div").appendTo('#yside');
|
|
$('<hr />').appendTo("#yside");
|
|
|
|
var selected = 'selected="selected">';
|
|
var select1 = '<select class="selector" id="yglobal"><option value="local"';
|
|
var select2 = 'local</option><option value="global"';
|
|
var select3 = 'global</option></select>';
|
|
|
|
if(global) {
|
|
select = select1 + '>' + select2 + selected + select3;
|
|
} else {
|
|
select = select1 + selected + select2 + '>' + select3;
|
|
}
|
|
|
|
$('<div class="ui-widget ynav"><label for="yglobal">Get local/global results:</label><br />'+select+'</div>').appendTo('#yside');
|
|
$("#yglobal").combobox({
|
|
selected: function(event, ui) {
|
|
if(ui.item.value == "global") {
|
|
global = true;
|
|
} else {
|
|
global = false;
|
|
}
|
|
yacysearch(true);
|
|
}
|
|
});
|
|
|
|
select1 = '<select class="selector" id="yrecent"><option value="relevance"';
|
|
select2 = 'Relevance</option><option value="date"';
|
|
select3 = 'Date</option></select>';
|
|
|
|
var query = unescape($("#yquery").getValue());
|
|
if(query.indexOf("/date") != -1) {
|
|
select = select1 + '>' + select2 + selected + select3;
|
|
} else {
|
|
select = select1 + selected + select2 + '>' + select3;
|
|
}
|
|
$('<div class="ui-widget ynav"><label for="yrecent">Sort result by:</label><br />'+select+'</div>').appendTo('#yside');
|
|
$("#yrecent").combobox({
|
|
selected: function(event, ui) {
|
|
if(ui.item.value == "date") {
|
|
query = query + " /date";
|
|
} else {
|
|
query = query.replace(/\s\/date/g,"");
|
|
}
|
|
$("#yquery").setValue($.trim(query));
|
|
$("#yquery").trigger('keyup');
|
|
}
|
|
});
|
|
|
|
$('<hr />').appendTo("#yside");
|
|
$("<p class='ytxt'>You can narrow down your search by selecting one of the below navigators:</p>").appendTo('#yside');
|
|
|
|
/*
|
|
var label = '<label for="ylang">Language:</label><br />';
|
|
var select = '<select class="selector" id="ylang"><option value="">Select one...</option><option value="en" >en-English</option><option value="fr" >fr-French</option><option value="es" >es-Spanish</option><option value="de" >de-German</option><option value="zh" >zh-Chinese</option></select>';
|
|
$('<div class="ui-widget ynav">'+label+select+'</div>').appendTo('#yside');
|
|
$("#ylang").combobox({
|
|
selected: function(event, ui) {
|
|
var query = unescape($("#yquery").getValue() + " /language/" +ui.item.value);
|
|
$("#yquery").setValue(query);
|
|
portalsearch.ynavigators.push("/language/"+ui.item.value);
|
|
$("#yquery").trigger('keyup');
|
|
}
|
|
});
|
|
*/
|
|
|
|
$.each ( // Loop through all available navigators and include comboboxes in sidebar
|
|
data.channels[0].navigation,
|
|
function(i,facet) {
|
|
if (facet) {
|
|
var id = "#y"+facet.facetname;
|
|
var label = '<label for="y' +facet.facetname+ '">' +facet.displayname+ ': </label><br />';
|
|
var select = '<select id="y' +facet.facetname+ '"><option value="">Select one...</option></select>';
|
|
$('<div class="ui-widget ynav">'+label+select+'</div>').appendTo('#yside');
|
|
$.each (
|
|
facet.elements,
|
|
function(j,element) {
|
|
var mod = '<option value="'+element.modifier +'">'+element.name+ ' (' +element.count+ ')</option>';
|
|
$(mod).appendTo(id);
|
|
}
|
|
)
|
|
$(id).combobox({
|
|
selected: function(event, ui) {
|
|
var query = unescape($("#yquery").getValue() + " " +ui.item.value);
|
|
$("#yquery").setValue(query);
|
|
portalsearch.ynavigators.push(ui.item.value);
|
|
$("#yquery").trigger('submit');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
);
|
|
|
|
$('<hr />').appendTo("#yside");
|
|
if(portalsearch.ynavigators.length > 0) {
|
|
$("<p class='ytxt'>Uncheck to release navigators:</p>").appendTo('#yside');
|
|
}
|
|
|
|
cancelNavigators(portalsearch.ynavigators, "#yside");
|
|
|
|
if($("#ypopup .yloading").length == 0) {
|
|
$(".ynav-cancel").bind("change", function(event) {
|
|
var query = $("#yquery").getValue();
|
|
var str = $(event.target).val();
|
|
var idx = portalsearch.ynavigators.indexOf($.trim(str));
|
|
if(idx!=-1) portalsearch.ynavigators.splice(idx, 1);
|
|
var regexp = new RegExp(' '+str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")); // properly escape string for regexp
|
|
$("#yquery").setValue($.trim(query.replace(regexp,"")));
|
|
portalsearch.startRecord = 0;
|
|
$("#yquery").trigger('submit');
|
|
});
|
|
autoOpenSidebar();
|
|
if ($("#ypopup").dialog('isOpen')) {
|
|
// If you got maximumRecords results, but still have display space, load more results
|
|
if($("#ypopup h3 :last").position().top < $("#ypopup").dialog( "option", "height" ) && count == portalsearch.maximumRecords) {
|
|
portalsearch.startRecord = portalsearch.startRecord + portalsearch.maximumRecords;
|
|
yacysearch(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
function autoOpenSidebar() {
|
|
window.setTimeout(function() { // The delay prevents the sidebar to open on every intermediate search results
|
|
if($("#ypopup .yloading").length == 0) { // Check again wether a search result is still loading
|
|
if( $("#yquery").getValue() == portalsearch.ycurr) { // Open side bar only if result matches current search term
|
|
$("#yside").dialog('open');
|
|
$("#yquery").focus();
|
|
}
|
|
}
|
|
} , 1000);
|
|
}
|
|
function cancelNavigators(ynavigators, appendTo) { // Include checkboxes to release navigators
|
|
var arLen=ynavigators.length;
|
|
var query = $("#yquery").getValue();
|
|
for ( var i=0, len=arLen; i<len; ++i ){
|
|
if(query.indexOf(ynavigators[i]) != -1) // Check wether search term still contains the navigator
|
|
$(' <input type="checkbox" checked="checked" class="ynav-cancel" name="ynav'+i+'" value="'+ynavigators[i]+'"><span class="ytxt">'+ynavigators[i]+'</span><br>').appendTo(appendTo);
|
|
else
|
|
ynavigators.splice(i, 1); // Remove navigator from array as it has been removed manually from search term
|
|
}
|
|
}
|
|
} |