flexi-bot/docs/marlin/assets/javascript/search.js
2023-09-05 20:38:49 +02:00

268 lines
8.8 KiB
JavaScript

/**
* A simple JSON search
* Requires jQuery (v 1.7+)
*
* @author Mat Hayward - Erskine Design
* Scott Lahteine - Thinkyhead
* @version 0.1-MF
*/
"use strict";
//
// Declare a jekyllSearch singleton
//
var jekyllSearch = (function(){
var q, qmatch, jsonFeedUrl = '/feeds/feed.json',
$searchForm, $searchInput, $searchButton,
$resultTemplate, $resultsPlaceholder, $results,
$foundContainer, $foundTerm, $foundCount,
allowEmpty = false, showLoader = false,
loadingClass = 'is--loading',
self, searchTimer, odd = false,
section_head = { gcode:"G-code", basics:"Getting Started", config:"Configuration", feat:"Features", devel:"Development", setting:"Settings" };
const ignore_pattern = /\b(a(ll|nd|re(n't)?)|but|can('t|not)?|d(id|oes)(n't)?|end|for|ha(d|s|ve)(n't)?|it'?s|odd|use[ds]?|even|from|man?y|more|much|some|this|tha[nt]|th[eo]se|the([mny]|ir|re|y're)?|(was|were)(n't)?|wh(at|en|ere|ich|o|y)|will|won't|other|people|(al)?though|users|your?|one|two)\b/g;
// Return the public interface
return {
/**
* Get query string parameter - taken from http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
* @param {String} name
* @return {String} parameter value
*/
getParameterByName: function(name) {
var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
},
/**
* Inject content into template using placeholder
* @param {String} originalContent
* @param {String} injection
* @param {String} placeholder
* @return {String} injected content
*/
injectContent: function(originalContent, injection, placeholder) {
if (injection === undefined) injection = '';
var regex = new RegExp(placeholder, 'g');
return originalContent.replace(regex, injection);
},
init: function() {
self = this;
if (document.location.href.indexOf('meta/search/') == -1) {
setTimeout(function(){ $('#searchbox>form').css('display','inline-block'); }, 800);
return;
}
$searchForm = $("[data-search-form]");
$searchInput = $("[data-search-input]");
$searchButton = $("[data-search-button]");
$resultTemplate = $("#search-result");
$resultsPlaceholder = $("[data-search-results]");
$foundContainer = $("[data-search-found]");
$foundTerm = $("[data-search-found-term]");
$foundCount = $("[data-search-found-count]");
// hide items found string
$foundContainer.hide();
/**
* Initiate search functionality.
* Show results based on (q)uerystring if present.
* Bind search function to form submission.
*/
// Get search results if q parameter is set in querystring
if (self.getParameterByName('q')) {
var newq = decodeURIComponent(self.getParameterByName('q'));
$searchInput.val(newq);
self.execSearch(newq, newq);
}
//$searchForm.on('submit',function(e){ return false; });
// Get search results on submission of form
// TODO: Update results on change, after a pause
$searchInput.change(self.onSearchChanged)
.keydown(function(e){
var k = e.keyCode;
if (k == 10 || k == 13) return self.onSearchChanged(e);
})
.keyup(function(e){
var k = e.keyCode;
if (k >= 32 || k == 8) self.onSearchKeyUp();
});
$searchButton.click(function(e) { self.onSearchChanged(e); });
self.searchFromField();
},
searchFieldString: function() {
return $searchInput.val().trim();
},
searchPattern: function(str) {
const patt = str.toLowerCase().replace(ignore_pattern, '').trim().replace(/\s+/g, '.+');
return new RegExp(patt);
},
searchFromField: function() {
var newq = self.searchFieldString(),
newm = self.searchPattern(newq);
self.execSearch(newq, newm);
},
onSearchChanged: function(e) {
e.preventDefault();
var newq = self.searchFieldString();
if (newq.length >= 3 || newq.match(/^[gm]\d+/i))
self.searchFromField();
return false;
},
onSearchKeyUp: function() {
if (searchTimer) { clearTimeout(searchTimer); searchTimer = 0; }
var newq = self.searchFieldString();
if (newq.length >= 3 || newq.match(/^[gm]\d+/i))
searchTimer = setTimeout(self.searchFromField, 800);
},
fixResultsPos: function() {
$resultsPlaceholder.css('padding-top', ($("#search .overlay").height() + 6) + 'px');
$(window).scrollTop(0);
},
/**
* Execute search
* @return null
*/
execSearch: function(newq, newm) {
if (newq != '' || allowEmpty) {
q = newq;
qmatch = newm;
if (showLoader) self.toggleLoadingClass();
self.getSearchResults(self.resultsProcessor());
var loc = window.location;
history.replaceState({}, "marlinfw.org Search", loc.origin + '/meta/search/' + "?q=" + newq);
}
},
/**
* Toggle loading class on results and found string
* @return null
*/
toggleLoadingClass: function() {
$resultsPlaceholder.toggleClass(loadingClass);
$foundContainer.toggleClass(loadingClass);
},
/**
* Get Search results from JSON
* @param {Function} callbackFunction
* @return null
*/
getSearchResults: function(callbackFunction) {
$.get(jsonFeedUrl, callbackFunction, 'json');
},
/**
* Process search result data
* @return null
*/
resultsProcessor: function() {
var results = [];
return function(data) {
//console.log("Processor data", data);
var resultsCount = 0, results = '', lastclass = '';
$.each(data, function(index, item) {
// check if search term is in content or title
const comp = (item.name + " " + item.title + ' ' + item.content + item.excerpt).toLowerCase();
if (comp.match(qmatch)) {
if (item.class != lastclass) {
lastclass = item.class;
var fancy = section_head[item.class];
results += '<h1 class="' + item.class + '">' + (fancy ? fancy : item.class) + '</h1>';
}
var result = self.populateResultContent($resultTemplate.html(), item);
resultsCount++;
results += result;
}
});
if (showLoader) self.toggleLoadingClass();
self.populateResultsString(resultsCount);
self.showSearchResults(results);
}
},
/**
* Add search results to placeholder
* @param {String} results
* @return null
*/
showSearchResults: function(results) {
// Add results HTML to placeholder
$resultsPlaceholder.html(results);
self.fixResultsPos();
},
/**
* Add results content to item template
* @param {String} html
* @param {object} item
* @return {String} Populated HTML
*/
populateResultContent: function(html, item) {
html = self.injectContent(html, item.title, '##Title##');
html = self.injectContent(html, item.link, '##Url##');
html = self.injectContent(html, item.excerpt, '##Excerpt##');
var extra_tags = '';
if (item.exp !== undefined)
extra_tags += '<span class="label label-warning"><span data-toggle="tooltip" data-placement="bottom" title="Experimental feature"><i class="fa fa-flask" aria-hidden="true"></i></span></span>';
if (item.since !== undefined)
extra_tags += '<span class="label label-success"><span data-toggle="tooltip" data-placement="bottom" title="Available since"><i class="fa fa-code" aria-hidden="true"></i>' + item.since + '</span></span>';
if (item.group !== undefined)
extra_tags += '<span class="label label-default"><i class="fa fa-tags" aria-hidden="true"></i>' + item.group + '</span>';
if (item.requires !== undefined)
$.each(item.requires.split(","), function() {
extra_tags += '<span class="label label-requires">' + this + '</span>';
});
html = self.injectContent(html, extra_tags, '##CustomHTML##');
var c = item.class ? item.class : '';
html = self.injectContent(html, 'item ' + (odd ? 'odd ' : '') + c, '##DivClass##');
if (item.date)
html = self.injectContent(html, item.date, '##Date##');
else
html = self.injectContent(html, '', '<h2 class="date"><a href="##Url##">##Date##</a></h2>');
odd = !odd;
return html;
},
/**
* Populates results string
* @param {String} count
* @return null
*/
populateResultsString: function(count) {
$foundTerm.text(q);
$foundCount.text(count);
$foundContainer.show();
}
}; // return public interface
})();