app.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. $(document).ready(function() {
  2. 'use strict';
  3. var translate = navigator.mozL10n.get;
  4. var searchstring = "";
  5. var activepage = "home";
  6. var searchreq = null;
  7. var searchscope = "general";
  8. var searchpage = 1;
  9. var scrollup = false;
  10. $.ajaxSetup({xhr:function() {return new XMLHttpRequest({mozSystem:true})}});
  11. function showError(text) {
  12. $("#error").text(text);
  13. $("meta[name='theme-color']").attr("content","#323232");
  14. setTimeout(function() {
  15. $("#error_holder").slideDown();
  16. },500);
  17. setTimeout(function() {
  18. $("#error_holder").slideUp(function() {
  19. $("meta[name='theme-color']").attr("content","#3faa7e");
  20. });
  21. },5000);
  22. }
  23. $("#searchform").submit(function(e) {
  24. e.preventDefault();
  25. var term = $("#term").val();
  26. if(term.length > 0) {
  27. $("#term").blur();
  28. $("#searchform").hide();
  29. $(".searx_logo").hide();
  30. $("#autocomplete").hide();
  31. $("#softkey-center").text("");
  32. $("#softkey-left").text("");
  33. $("#results").hide();
  34. $("#no_results").hide();
  35. $(".loading").show();
  36. $("#pagetitle").text($("#term").val()+" - Searx");
  37. activepage = "loading";
  38. if(searchreq && searchreq.readyState != 4) searchreq.abort();
  39. searchreq = $.ajax('https://'+srxsettings.instances.find(function(data) {return data.active}).url+'/search?format=json&safesearch='+srxsettings.safesearch+'&language='+srxsettings.language+'&categories='+searchscope+'&engines='+srxsettings.engines[searchscope].join(',')+'&pageno='+searchpage+'&q='+encodeURIComponent(term)).done(function(response) {
  40. if(response.length == 0) {
  41. showError(translate('searching_error'));
  42. return;
  43. }
  44. var searchres = response.results;
  45. if(searchres.length === 0) {
  46. if(searchpage == 1) {
  47. $(".loading").hide();
  48. $("#no_results").show();
  49. }
  50. else {
  51. $(".loading").hide();
  52. showError(translate("no_more_pages_available"));
  53. $("#results").show();
  54. }
  55. }
  56. else {
  57. activepage = "results";
  58. $("#result_list").empty();
  59. searchres.forEach(function(doc,i) {
  60. if(searchscope == "images") {
  61. if(doc.thumbnail_src.substr(0,2) == "//") doc.thumbnail_src = "https:"+doc.thumbnail_src;
  62. var result = $("<li>").addClass("navigable").addClass("image_result")
  63. .append($("<div>").addClass("kui-list-cont").css("background-image","url("+doc.thumbnail_src+")"))
  64. .keyup(function(e) {
  65. if(e.keyCode == 0 && e.originalEvent.key == "SoftLeft") {
  66. $("#results").hide();
  67. $(".loading").show();
  68. if(doc.img_src.substr(0,2) == "//") doc.img_src = "https:"+doc.img_src;
  69. var xhr = new XMLHttpRequest({mozSystem:true});
  70. xhr.open('GET',doc.img_src,true);
  71. xhr.responseType = 'blob';
  72. xhr.onload = function(e) {
  73. if(this.status == 200) {
  74. var blob = this.response;
  75. var dataurl = window.URL.createObjectURL(blob);
  76. var random = Math.round(Math.random()*100000);
  77. $(document.body).append($("<a>").attr("id",random).attr("download","").attr("href",dataurl));
  78. $("#"+random)[0].click();
  79. $("#"+random).remove();
  80. $(".loading").hide();
  81. $("#results").show();
  82. }
  83. };
  84. xhr.send();
  85. }
  86. });
  87. }
  88. else {
  89. var result = $("<li>").addClass("navigable")
  90. .append($("<div>").addClass("kui-list-cont")
  91. .append($("<p>").addClass("kui-pri").text(doc.title))
  92. .append($("<p>").addClass("kui-thi").addClass("result_url").text(doc.url))
  93. .append($("<p>").addClass("kui-sec").text(doc.content)));
  94. }
  95. result.keyup(function(e) {
  96. if(e.keyCode == 13) {
  97. $("meta[name='theme-color']").attr("content","#320374");
  98. window.open(doc.url,"overlay");
  99. }
  100. });
  101. result.keydown(function(e) {
  102. if(searchpage > 1 && i == 0 && e.keyCode == 38) {
  103. searchpage--;
  104. scrollup = true;
  105. $("#searchform").submit();
  106. }
  107. else if(i != 0 && e.keyCode == 38) $("#result_list li").eq(i-1).focus();
  108. else if(i+1 == searchres.length && e.keyCode == 40) {
  109. searchpage++;
  110. $("#searchform").submit();
  111. }
  112. else if(e.keyCode == 40) $("#result_list li").eq(i+1).focus();
  113. });
  114. $("#result_list").append(result);
  115. });
  116. $("#searchpage").text(searchpage);
  117. $(".loading").hide();
  118. $("#results").show();
  119. $("#softkey-center").text(translate("visit"));
  120. if(searchscope == "images") $("#softkey-left").text(translate("download"));
  121. else $("#softkey-left").text("");
  122. naviBoard.destroyCurrentNavigationView();
  123. naviBoard.setNavigation("result_list");
  124. setTimeout(function() {
  125. if(scrollup) $("#result_list li").eq(searchres.length-1).focus();
  126. else $("#result_list li").eq(0).focus();
  127. scrollup = false;
  128. },0);
  129. }
  130. }).fail(function(data,status,error) {
  131. if(!error) {
  132. error = translate('searching_error');
  133. }
  134. if(error != "abort") showError(error);
  135. });
  136. }
  137. });
  138. $("#term").focus();
  139. $("#term").on("input",function(e) {
  140. if($(this).val().length > 0 && srxsettings.autocomplete != "off") {
  141. activepage = "typing";
  142. $(".searx_logo").hide();
  143. if($("#term").val() != searchstring) {
  144. searchstring = $("#term").val();
  145. $.ajax("https://"+srxsettings.instances.find(function(data) {return data.active}).url+"/autocompleter?autocomplete="+srxsettings.autocomplete+"&language="+srxsettings.language+"&q="+encodeURIComponent($("#term").val())).done(function(data) {
  146. if(activepage == "typing") {
  147. $("#autocomplete_list").empty();
  148. if(data.length > 0) {
  149. data.forEach(function(doc) {
  150. if(doc.length > 0) {
  151. $("#autocomplete_list").append($("<li>").addClass("navigable")
  152. .append($("<div>").addClass("kui-list-cont")
  153. .append($("<p>").addClass("kui-pri").text(doc)))
  154. .keyup(function(e) {
  155. if(e.keyCode == 13) {
  156. $("#term").val(doc);
  157. $("#searchform").submit();
  158. }
  159. }));
  160. }
  161. });
  162. naviBoard.destroyCurrentNavigationView();
  163. naviBoard.setNavigation("autocomplete_nav");
  164. $("#autocomplete").show();
  165. }
  166. else {
  167. naviBoard.destroyCurrentNavigationView();
  168. $("#term").focus();
  169. $("#autocomplete").hide();
  170. }
  171. }
  172. });
  173. }
  174. }
  175. else {
  176. activepage = "home";
  177. naviBoard.destroyCurrentNavigationView();
  178. $("#term").focus();
  179. $("#autocomplete").hide();
  180. $(".searx_logo").show();
  181. }
  182. });
  183. $("#settings .navigable").eq(0).focus(function() {
  184. $("#settings").scrollTop(0);
  185. });
  186. $(document).keydown(function(e) {
  187. if(e.keyCode == 38 || e.keyCode == 40) {
  188. e.preventDefault();
  189. }
  190. if(e.keyCode == 8 && activepage == "settings_option") {
  191. e.preventDefault();
  192. activepage = "settings";
  193. $("#settings_option").hide();
  194. $("#softkey-left").text("");
  195. $("#softkey-right").text("");
  196. $("#cur_instance").text(srxsettings.instances.find(function(data) {return data.active}).name);
  197. $("#cur_language").text(srxdata.language.find(function(data) {if(data.value == this) return true},srxsettings.language).name);
  198. $("#cur_autocomplete").text(srxdata.autocomplete.find(function(data) {if(data.value == this) return true},srxsettings.autocomplete).name);
  199. $("#cur_safesearch").text(srxdata.safesearch.find(function(data) {if(data.value == this) return true},srxsettings.safesearch).name);
  200. $(".set_engines").each(function() {
  201. var set_scope = $(this).data("scope");
  202. var engine_list = new Array;
  203. for(var i=0;i<srxsettings.engines[set_scope].length;i++) {
  204. engine_list.push(srxdata.engines[set_scope].find(function(data) {if(data.value == this) return true},srxsettings.engines[set_scope][i]).name);
  205. }
  206. $(this).find(".cur_engines").text(engine_list.join(", "));
  207. });
  208. $("#settings").show();
  209. naviBoard.destroyCurrentNavigationView();
  210. naviBoard.setNavigation("settings");
  211. }
  212. else if(e.keyCode == 8 && activepage == "settings_instance") {
  213. e.preventDefault();
  214. $("#settings_instance").hide();
  215. $("#set_instance").trigger($.Event("keyup",{keyCode:13}));
  216. }
  217. else if(e.keyCode == 8 && activepage == "loading_test") {
  218. e.preventDefault();
  219. if(searchreq && searchreq.readyState != 4) searchreq.abort();
  220. $(".loading").hide();
  221. $("#softkey-center").text(translate("save"));
  222. $("#settings_instance").show();
  223. }
  224. else if(e.keyCode == 8 && activepage != "home") {
  225. e.preventDefault();
  226. if(searchreq && searchreq.readyState != 4) searchreq.abort();
  227. $("#results").hide();
  228. $("#autocomplete").hide();
  229. $(".loading").hide();
  230. $("#settings").hide();
  231. $("#no_results").hide();
  232. $("#term").val("");
  233. $("#softkey-center").text(translate("search"));
  234. $("#softkey-left").text("");
  235. $("#searchform").show();
  236. $(".searx_logo").show();
  237. $("#tabs").show();
  238. $("#softkey-right").text(translate("settings"));
  239. $("#pagetitle").text("Searx");
  240. $("#term").focus();
  241. naviBoard.destroyCurrentNavigationView();
  242. searchpage = 1;
  243. activepage = "home";
  244. }
  245. if((e.keyCode == 37 || e.keyCode == 39) && (!$("#term").is(":focus") || $("#term").val().length == 0) && $("#tabs").is(":visible")) {
  246. if(e.keyCode == 37) {
  247. if($("#tabs li").index($("#tabs li.active")) == 0) var newid = $("#tabs li").length-1;
  248. else var newid = $("#tabs li").index($("#tabs li.active"))-1;
  249. }
  250. else {
  251. if($("#tabs li").index($("#tabs li.active")) == $("#tabs li").length-1) var newid = 0;
  252. else var newid = $("#tabs li").index($("#tabs li.active"))+1;
  253. }
  254. var tabwidth = 0;
  255. for(var i=0;i<newid;i++) {
  256. tabwidth = tabwidth+$("#tabs li").eq(i).outerWidth()+4;
  257. }
  258. tabwidth = tabwidth-(($(window).width()-$("#tabs li").eq(newid).width())/2)+10;
  259. searchscope = $("#tabs li").eq(newid).data("scope");
  260. $("#tabs li.active").removeClass("active");
  261. $("#tabs").scrollLeft(tabwidth);
  262. $("#tabs li").eq(newid).addClass("active");
  263. if(activepage == "results" || activepage == "loading") {
  264. searchpage = 1;
  265. $("#searchform").submit();
  266. }
  267. }
  268. if(activepage != "settings" && activepage != "settings_option" && activepage != "settings_instance" && activepage != "loading_test" && e.keyCode == 0 && e.originalEvent.key == "SoftRight") {
  269. activepage = "settings";
  270. $("#tabs").hide();
  271. $(".searx_logo").hide();
  272. $("#searchform").hide()
  273. $("#autocomplete").hide();
  274. $("#results").hide();
  275. $(".loading").hide();
  276. $("#no_results").hide();
  277. $("#softkey-right").text("");
  278. $("#softkey-left").text("");
  279. $("#softkey-center").text(translate("select"));
  280. $("#pagetitle").text(translate("settings")+" - Searx");
  281. $("#cur_instance").text(srxsettings.instances.find(function(data) {return data.active}).name);
  282. $("#cur_language").text(srxdata.language.find(function(data) {if(data.value == this) return true},srxsettings.language).name);
  283. $("#cur_autocomplete").text(srxdata.autocomplete.find(function(data) {if(data.value == this) return true},srxsettings.autocomplete).name);
  284. $("#cur_safesearch").text(srxdata.safesearch.find(function(data) {if(data.value == this) return true},srxsettings.safesearch).name);
  285. $(".set_engines").each(function() {
  286. var set_scope = $(this).data("scope");
  287. var engine_list = new Array;
  288. for(var i=0;i<srxsettings.engines[set_scope].length;i++) {
  289. engine_list.push(srxdata.engines[set_scope].find(function(data) {if(data.value == this) return true},srxsettings.engines[set_scope][i]).name);
  290. }
  291. $(this).find(".cur_engines").text(engine_list.join(", "));
  292. });
  293. $("#settings").show();
  294. naviBoard.destroyCurrentNavigationView();
  295. naviBoard.setNavigation("settings");
  296. }
  297. });
  298. $("#set_instance").keyup(function(e) {
  299. if(e.keyCode == 13) {
  300. activepage = "settings_option";
  301. $("#settings").hide();
  302. $("#settings_option_list").empty();
  303. $("#settings_option_header").text(translate("searx_instance"));
  304. for(var i=0;i<srxsettings.instances.length;i++) {
  305. (function(index) {
  306. $("#settings_option_list").append($("<li>").addClass("navigable").addClass("instance_sel")
  307. .append($("<div>").addClass("kui-list-cont")
  308. .append($("<p>").addClass("kui-pri")
  309. .append($("<input>").addClass("kui-radio").attr("type","radio").attr("id","instance_"+srxsettings.instances[i].url.replace(/./g,"_")))
  310. .append($("<label>").attr("for","instance_"+srxsettings.instances[i].url.replace(/./g,"_")).text(srxsettings.instances[i].name)))
  311. .append($("<p>").addClass("kui-sec").text(srxsettings.instances[i].url))).keyup(function(e) {
  312. if(e.keyCode == 13) {
  313. for(var x=0;x<srxsettings.instances.length;x++) {
  314. srxsettings.instances[x].active = false;
  315. }
  316. srxsettings.instances[index].active = true;
  317. localStorage.setItem("instances",JSON.stringify(srxsettings.instances));
  318. $("#settings_option_list input").removeAttr("checked");
  319. $("#instance_"+srxsettings.instances[index].url.replace(/./g,"_")).attr("checked","checked");
  320. }
  321. else if(e.keyCode == 0 && e.originalEvent.key == "SoftLeft") {
  322. activepage = "settings_instance";
  323. $("#settings_option").hide();
  324. $("#softkey-left").text("");
  325. $("#softkey-right").text("");
  326. $("#softkey-center").text(translate("save"));
  327. $("#settings_instance").show();
  328. naviBoard.destroyCurrentNavigationView();
  329. naviBoard.setNavigation("settings_instance");
  330. }
  331. else if(e.keyCode == 0 && e.originalEvent.key == "SoftRight") {
  332. if(srxsettings.instances[index].active == true) showError(translate("you_can_not_delete_the_searx_instance_you_are_currently_using"));
  333. else {
  334. srxsettings.instances.splice(index,1);
  335. localStorage.instances = JSON.stringify(srxsettings.instances);
  336. $("#set_instance").trigger($.Event("keyup",{keyCode:13}));
  337. }
  338. }
  339. }));
  340. if(srxsettings.instances[i].active == true) $("#instance_"+srxsettings.instances[i].url.replace(/./g,"_")).attr("checked","checked");
  341. })(i);
  342. }
  343. $("#settings_option").show();
  344. $("#softkey-left").text(translate("add"));
  345. $("#softkey-right").text(translate("delete"));
  346. naviBoard.destroyCurrentNavigationView();
  347. naviBoard.setNavigation("settings_option_list");
  348. }
  349. });
  350. $("#set_language").keyup(function(e) {
  351. if(e.keyCode == 13) {
  352. settings_radio("language","search_language");
  353. }
  354. });
  355. $("#set_autocomplete").keyup(function(e) {
  356. if(e.keyCode == 13) {
  357. settings_radio("autocomplete","autocomplete");
  358. }
  359. });
  360. $("#set_safesearch").keyup(function(e) {
  361. if(e.keyCode == 13) {
  362. settings_radio("safesearch","safe_search");
  363. }
  364. });
  365. $(".set_engines").keyup(function(e) {
  366. if(e.keyCode == 13) {
  367. activepage = "settings_option";
  368. var set_scope = $(this).data("scope");
  369. $("#settings").hide();
  370. $("#settings_option_list").empty();
  371. $("#settings_option_header").text(translate("search_engines")+": "+$(this).find(".kui-pri").text());
  372. for(var i=0;i<srxdata.engines[set_scope].length;i++) {
  373. (function(index) {
  374. $("#settings_option_list").append($("<li>").addClass("navigable").addClass("large")
  375. .append($("<div>").addClass("kui-list-cont")
  376. .append($("<p>").addClass("kui-pri")
  377. .append($("<input>").addClass("kui-checkbox").attr("type","checkbox").attr("id","engines_"+srxdata.engines[set_scope][i].value.replace(/\+/g,"_")))
  378. .append($("<label>").attr("for","engines_"+srxdata.engines[set_scope][i].value.replace(/\+/g,"_")).text(srxdata.engines[set_scope][i].name)))).keyup(function(e) {
  379. if(e.keyCode == 13) {
  380. var set_engine = srxdata.engines[set_scope][index].value;
  381. if(srxsettings.engines[set_scope].indexOf(set_engine) == -1) {
  382. srxsettings.engines[set_scope].push(set_engine);
  383. $("#engines_"+set_engine.replace(/\+/g,"_")).attr("checked","checked");
  384. }
  385. else {
  386. srxsettings.engines[set_scope].splice(srxsettings.engines[set_scope].indexOf(set_engine),1);
  387. $("#engines_"+set_engine.replace(/\+/g,"_")).removeAttr("checked");
  388. }
  389. localStorage.setItem("engines_"+set_scope,JSON.stringify(srxsettings.engines[set_scope]));
  390. }
  391. }));
  392. if(srxsettings.engines[set_scope].indexOf(srxdata.engines[set_scope][i].value) != -1) $("#engines_"+srxdata.engines[set_scope][i].value.replace(/\+/g,"_")).attr("checked","checked");
  393. })(i);
  394. }
  395. $("#settings_option").show();
  396. naviBoard.destroyCurrentNavigationView();
  397. naviBoard.setNavigation("settings_option_list");
  398. }
  399. });
  400. $("#set_about_searx").keyup(function(e) {
  401. if(e.keyCode == 13) {
  402. $("meta[name='theme-color']").attr("content","#320374");
  403. window.open("https://github.com/asciimoo/searx/blob/master/README.rst","overlay");
  404. }
  405. });
  406. $("#set_about_app").keyup(function(e) {
  407. if(e.keyCode == 13) {
  408. $("meta[name='theme-color']").attr("content","#320374");
  409. window.open("https://notabug.org/kaitools/searx/src/master/README.md","overlay");
  410. }
  411. });
  412. $("#set_license").keyup(function(e) {
  413. if(e.keyCode == 13) {
  414. $("meta[name='theme-color']").attr("content","#320374");
  415. window.open("https://notabug.org/kaitools/searx/src/master/LICENSE","overlay");
  416. }
  417. });
  418. $(document).focus(function() {
  419. $("meta[name='theme-color']").attr("content","#3faa7e");
  420. });
  421. $("#settings_instance .kui-input").focus(function(e) {
  422. $(e.target).closest(".kui-input-holder").addClass("kui-focus-within");
  423. });
  424. $("#settings_instance .kui-input").blur(function(e) {
  425. $(e.target).closest(".kui-input-holder").removeClass("kui-focus-within");
  426. });
  427. $("#settings_instance").keyup(function(e) {
  428. if(e.keyCode == 13) {
  429. if($("#instance_name").val().length > 0 && $("#instance_url").val().length > 0) {
  430. activepage = "loading_test";
  431. $("#settings_instance").hide();
  432. $("#softkey-center").text("");
  433. $(".loading").show();
  434. searchreq = $.ajax("https://"+$("#instance_url").val()+"/search?format=json&q=test").done(function(data) {
  435. $(".loading").hide();
  436. if(data.length == 0 || !data.results || data.results.length == 0) {
  437. $("#softkey-center").text(translate("save"));
  438. $("#settings_instance").show();
  439. showError(translate("this_instance_does_not_work"));
  440. }
  441. else {
  442. var add_instance = new Object();
  443. add_instance.name = $("#instance_name").val();
  444. add_instance.url = $("#instance_url").val();
  445. add_instance.active = false;
  446. srxsettings.instances.push(add_instance);
  447. localStorage.instances = JSON.stringify(srxsettings.instances);
  448. $("#instance_name").val("");
  449. $("#instance_url").val("");
  450. $("#set_instance").trigger($.Event("keyup",{keyCode:13}));
  451. }
  452. }).fail(function() {
  453. $(".loading").hide();
  454. $("#softkey-center").text(translate("save"));
  455. $("#settings_instance").show();
  456. showError(translate("this_instance_does_not_work"));
  457. });
  458. }
  459. }
  460. });
  461. function settings_radio(option,title) {
  462. activepage = "settings_option";
  463. $("#settings").hide();
  464. $("#settings_option_list").empty();
  465. $("#settings_option_header").text(translate(title));
  466. for(var i=0;i<srxdata[option].length;i++) {
  467. (function(index) {
  468. $("#settings_option_list").append($("<li>").addClass("navigable").addClass("large")
  469. .append($("<div>").addClass("kui-list-cont")
  470. .append($("<p>").addClass("kui-pri")
  471. .append($("<input>").addClass("kui-radio").attr("type","radio").attr("id",option+"_"+srxdata[option][i].value))
  472. .append($("<label>").attr("for",option+"_"+srxdata[option][i].value).text(srxdata[option][i].name)))).keyup(function(e) {
  473. if(e.keyCode == 13) {
  474. srxsettings[option] = srxdata[option][index].value;
  475. localStorage.setItem(option,srxdata[option][index].value);
  476. $("#settings_option_list input").removeAttr("checked");
  477. $("#"+option+"_"+srxdata[option][index].value).attr("checked","checked");
  478. }
  479. }));
  480. })(i);
  481. }
  482. $("#"+option+"_"+srxsettings[option]).attr("checked","checked");
  483. $("#settings_option").show();
  484. naviBoard.destroyCurrentNavigationView();
  485. naviBoard.setNavigation("settings_option_list");
  486. }
  487. });