search.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. define(['util', 'options', 'nwSearchFnt', 'searchHistoryItems', 'localization', 'jquery', 'jquery.highlight', 'jquery.bootpag'], function(util, options, nwSearchFnt, searchHistory, i18n, $) {
  2. /*
  3. Oxygen WebHelp Plugin
  4. Copyright (c) 1998-2020 Syncro Soft SRL, Romania. All rights reserved.
  5. */
  6. var txt_browser_not_supported = "Your browser is not supported. Use of Mozilla Firefox is recommended.";
  7. /**
  8. * Constant with maximum search items presented for a single page.
  9. * @type {number}
  10. */
  11. var maxItemsPerPage = 10;
  12. /**
  13. * Variable with total page number.
  14. *
  15. * @type {number}
  16. */
  17. var totalPageNumber = -1;
  18. /**
  19. * Last displayed search results items.
  20. * @type {Array}
  21. */
  22. var lastSearchResultItems = [];
  23. /**
  24. * Last displayed search result.
  25. * @type {Array}
  26. */
  27. var lastSearchResult;
  28. /**
  29. * When it is true, then the score is displayed as tooltip.
  30. *
  31. * @type {boolean}
  32. */
  33. var displayScore = false;
  34. if(typeof String.prototype.trim !== 'function') {
  35. String.prototype.trim = function() {
  36. return $.trim(this);
  37. }
  38. }
  39. $(document).ready(function () {
  40. var searchQuery = '';
  41. try {
  42. searchQuery = util.getParameter('searchQuery');
  43. searchQuery = decodeURIComponent(searchQuery);
  44. searchQuery = searchQuery.replace(/\+/g, " ");
  45. if (searchQuery.trim()!='' && searchQuery!==undefined && searchQuery!='undefined') {
  46. $('#textToSearch').val(searchQuery);
  47. util.debug("Execute search");
  48. executeQuery();
  49. util.debug("Executed search");
  50. }
  51. } catch (e) {
  52. util.debug("#########", e);
  53. }
  54. $('.gcse-searchresults-only').attr('data-queryParameterName', 'searchQuery');
  55. // Select page from parameter in the pages widget
  56. window.onpopstate = function(event) {
  57. if (lastSearchResultItems != null && lastSearchResult != null) {
  58. // Get the value for the 'page' parameter
  59. var pageToShow = util.getParameter("page");
  60. // Set to 1 if it is undefined
  61. if (pageToShow == undefined || pageToShow == "undefined" || pageToShow == "") {
  62. pageToShow = 1;
  63. } else {
  64. pageToShow = parseInt(pageToShow);
  65. if (isNaN(pageToShow)) {
  66. pageToShow = 1;
  67. }
  68. }
  69. displayPageResults(pageToShow);
  70. // Update the active page
  71. $('.pagination li[class~="active"]').removeClass("active");
  72. $('.pagination li[data-lp="' + pageToShow + '"]:not([class~="prev"]):not([class~="next"])').addClass("active");
  73. }
  74. };
  75. $('#searchForm').on('submit', function(event){
  76. util.debug('submit form....');
  77. if ($('#textToSearch').val().trim()=='') {
  78. event.preventDefault();
  79. event.stopPropagation();
  80. return false;
  81. }
  82. });
  83. });
  84. /**
  85. * @description Search using Google Search if it is available, otherwise use our search engine to execute the query
  86. * @return {boolean} Always return false
  87. */
  88. function executeQuery() {
  89. util.debug("executeQuery");
  90. var input = document.getElementById('textToSearch');
  91. try {
  92. var element = google.search.cse.element.getElement('searchresults-only0');
  93. } catch (e) {
  94. util.debug(e);
  95. }
  96. if (element != undefined) {
  97. if (input.value == '') {
  98. element.clearAllResults();
  99. } else {
  100. element.execute(input.value);
  101. }
  102. } else {
  103. executeSearchQuery($("#textToSearch").val());
  104. }
  105. return false;
  106. }
  107. function clearHighlights() {
  108. }
  109. /**
  110. * Execute search query with internal search engine.
  111. *
  112. * @description This function find all matches using the search term
  113. * @param {HTMLObjectElement} ditaSearch_Form The search form from WebHelp page as HTML Object
  114. */
  115. function executeSearchQuery(query) {
  116. util.debug('SearchToc(..)');
  117. // Check browser compatibility
  118. if (navigator.userAgent.indexOf("Konquerer") > -1) {
  119. alert(i18n.getLocalization(txt_browser_not_supported));
  120. return;
  121. }
  122. searchAndDisplayResults(query);
  123. }
  124. function searchAndDisplayResults(query) {
  125. nwSearchFnt.performSearch(query, function(searchResult) {
  126. if (searchResult.searchExpression.trim().length > 0 || searchResult.excluded.length > 0) {
  127. displayResults(searchResult);
  128. } else {
  129. var error = searchResult.error;
  130. if (typeof error != "undefined" && error.length > 0) {
  131. displayErrors(searchResult.error);
  132. }
  133. }
  134. });
  135. }
  136. /**
  137. * @description Display errors in HTML format
  138. * @param {string} errorMsg
  139. */
  140. function displayErrors(errorMsg) {
  141. var searchResultHTML = $('<p/>');
  142. searchResultHTML.addClass('errorMessage')
  143. .html(errorMsg);
  144. $('#searchResults').html(searchResultHTML);
  145. }
  146. /**
  147. * @description Display results in HTML format
  148. * @param {SearchResult} searchResult The search result.
  149. */
  150. function displayResults(searchResult) {
  151. preprocessSearchResult(searchResult, 'wh-responsive');
  152. // Add search query to history
  153. searchHistory.addSearchQueryToHistory(searchResult.originalSearchExpression);
  154. var webhelpEnableSearchPagination = options.getBoolean("webhelp.search.enable.pagination");
  155. var webhelpSearchNumberOfItems = options.getInteger("webhelp.search.page.numberOfItems");
  156. if (webhelpEnableSearchPagination !== 'undefined' && webhelpEnableSearchPagination == false) {
  157. // WH-1470 - Search pagination is disabled
  158. maxItemsPerPage = Number.MAX_VALUE;
  159. } else if (typeof webhelpSearchNumberOfItems !== 'undefined') {
  160. // WH-1471 - Option to control the maximum numbers of items displayed for each page
  161. maxItemsPerPage = webhelpSearchNumberOfItems;
  162. }
  163. // Compute the total page number
  164. totalPageNumber =
  165. Math.ceil(lastSearchResultItems.length / maxItemsPerPage);
  166. // Get the value for the 'page' parameter
  167. var pageToShow = util.getParameter("page");
  168. // Set to 1 if it is undefined
  169. if (pageToShow == undefined || pageToShow == "undefined" || pageToShow == "") {
  170. pageToShow = 1;
  171. } else {
  172. pageToShow = parseInt(pageToShow);
  173. if (isNaN(pageToShow)) {
  174. pageToShow = 1;
  175. }
  176. }
  177. // Display a page
  178. displayPageResults(pageToShow);
  179. if (totalPageNumber > 1) {
  180. // Add pagination widget
  181. $('#wh-search-pagination').bootpag({
  182. total: totalPageNumber, // total pages
  183. page: pageToShow, // default page
  184. maxVisible: 10, // visible pagination
  185. leaps: false, // next/prev leaps through maxVisible
  186. next: i18n.getLocalization("next.page"),
  187. prev: i18n.getLocalization("prev.page")
  188. }).on("page", function(event, num){
  189. util.debug("Display page with number: ", num);
  190. // Replace or add the page query
  191. var oldPage = util.getParameter("page");
  192. var oldQuery = window.location.search;
  193. var oldHref = window.location.href;
  194. var oldLocation = oldHref.substr(0, oldHref.indexOf(oldQuery));
  195. var newQuery = "";
  196. if (oldPage == undefined || oldPage == "undefined" || oldPage == "") {
  197. newQuery = oldQuery + "&page=" + num;
  198. } else {
  199. var re = new RegExp("(\\?|&)page\=" + oldPage);
  200. newQuery = oldQuery.replace(re, "$1page="+num);
  201. }
  202. window.history.pushState("searchPage" + num, document.title, oldLocation + newQuery);
  203. displayPageResults(num);
  204. /*$("#content").html("Page " + num); // or some ajax content loading...
  205. // ... after content load -> change total to 10
  206. $(this).bootpag({total: 10, maxVisible: 10});*/
  207. });
  208. }
  209. // make bootpag compatible with Bootstrap 4.0
  210. $('#wh-search-pagination').find('li').addClass('page-item');
  211. $('#wh-search-pagination').find('a').addClass('page-link');
  212. $("#search").trigger('click');
  213. }
  214. /**
  215. * Display search results for a specific page.
  216. *
  217. * @param pageIdx The page index.
  218. */
  219. function displayPageResults(pageIdx) {
  220. var searchResultHTML =
  221. computeHTMLResult('wh-responsive', pageIdx, totalPageNumber, maxItemsPerPage);
  222. $('#searchResults').html(searchResultHTML);
  223. window.scrollTo(0, 0);
  224. }
  225. /***************************************************************************************
  226. ******************************* searchCommon.js****************************************
  227. **************************************************************************************/
  228. /**
  229. * An object containing the search result for a single topic/HTML page.
  230. * Contains pointer to the topicID, title, short description and the list of words that were found.
  231. *
  232. * @param {string} topicID The ID of the topic. Can be used to identify unique a document in the search result.
  233. * @param {string} relativePath The relative path to the topic.
  234. * @param {string} title The topic title.
  235. * @param {string} shortDescription The topic short description.
  236. * @param {[string]} words The array with words contained by this topic.
  237. * @param {int} scoring The search scoring computed for this document.
  238. * @param {int} startsWith The number used to display 5 stars ranking.
  239. * @param {int} resultID The search result ID.
  240. * @param {int} linkID The search link ID.
  241. * @param {[TopicInfo]} breadcrumb The breadcrumb of current document. Can be [].
  242. * @constructor
  243. */
  244. function SearchResultInfo(topicID, relativePath, title, shortDescription, words, scoring, starWidth, resultID, linkID, breadcrumb) {
  245. this.topicID = topicID;
  246. this.relativePath = relativePath;
  247. this.title = title;
  248. this.shortDescription = shortDescription;
  249. this.words = words;
  250. this.scoring = scoring;
  251. this.starWidth = starWidth;
  252. this.resultID = resultID;
  253. this.linkID = linkID;
  254. this.similarResults = [];
  255. this.breadcrumb = breadcrumb;
  256. }
  257. /**
  258. * Pre process search result to compute similar results and scoring.
  259. * The lastSearchResultItems variable will be updated.
  260. *
  261. * @param searchResult The seach result to process.
  262. * @param whDistribution The WebHelp distribution.
  263. */
  264. function preprocessSearchResult(searchResult, whDistribution) {
  265. lastSearchResult = searchResult;
  266. lastSearchResultItems = [];
  267. var wh_mobile =
  268. (typeof whDistribution != 'undefined') && whDistribution == 'wh-mobile';
  269. var wh_Classic =
  270. (typeof whDistribution != 'undefined') && whDistribution == 'wh-classic';
  271. if (searchResult.documents !== undefined && searchResult.documents.length > 0) {
  272. var allPages = searchResult.documents;
  273. // WH-1943 - sort by scoring, title and short description
  274. allPages.sort(function (first, second) {
  275. var cRes = second.scoring -first.scoring;
  276. if (cRes == 0) {
  277. cRes = second.title.localeCompare(first.title);
  278. if (cRes == 0) {
  279. cRes = second.shortDescription.localeCompare(first.shortDescription);
  280. }
  281. }
  282. return cRes;
  283. });
  284. // The score for fist item
  285. var ttScore_first = 1;
  286. if (allPages.length > 0) {
  287. ttScore_first = allPages[0].scoring;
  288. }
  289. var currentSimilarPage={};
  290. for (var page = 0; page < allPages.length; page++) {
  291. /*debug("Page number: " + page);*/
  292. if (allPages[page].relativePath == 'toc.html') {
  293. continue;
  294. }
  295. var starWidth = 0;
  296. var webhelpSearchRanking = options.getBoolean("webhelp.search.ranking");
  297. if (typeof webhelpSearchRanking != "undefined" && webhelpSearchRanking) {
  298. var hundredPercent = allPages[page].scoring + 100 * allPages[page].words.length;
  299. var numberOfWords = allPages[page].words.length;
  300. /*debug("hundredPercent: " + hundredPercent + "; ttScore_first: " + ttScore_first + "; numberOfWords: " + numberOfWords);*/
  301. var ttScore = allPages[page].scoring;
  302. // Fake value
  303. var maxNumberOfWords = allPages[page].words.length;
  304. starWidth = (ttScore * 100 / hundredPercent) / (ttScore_first / hundredPercent) * (numberOfWords / maxNumberOfWords);
  305. starWidth = starWidth < 10 ? (starWidth + 5) : starWidth;
  306. // Keep the 5 stars format
  307. if (starWidth > 85) {
  308. starWidth = 85;
  309. }
  310. }
  311. var idLink = 'foundLink' + page;
  312. var idResult = 'foundResult' + page;
  313. // topicID, relativePath, title, shortDescription, words, scoring, starWidth, resultID, linkID, similarResults
  314. util.debug("page", page);
  315. var csri = new SearchResultInfo(
  316. allPages[page].topicID,
  317. allPages[page].relativePath,
  318. allPages[page].title,
  319. allPages[page].shortDescription,
  320. allPages[page].words,
  321. allPages[page].scoring,
  322. starWidth,
  323. idResult,
  324. idLink,
  325. allPages[page].breadcrumb
  326. );
  327. // Similar pages
  328. var similarPages = !wh_mobile && similarPage(allPages[page], allPages[page - 1]);
  329. if (!similarPages) {
  330. currentSimilarPage = csri;
  331. lastSearchResultItems.push(csri);
  332. } else {
  333. currentSimilarPage.similarResults.push(csri);
  334. }
  335. }
  336. }
  337. }
  338. /**
  339. * Compute the HTML to be displayed in the search results page.
  340. *
  341. * @param whDistribution The string with WebHelp distribution. One of wh-classic, wh-mobile or wh-responsive.
  342. * @param pageNumber The page number to display.
  343. * @param totalPageNumber The total page number.
  344. * @param itemsPerPage The number of items to display on a page.
  345. * @returns {string} The HTML to be displayed as search result.
  346. */
  347. function computeHTMLResult(whDistribution, pageNumber, totalPageNumber, itemsPerPage) {
  348. // Empty jQuery element
  349. var results = $();
  350. var $wh_search_results_items = $();
  351. if (lastSearchResult.searchExpression.length > 0) {
  352. if (lastSearchResultItems.length > 0) {
  353. $wh_search_results_items = $('<div/>', {
  354. class: 'wh_search_results_items'
  355. });
  356. // Start and end index depending on the current presented page
  357. var s = 0;
  358. var e = lastSearchResultItems.length;
  359. if (typeof pageNumber != "undefined" && typeof itemsPerPage != "undefined") {
  360. s = (pageNumber - 1) * itemsPerPage;
  361. var next = s + itemsPerPage;
  362. e = Math.min(next, lastSearchResultItems.length);
  363. }
  364. // Result for: word1 word2
  365. var txt_results_for = "Results for:";
  366. var $headerHTML = $('<div/>', {
  367. class: 'wh_search_results_header'
  368. });
  369. var $whSearchResultsHeaderDocs = $('<div/>', {
  370. class: 'wh_search_results_header_docs'
  371. }).html(
  372. lastSearchResultItems.length +
  373. ' ' +
  374. i18n.getLocalization(txt_results_for) + ' '
  375. );
  376. var $span = $('<span/>', {
  377. class: 'wh_search_expression'
  378. }).html(lastSearchResult.originalSearchExpression);
  379. $whSearchResultsHeaderDocs.append($span);
  380. $headerHTML.append($whSearchResultsHeaderDocs);
  381. if (typeof pageNumber != "undefined" && typeof totalPageNumber != "undefined" && totalPageNumber > 1) {
  382. var $wh_search_results_header_pages = $('<div/>', {
  383. class: 'wh_search_results_header_pages'
  384. }).html(i18n.getLocalization('Page') + ' ' + pageNumber + '/' + totalPageNumber);
  385. $headerHTML.append($wh_search_results_header_pages);
  386. }
  387. $wh_search_results_items.append($headerHTML);
  388. // EXM-38967 Start numbering
  389. var start = (pageNumber - 1) * 10 + 1;
  390. var $ol = $('<ol/>', {
  391. class: 'searchresult',
  392. start: start
  393. });
  394. for (var page = s; page < e; page++) {
  395. var csri = lastSearchResultItems[page];
  396. var hasSimilarPages =
  397. csri.similarResults != null &&
  398. csri.similarResults.length > 0;
  399. var siHTML = computeSearchItemHTML(
  400. csri,
  401. whDistribution,
  402. hasSimilarPages,
  403. null);
  404. $ol.append(siHTML);
  405. if (hasSimilarPages) {
  406. // Add HTML for similar pages
  407. for (var smPage = 0; smPage < csri.similarResults.length; smPage++) {
  408. var simHTML = computeSearchItemHTML(
  409. csri.similarResults[smPage],
  410. whDistribution,
  411. false,
  412. csri.resultID);
  413. $ol.append(simHTML);
  414. }
  415. }
  416. }
  417. $wh_search_results_items.append($ol);
  418. if ($wh_search_results_items.find('li').length == 0) {
  419. $wh_search_results_items = $('<div/>', {
  420. class: 'wh_search_results_for'
  421. });
  422. var $span = $('<span/>', {
  423. class: 'wh_search_expression'
  424. }).text(lastSearchResult.originalSearchExpression);
  425. $wh_search_results_items.append($span);
  426. }
  427. } else {
  428. $wh_search_results_items = $('<div/>', {
  429. class: 'wh_search_results_for'
  430. }).html(i18n.getLocalization('Search no results') + ' ');
  431. var $span = $('<span/>', {
  432. class: 'wh_search_expression'
  433. }).text(lastSearchResult.originalSearchExpression);
  434. $wh_search_results_items.append($span);
  435. }
  436. } else {
  437. // Search expression is empty. If there are stop words, display a message accordingly
  438. if (lastSearchResult.excluded.length > 0) {
  439. $wh_search_results_items = $();
  440. var $p = $('<p/>', {
  441. class: 'wh_search_results_for'
  442. }).html(i18n.getLocalization("no_results_only_stop_words1"));
  443. $wh_search_results_items.append($p);
  444. $p.html(i18n.getLocalization('no_results_only_stop_words2'));
  445. $wh_search_results_items.append($p);
  446. }
  447. }
  448. return $wh_search_results_items;
  449. }
  450. function computeSearchItemHTML(searchItem, whDistribution, hasSimilarPages, similarPageID) {
  451. // New empty jQuery element
  452. var htmlResult = $();
  453. var wh_mobile =
  454. (typeof whDistribution != 'undefined') && whDistribution == 'wh-mobile';
  455. var wh_Classic =
  456. (typeof whDistribution != 'undefined') && whDistribution == 'wh-classic';
  457. var allSearchWords = lastSearchResult.searchExpression.split(" ");
  458. var tempPath = searchItem.relativePath;
  459. // EXM-27709 START
  460. // Display words between '<' and '>' in title of search results.
  461. var tempTitle = searchItem.title;
  462. // EXM-27709 END
  463. var tempShortDesc = searchItem.shortDescription;
  464. var starWidth = searchItem.starWidth;
  465. var rankingHTML = $();
  466. var webhelpSearchRanking = options.getBoolean("webhelp.search.ranking");
  467. if (!wh_mobile && (typeof webhelpSearchRanking != 'undefined') && webhelpSearchRanking) {
  468. // Add rating values for scoring at the list of matches
  469. rankingHTML = $("<div/>", {
  470. id: 'rightDiv'
  471. });
  472. if (displayScore) {
  473. rankingHTML.attr('title', 'Score: ' + searchItem.scoring);
  474. }
  475. var rankingStar =
  476. $('<div/>', {
  477. id: 'star'
  478. }).append(
  479. $('<div/>', {
  480. id: 'star0',
  481. class: 'star'
  482. }).append(
  483. $('<div/>', {
  484. id: 'starCur0',
  485. class: 'curr',
  486. style: 'width: ' + starWidth + 'px'
  487. }).append(
  488. $('<br/>', {
  489. style: 'clear: both;'
  490. })
  491. )
  492. )
  493. );
  494. rankingHTML.append(rankingStar);
  495. }
  496. var finalArray = searchItem.words;
  497. var arrayStringAux = [];
  498. var arrayString = '';
  499. var indexerLanguage = options.getIndexerLanguage();
  500. var useCJKTokenizing = !!(typeof indexerLanguage != "undefined" && (indexerLanguage == "zh" || indexerLanguage == "ko"));
  501. for (var x in finalArray) {
  502. if (finalArray[x].length >= 2 || useCJKTokenizing || (indexerLanguage == "ja" && finalArray[x].length >= 1)) {
  503. arrayStringAux.push(finalArray[x]);
  504. }
  505. }
  506. arrayString = arrayStringAux.toString();
  507. // Add highlight param
  508. if (!wh_Classic && !wh_mobile) {
  509. tempPath += '?hl=' + encodeURIComponent(arrayString);
  510. }
  511. var idLink = searchItem.linkID;
  512. var idResult = searchItem.resultID;
  513. var link = 'return openAndHighlight(\'' + tempPath + '\', ' + arrayString + '\)';
  514. // Create the search result item li
  515. // Similar pages
  516. if (similarPageID == null) {
  517. htmlResult = $('<li/>', {
  518. id: idResult
  519. });
  520. } else {
  521. htmlResult = $('<li/>', {
  522. id: idResult,
  523. class: 'similarResult',
  524. 'data-similarTo': similarPageID
  525. });
  526. }
  527. // The topic title of the search result item
  528. var $a = $('<a/>', {
  529. id: idLink,
  530. href: tempPath,
  531. class: 'foundResult'
  532. }).html(tempTitle);
  533. htmlResult.append($a);
  534. // The breadcrumb
  535. var breadcrumb = searchItem.breadcrumb;
  536. util.debug('searchItem', searchItem);
  537. util.debug('breadcrumb', breadcrumb);
  538. if (breadcrumb !== undefined && breadcrumb.length > 0) {
  539. // Show the breadcrumb
  540. var breadcrumbHtml = $('<div>', {
  541. class: 'search-breadcrumb',
  542. });
  543. var breadcrumbItems = $('<ol>');
  544. breadcrumb.forEach(function (item) {
  545. var li = $('<li>');
  546. var span = $('<span>',
  547. {
  548. class: 'title'
  549. });
  550. span.append($('<a>',
  551. {
  552. href: item.relativePath,
  553. html: item.title
  554. }));
  555. li.append(span);
  556. breadcrumbItems.append(li);
  557. });
  558. breadcrumbHtml.append(breadcrumbItems);
  559. htmlResult.append(breadcrumbHtml);
  560. }
  561. // Short description
  562. // Also check if we have a valid description
  563. if ((tempShortDesc != "null" && tempShortDesc != '...')) {
  564. var $shortDescriptionDIV = $('<div/>', {
  565. class: 'shortdesclink'
  566. }).html(tempShortDesc);
  567. // Highlight the search words in short description
  568. for (var si = 0; si < allSearchWords.length; si++) {
  569. var sw = allSearchWords[si];
  570. $shortDescriptionDIV.highlight(sw, 'search-shortdescription-highlight');
  571. }
  572. htmlResult.append($shortDescriptionDIV);
  573. }
  574. // Empty jQuery element
  575. var searchItemInfo = $('<div/>', {
  576. class: 'missingAndSimilar'
  577. });
  578. // Relative Path
  579. $a = $('<a/>', {
  580. href: tempPath
  581. }).html(searchItem.relativePath);
  582. if (wh_Classic) {
  583. $a.attr('onclick', link);
  584. }
  585. var relPathStr = $('<div/>', {
  586. class: 'relativePath'
  587. }).append($a);
  588. searchItemInfo.append(relPathStr);
  589. // Missing words
  590. if (!wh_mobile && allSearchWords.length != searchItem.words.length) {
  591. var missingWords = [];
  592. allSearchWords.forEach(function (word) {
  593. if (searchItem.words.indexOf(word) == -1) {
  594. missingWords.push(word);
  595. }
  596. });
  597. var missingHTML = $('<div/>', {
  598. class: 'wh_missing_words'
  599. });
  600. missingHTML.html(i18n.getLocalization('missing') + ' : ');
  601. for (var widx = 0; widx < missingWords.length; widx++) {
  602. var $span = $('<span/>', {
  603. class: 'wh_missing_word'
  604. }).html(missingWords[widx]);
  605. missingHTML.append($span).append(' ');
  606. }
  607. searchItemInfo.append(missingHTML);
  608. }
  609. if (!wh_mobile && hasSimilarPages) {
  610. var $similarHTML = $('<a/>', {
  611. class: 'showSimilarPages'
  612. }).html(i18n.getLocalization('Similar results') + '...');
  613. $similarHTML.click(showSimilarResults);
  614. searchItemInfo.append($similarHTML);
  615. }
  616. if (rankingHTML.html() != '' && searchItemInfo.html() != '') {
  617. var $searchItemAdditionalData = $('<div/>', {
  618. class: 'searchItemAdditionalData'
  619. }).append(searchItemInfo).append(rankingHTML);
  620. htmlResult.append($searchItemAdditionalData);
  621. } else if (searchItemInfo.html() != '') {
  622. htmlResult.append(searchItemInfo);
  623. } else if (rankingHTML.html() != '') {
  624. htmlResult.append(rankingHTML);
  625. }
  626. return htmlResult;
  627. }
  628. /**
  629. * @description Compare two result pages to see if there are similar
  630. * @param result1 Result page
  631. * @param result2 Result page
  632. * @returns {boolean} true - result pages are similar
  633. * false - result pages are not similar
  634. */
  635. function similarPage(result1, result2) {
  636. var toReturn = false;
  637. if (result1 === undefined || result2 === undefined) {
  638. return toReturn;
  639. }
  640. var pageTitle1 = result1.title;
  641. var pageShortDesc1 = result1.shortDescription;
  642. var pageTitle2 = result2.title;
  643. var pageShortDesc2 = result2.shortDescription;
  644. if (pageTitle1.trim() == pageTitle2.trim() && pageShortDesc1.trim() == pageShortDesc2.trim()) {
  645. toReturn = true;
  646. }
  647. return toReturn;
  648. }
  649. /**
  650. * @description Show similar results that are hidden by default
  651. */
  652. function showSimilarResults() {
  653. var parentLiElement = $(this).parents('li[id]');
  654. var currentResultId = parentLiElement.attr('id');
  655. $('[data-similarTo="' + currentResultId + '"]').toggle();
  656. $(this).toggleClass('expanded');
  657. }
  658. });