nightTab/js/auto-suggest.js

261 lines
8.4 KiB
JavaScript
Raw Normal View History

var autoSuggest = (function() {
var _timer = null;
var _currentInputOptions = {};
var _autoSuggestActive = false;
var _delayRender = function(options) {
render(options);
};
var bind = function(override) {
var options = {
input: null,
type: null,
postFocus: null
};
if (override) {
options = helper.applyOptions(options, override);
};
if (options.input) {
options.input.addEventListener("focus", function() {
if (!_autoSuggestActive) {
clearTimeout(_timer);
_timer = setTimeout(_delayRender, 300, options);
};
}, false);
options.input.addEventListener("input", function() {
clearTimeout(_timer);
_timer = setTimeout(_delayRender, 300, options);
}, false);
};
};
var _navigateResults = function(event) {
var elementToFocus = null;
var focusIndex = null;
var allSuggestItems = helper.eA(".auto-suggest-link");
var _findInput = function() {
if (event.target.classList.contains("auto-suggest-input")) {
_currentInputOptions.input = event.target;
};
};
var _findFocus = function() {
for (var i = 0; i < allSuggestItems.length; i++) {
if (allSuggestItems[i] == document.activeElement) {
focusIndex = i;
};
};
};
var _keyEvents = function() {
// up
if (event.keyCode == 38) {
event.preventDefault();
if (focusIndex == null) {
elementToFocus = allSuggestItems[allSuggestItems.length - 1];
} else {
if (focusIndex > 2 && focusIndex <= allSuggestItems.length - 1) {
elementToFocus = allSuggestItems[focusIndex - 3];
} else {
elementToFocus = _currentInputOptions.input;
};
};
};
// down
if (event.keyCode == 40) {
event.preventDefault();
if (focusIndex == null) {
elementToFocus = allSuggestItems[0];
} else {
if (focusIndex < allSuggestItems.length - 3) {
elementToFocus = allSuggestItems[focusIndex + 3];
} else {
elementToFocus = _currentInputOptions.input;
};
};
};
// right
if (event.keyCode == 39 && document.activeElement != _currentInputOptions.input) {
event.preventDefault();
if (focusIndex == null) {
elementToFocus = allSuggestItems[0];
} else {
if (focusIndex >= 0 && focusIndex < allSuggestItems.length - 1) {
elementToFocus = allSuggestItems[focusIndex + 1];
} else {
elementToFocus = _currentInputOptions.input;
};
};
};
// left
if (event.keyCode == 37 && document.activeElement != _currentInputOptions.input) {
event.preventDefault();
if (focusIndex == null) {
elementToFocus = allSuggestItems[allSuggestItems.length - 1];
} else {
if (focusIndex > 0 && focusIndex <= allSuggestItems.length - 1) {
elementToFocus = allSuggestItems[focusIndex - 1];
} else {
elementToFocus = _currentInputOptions.input;
};
};
};
// tab
if (!event.shiftKey && event.keyCode == 9 && document.activeElement == _currentInputOptions.input) {
event.preventDefault();
elementToFocus = allSuggestItems[0];
};
if (!event.shiftKey && event.keyCode == 9 && document.activeElement == allSuggestItems[allSuggestItems.length - 1]) {
event.preventDefault();
elementToFocus = _currentInputOptions.postFocus;
destroy();
};
// shift tab
if (event.shiftKey && event.keyCode == 9 && document.activeElement == allSuggestItems[0]) {
event.preventDefault();
elementToFocus = _currentInputOptions.input;
};
if (event.shiftKey && event.keyCode == 9 && document.activeElement == _currentInputOptions.input) {
destroy();
};
};
_findInput();
_findFocus();
_keyEvents();
if (elementToFocus) {
elementToFocus.focus();
};
};
var _addDocumentEvent = function() {
document.addEventListener("click", _checkClick, false);
document.addEventListener("keydown", _navigateResults, false);
};
var _removeDocumentEvent = function() {
document.removeEventListener("click", _checkClick, false);
document.removeEventListener("keydown", _navigateResults, false);
};
var _checkClick = function(event) {
if (!(event.target.classList.contains("auto-suggest-list")) && !(event.target.classList.contains("auto-suggest-input"))) {
destroy();
};
};
var destroy = function() {
var autoSuggestList = helper.e(".auto-suggest-list");
if (autoSuggestList) {
autoSuggestList.remove();
_removeDocumentEvent();
helper.setObject({
object: state.get(),
path: "autoSuggest",
newValue: false
});
_currentInputOptions = {};
_autoSuggestActive = false;
};
};
var _getSuggestItems = function() {
var searchTerm = _currentInputOptions.input.value.replace(/^\s+/, "").replace(/\s+$/, "").toLowerCase();
var action = {
fontawesomeIcon: function() {
if (searchTerm == "" || searchTerm == undefined) {
return fontawesome.icons;
} else {
return fontawesome.icons.filter(function(item) {
var match = false;
if (item.name.toLowerCase().includes(searchTerm) || item.label.toLowerCase().includes(searchTerm)) {
match = true;
};
item.search.forEach(function(item, index) {
if (item.toLowerCase().includes(searchTerm)) {
match = true;
};
});
item.styles.forEach(function(item, index) {
if (item.toLowerCase().includes(searchTerm)) {
match = true;
};
});
return match;
});
};
}
};
return action[_currentInputOptions.type]();
};
var render = function(options) {
_currentInputOptions = options;
var body = helper.e("body");
var suggestItems = _getSuggestItems(options);
var _populateList = function(list) {
var action = {
fontawesomeIcon: function() {
suggestItems.forEach(function(arrayItem) {
var li = helper.node("li|class:auto-suggest-list-item");
var anchor = helper.node("a|href:#,tabindex:1,class:auto-suggest-link");
var icon = helper.node("span|class:auto-suggest-icon fa-" + arrayItem.name);
if (arrayItem.styles.includes("solid")) {
helper.addClass(icon, "fas");
} else if (arrayItem.styles.includes("brands")) {
helper.addClass(icon, "fab");
};
anchor.addEventListener("click", function() {
link.autoSuggestIconAction(arrayItem);
}, false);
var text = helper.node("span:" + arrayItem.label + "|class:auto-suggest-icon-text");
anchor.appendChild(icon);
anchor.appendChild(text);
li.appendChild(anchor);
list.appendChild(li);
});
}
};
action[_currentInputOptions.type]();
};
var _render_autoSuggestList = function() {
var autoSuggestWrapper = helper.e(".auto-suggest-wrapper");
var autoSuggestList = helper.e(".auto-suggest-list");
if (autoSuggestList) {
while (autoSuggestList.lastChild) {
autoSuggestList.removeChild(autoSuggestList.lastChild);
};
} else {
var style = {
left: autoSuggestWrapper.getBoundingClientRect().left,
top: autoSuggestWrapper.getBoundingClientRect().bottom + window.scrollY,
width: autoSuggestWrapper.getBoundingClientRect().width
};
var autoSuggestList = helper.node("ul|class:auto-suggest-list list-unstyled");
body.appendChild(autoSuggestList);
autoSuggestList.setAttribute("style", "width: " + style.width + "px; top: " + style.top + "px; left: " + style.left + "px;");
_addDocumentEvent();
};
_populateList(autoSuggestList);
};
if (suggestItems.length > 0) {
_autoSuggestActive = true;
helper.setObject({
object: state.get(),
path: "autoSuggest",
newValue: true
});
_render_autoSuggestList();
} else {
destroy();
};
};
// exposed methods
return {
bind: bind,
destroy: destroy
};
})();