diff options
Diffstat (limited to 'assets/js/mumi.js')
-rw-r--r-- | assets/js/mumi.js | 161 |
1 files changed, 147 insertions, 14 deletions
diff --git a/assets/js/mumi.js b/assets/js/mumi.js index f98a902..1ba77d0 100644 --- a/assets/js/mumi.js +++ b/assets/js/mumi.js @@ -1,19 +1,152 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3.0-or-later -(function () { - var loadSnippet = function (targetId, URL) { - var req = new XMLHttpRequest(); - req.onload = function (e) { - var target = document.getElementById(targetId); - target.outerHTML = req.responseText; - }; - req.onerror = function (e) { - var target = document.getElementById(targetId); - target.outerHTML = "Never mind..."; +var mumi = (function () { + var initTokenInput = function () { + var inputElement = document.querySelector (".tokenInput input#query"); + if (inputElement == null) { + return; + } + const queryTokenizer = { + [Symbol.split](str) { + let phrase = false; + let phrasePos = 0; + let pos = 0; + const result = []; + while (pos < str.length) { + let matchPos = str.substring(pos).search(/(\s|\")/); + if (matchPos === -1) { + result.push(str.substring(pos)); + break; + } + + matchPos += pos; + let char = str.charAt(matchPos); + let begin = pos; + + if (char === '"') { + if (phrase) { + /* finished phrase, record from beginning */ + phrase = false; + begin = phrasePos; + matchPos += 1; + } else { + /* beginning phrase, remember position */ + phrase = true; + phrasePos = matchPos; + } + } + + /* don't push anything while inside a phrase */ + if (!phrase) { + result.push(str.substring(begin, matchPos)); + } + pos = matchPos + 1; + } + return result; + }, + }; + var possibleTokens = [ + { text: 'is:open' }, + { text: 'is:pending' }, + { text: 'is:done' }, + { text: 'is:closed' }, + + { text: 'tag:confirmed' }, + { text: 'tag:easy' }, + { text: 'tag:fixed' }, + { text: 'tag:help' }, + { text: 'tag:moreinfo' }, + { text: 'tag:notabug' }, + { text: 'tag:patch' }, + { text: 'tag:pending' }, + { text: 'tag:security' }, + { text: 'tag:unreproducible' }, + { text: 'tag:wontfix' }, + + { text: 'severity:critical' }, + { text: 'severity:grave' }, + { text: 'severity:important' }, + { text: 'severity:minor' }, + { text: 'severity:normal' }, + { text: 'severity:serious' }, + { text: 'severity:wishlist' }, + ]; + var completionsForTextWithSuggestions = function (suggestions) { + return function (text) { + var completions = []; + text = text.toLowerCase(); + if (text.length) { + suggestions.forEach(function (suggestion) { + var suggestionText = suggestion.text.toLowerCase(); + if (suggestionText.substr (0, text.length) == text) { + completions.push (suggestion); + } + }, this); + } + return completions; + }; + }; + var options = { + freeTextEnabled: true, + freeTextToken : function (text) { + return { + text: text, + value: text, + freeText: true, + group: 'freeText' }; - req.open('GET', URL, true); - req.send(); + }, + tokenFormatter: function (datum, element) { + if (datum.freeText) { + element.classList += " free-text"; + } else { + element.classList += " completed"; + } + }, + completionsForText: completionsForTextWithSuggestions (possibleTokens), + positionFloatingElement: function (element) { + element.style.position = 'absolute'; + element.style.display = 'inline-block'; + element.style.left = '0px'; + element.style.top = inputElement.offsetTop + inputElement.offsetHeight + 'px'; + } }; - loadSnippet ('snippet-recent', '/snippet/recent'); - loadSnippet ('snippet-priority', '/snippet/priority'); + + tokenInput = new TokenInput (inputElement, options); + window.tokenInputs = window.tokenInputs || []; + window.tokenInputs.push (tokenInput); + + const form = document.querySelector ("form#search"); + form.addEventListener ("submit", function (event) { + event.preventDefault (); + for (token of tokenInput.getTokens ()) { + inputElement.value += token.text + " "; + } + inputElement.style.visibility = 'hidden'; + form.submit (); + }); + + /* tokenize existing input text */ + if (inputElement.value.length > 0) { + let items = inputElement.value.split(queryTokenizer).filter(entry => entry.trim() != ''); + let tokens = []; + for (item of items) { + if (possibleTokens.find(element => element.text == item)) { + tokens.push({text: item}); + } else { + tokens.push(options.freeTextToken(item)); + } + } + inputElement.value = ""; + tokenInput.setTokens(tokens); + } + }; + var init = function () { + initTokenInput (); + }; + return({ + 'init': init, + }); })(); + +window.addEventListener ("load", mumi.init); // @license-end |