From 55a0e61789acddf3756c56f76de90e5fbf345bbd Mon Sep 17 00:00:00 2001 From: Rafael Costa Date: Mon, 20 Nov 2023 12:44:22 -0300 Subject: [PATCH 1/2] feat: pesquisar perguntas melhorado --- api/src/Controllers/PerguntaController.php | 4 +- api/src/Gateways/PerguntaGateway.php | 17 +- index.js | 112 ++- index.php | 10 +- scripts/autocomplete/autoComplete.js | 636 ++++++++++++++++++ scripts/autocomplete/css/autoComplete.01.css | 92 +++ scripts/autocomplete/css/autoComplete.02.css | 82 +++ scripts/autocomplete/css/autoComplete.css | 128 ++++ .../autocomplete/css/autoComplete.custom.css | 129 ++++ scripts/autocomplete/css/images/magnifier.svg | 3 + scripts/autocomplete/css/images/search.svg | 8 + scripts/perguntas/listarPerguntas.js | 3 +- style.css | 10 +- styles/global.css | 2 + 14 files changed, 1201 insertions(+), 35 deletions(-) create mode 100644 scripts/autocomplete/autoComplete.js create mode 100644 scripts/autocomplete/css/autoComplete.01.css create mode 100644 scripts/autocomplete/css/autoComplete.02.css create mode 100644 scripts/autocomplete/css/autoComplete.css create mode 100644 scripts/autocomplete/css/autoComplete.custom.css create mode 100644 scripts/autocomplete/css/images/magnifier.svg create mode 100644 scripts/autocomplete/css/images/search.svg diff --git a/api/src/Controllers/PerguntaController.php b/api/src/Controllers/PerguntaController.php index d2ab21e..cef6282 100644 --- a/api/src/Controllers/PerguntaController.php +++ b/api/src/Controllers/PerguntaController.php @@ -96,7 +96,9 @@ private function processCollectionRequest(string $method, array $ordenacao): voi $qtdPorPg = filter_input(INPUT_GET, "quantidade_por_pagina", FILTER_SANITIZE_NUMBER_INT) ?? 10; - echo json_encode($this->gateway->getAll($ordenacao, $pagina, $qtdPorPg, isset($_GET["order"]) ? $_GET["order"] : '')); + $titulo = $_GET['titulo'] ?? ''; + + echo json_encode($this->gateway->getAll($ordenacao, $pagina, $qtdPorPg, isset($_GET["order"]) ? $_GET["order"] : '', $titulo)); break; case "POST": $usuarioLogado = $this->authController->verifyAccessToken($this->config, $this->token); diff --git a/api/src/Gateways/PerguntaGateway.php b/api/src/Gateways/PerguntaGateway.php index b674e62..16bdba9 100644 --- a/api/src/Gateways/PerguntaGateway.php +++ b/api/src/Gateways/PerguntaGateway.php @@ -9,10 +9,15 @@ public function __construct(Database $database) $this->conn = $database->getConnection(); } - public function getAll(array $ordenacao, $pagina = 1, $qtdPorPg = 10, $order = "asc"): array + public function getAll(array $ordenacao, $pagina = 1, $qtdPorPg = 10, $order = "asc", $titulo = ''): array { - $sql = "SELECT COUNT(*) AS qtd_pg FROM pergunta"; - $stmt = $this->conn->query($sql); + $tituloParam = '%' . $titulo . '%'; + + $sql = "SELECT COUNT(*) AS qtd_pg FROM pergunta WHERE pergunta LIKE :titulo"; + $stmt = $this->conn->prepare($sql); + $stmt->bindParam(':titulo', $tituloParam, PDO::PARAM_STR); + $stmt->execute(); + $result = $stmt->fetch(PDO::FETCH_ASSOC); $qtd_pg = ceil($result["qtd_pg"] / $qtdPorPg); @@ -36,6 +41,7 @@ public function getAll(array $ordenacao, $pagina = 1, $qtdPorPg = 10, $order = " LEFT JOIN usuario u ON p.criado_por = u.id LEFT JOIN pergunta_editada_por pe ON p.id = pe.pergunta_id LEFT JOIN usuario ue ON pe.usuario_id = ue.id + WHERE p.pergunta LIKE :titulo ORDER BY p.id $order LIMIT :limit OFFSET :offset "; @@ -53,6 +59,7 @@ public function getAll(array $ordenacao, $pagina = 1, $qtdPorPg = 10, $order = " LEFT JOIN usuario u ON p.criado_por = u.id LEFT JOIN pergunta_editada_por pe ON p.id = pe.pergunta_id LEFT JOIN usuario ue ON pe.usuario_id = ue.id + WHERE p.pergunta LIKE :titulo ORDER BY CASE WHEN prioridade = 'Alta' THEN 1 @@ -75,11 +82,15 @@ public function getAll(array $ordenacao, $pagina = 1, $qtdPorPg = 10, $order = " LEFT JOIN usuario u ON p.criado_por = u.id LEFT JOIN pergunta_editada_por pe ON p.id = pe.pergunta_id LEFT JOIN usuario ue ON pe.usuario_id = ue.id + WHERE p.pergunta LIKE :titulo ORDER BY curtidas DESC LIMIT :limit OFFSET :offset"; } + + $stmt = $this->conn->prepare($sql); + $stmt->bindParam(':titulo', $tituloParam, PDO::PARAM_STR); $stmt->bindParam(":limit", $qtdPorPg, PDO::PARAM_INT); $stmt->bindParam(":offset", $offset, PDO::PARAM_INT); $stmt->execute(); diff --git a/index.js b/index.js index eddf035..fac87d1 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,4 @@ +import './scripts/autocomplete/autoComplete.js'; import { decrementarCurtidas } from './scripts/perguntas/decrementarCurtidas.js'; import { incrementarCurtidas } from './scripts/perguntas/incrementarCurtidas.js'; import { listarPerguntas } from './scripts/perguntas/listarPerguntas.js'; @@ -25,13 +26,16 @@ pgNumerosPerguntas.innerHTML = ` let paginas = 1; let qtdPgs = 0; +let loading = false; const renderPerguntas = async ({ maisAlta = true, pagina = 1, qtdPorPg = 20, order = 'asc', + titulo = '', } = {}) => { try { + loading = true; spinnerContainer.classList.add('mostrar'); questionsContainer.innerHTML = ''; pgNumerosPerguntas.innerHTML = ''; @@ -41,6 +45,7 @@ const renderPerguntas = async ({ pagina, qtdPorPg, order, + titulo, }); paginas = perguntas.pagina; @@ -86,26 +91,6 @@ const renderPerguntas = async ({ ) .join(''); - // pega todas as divs containers que tem a tag faq-container para filtrar - const form = document.querySelector('form'); - const containers = document.querySelectorAll('.faq-container'); - form.addEventListener('keyup', (event) => { - event.preventDefault(); - const searchValue = form.querySelector('input').value.toLowerCase(); - containers.forEach((container) => { - const questionTitleText = container - .querySelector('.question-title') - .textContent.toLowerCase(); - const content = container.querySelector('.content').textContent.toLowerCase(); - - if (questionTitleText.includes(searchValue) || content.includes(searchValue)) { - container.style.display = 'block'; - } else { - container.style.display = 'none'; - } - }); - }); - //deixa o coração vermelho ao clicar e chama a funçao de incrementar const hearts = document.querySelectorAll('.heart'); let idCurtidasLocalStorage = localStorage.getItem('idCurtidas'); @@ -159,6 +144,7 @@ const renderPerguntas = async ({ toast('Houve um erro ao carregar as perguntas', true); console.log(error); } finally { + loading = false; spinnerContainer.classList.remove('mostrar'); window.scrollTo({ top: 0, @@ -228,3 +214,89 @@ pgUltimoPerguntas.addEventListener('click', async function () { pagina: qtdPgs, }); }); + +const autoCompleteJS = new autoComplete({ + data: { + src: async () => { + try { + document.getElementById('autoComplete').disabled = true; + document.getElementById('autoComplete').setAttribute('placeholder', 'Carregando...'); + + const data = await listarPerguntas({ qtdPorPg: 2000 }); + + document + .getElementById('autoComplete') + .setAttribute('placeholder', autoCompleteJS.placeHolder); + + const { resultado } = data; + + const perguntasArray = resultado.map((item) => item.pergunta); + + return perguntasArray; + } catch (error) { + return error; + } finally { + document.getElementById('autoComplete').disabled = false; + } + }, + cache: true, + }, + placeHolder: 'Quando abre o vestibular?', + resultsList: { + element: (list, data) => { + const info = document.createElement('p'); + if (data.results.length > 0) { + info.innerHTML = `Mostrando ${data.results.length} de ${data.matches.length} resultados`; + } else { + info.innerHTML = `Encontrado ${data.matches.length} resultados que combinam com "${data.query}"`; + } + list.prepend(info); + }, + noResults: true, + tabSelect: true, + }, + resultItem: { + element: (item, data) => { + item.style = 'display: flex; justify-content: space-between;'; + item.innerHTML = ` + + ${data.match} + + `; + }, + highlight: true, + }, + events: { + input: { + focus: () => { + if (autoCompleteJS.input.value.length) autoCompleteJS.start(); + }, + }, + }, +}); + +autoCompleteJS.input.addEventListener('input', async function (event) { + if (loading) return; + if (!event.target.value) { + await renderPerguntas(); + } +}); + +autoCompleteJS.input.addEventListener('results', async function (event) { + if (loading) return; + await renderPerguntas({ + titulo: event.detail.query, + }); +}); + +autoCompleteJS.input.addEventListener('selection', async function (event) { + if (loading) return; + const feedback = event.detail; + autoCompleteJS.input.blur(); + + document.querySelector('#autoComplete'); + autoCompleteJS.input.value = feedback.selection.value; + await renderPerguntas({ + titulo: feedback.selection.value, + }); +}); diff --git a/index.php b/index.php index 41f4a27..36c29d1 100644 --- a/index.php +++ b/index.php @@ -16,6 +16,7 @@ + @@ -32,12 +33,9 @@

Filtre sua dúvida

-
-
- - -
-
+
+ +
diff --git a/scripts/autocomplete/autoComplete.js b/scripts/autocomplete/autoComplete.js new file mode 100644 index 0000000..30b8c2e --- /dev/null +++ b/scripts/autocomplete/autoComplete.js @@ -0,0 +1,636 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.autoComplete = factory()); +})(this, (function () { 'use strict'; + + function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + enumerableOnly && (symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + })), keys.push.apply(keys, symbols); + } + + return keys; + } + + function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = null != arguments[i] ? arguments[i] : {}; + i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { + _defineProperty(target, key, source[key]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + + return target; + } + + function _typeof(obj) { + "@babel/helpers - typeof"; + + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { + return typeof obj; + } : function (obj) { + return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }, _typeof(obj); + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _createForOfIteratorHelper(o, allowArrayLike) { + var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + + if (!it) { + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; + var i = 0; + + var F = function () {}; + + return { + s: F, + n: function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = it.call(o); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; + } + + var select$1 = function select(element) { + return typeof element === "string" ? document.querySelector(element) : element(); + }; + var create = function create(tag, options) { + var el = typeof tag === "string" ? document.createElement(tag) : tag; + for (var key in options) { + var val = options[key]; + if (key === "inside") { + val.append(el); + } else if (key === "dest") { + select$1(val[0]).insertAdjacentElement(val[1], el); + } else if (key === "around") { + var ref = val; + ref.parentNode.insertBefore(el, ref); + el.append(ref); + if (ref.getAttribute("autofocus") != null) ref.focus(); + } else if (key in el) { + el[key] = val; + } else { + el.setAttribute(key, val); + } + } + return el; + }; + var getQuery = function getQuery(field) { + return field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement ? field.value : field.innerHTML; + }; + var format = function format(value, diacritics) { + value = String(value).toLowerCase(); + return diacritics ? value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").normalize("NFC") : value; + }; + var debounce = function debounce(callback, duration) { + var timer; + return function () { + clearTimeout(timer); + timer = setTimeout(function () { + return callback(); + }, duration); + }; + }; + var checkTrigger = function checkTrigger(query, condition, threshold) { + return condition ? condition(query) : query.length >= threshold; + }; + var mark = function mark(value, cls) { + return create("mark", _objectSpread2({ + innerHTML: value + }, typeof cls === "string" && { + "class": cls + })).outerHTML; + }; + + var configure = (function (ctx) { + var name = ctx.name, + options = ctx.options, + resultsList = ctx.resultsList, + resultItem = ctx.resultItem; + for (var option in options) { + if (_typeof(options[option]) === "object") { + if (!ctx[option]) ctx[option] = {}; + for (var subOption in options[option]) { + ctx[option][subOption] = options[option][subOption]; + } + } else { + ctx[option] = options[option]; + } + } + ctx.selector = ctx.selector || "#" + name; + resultsList.destination = resultsList.destination || ctx.selector; + resultsList.id = resultsList.id || name + "_list_" + ctx.id; + resultItem.id = resultItem.id || name + "_result"; + ctx.input = select$1(ctx.selector); + }); + + var eventEmitter = (function (name, ctx) { + ctx.input.dispatchEvent(new CustomEvent(name, { + bubbles: true, + detail: ctx.feedback, + cancelable: true + })); + }); + + var search = (function (query, record, options) { + var _ref = options || {}, + mode = _ref.mode, + diacritics = _ref.diacritics, + highlight = _ref.highlight; + var nRecord = format(record, diacritics); + record = String(record); + query = format(query, diacritics); + if (mode === "loose") { + query = query.replace(/ /g, ""); + var qLength = query.length; + var cursor = 0; + var match = Array.from(record).map(function (character, index) { + if (cursor < qLength && nRecord[index] === query[cursor]) { + character = highlight ? mark(character, highlight) : character; + cursor++; + } + return character; + }).join(""); + if (cursor === qLength) return match; + } else { + var _match = nRecord.indexOf(query); + if (~_match) { + query = record.substring(_match, _match + query.length); + _match = highlight ? record.replace(query, mark(query, highlight)) : record; + return _match; + } + } + }); + + var getData = function getData(ctx, query) { + return new Promise(function ($return, $error) { + var data; + data = ctx.data; + if (data.cache && data.store) return $return(); + return new Promise(function ($return, $error) { + if (typeof data.src === "function") { + return data.src(query).then($return, $error); + } + return $return(data.src); + }).then(function ($await_4) { + try { + ctx.feedback = data.store = $await_4; + eventEmitter("response", ctx); + return $return(); + } catch ($boundEx) { + return $error($boundEx); + } + }, $error); + }); + }; + var findMatches = function findMatches(query, ctx) { + var data = ctx.data, + searchEngine = ctx.searchEngine; + var matches = []; + data.store.forEach(function (value, index) { + var find = function find(key) { + var record = key ? value[key] : value; + var match = typeof searchEngine === "function" ? searchEngine(query, record) : search(query, record, { + mode: searchEngine, + diacritics: ctx.diacritics, + highlight: ctx.resultItem.highlight + }); + if (!match) return; + var result = { + match: match, + value: value + }; + if (key) result.key = key; + matches.push(result); + }; + if (data.keys) { + var _iterator = _createForOfIteratorHelper(data.keys), + _step; + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var key = _step.value; + find(key); + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); + } + } else { + find(); + } + }); + if (data.filter) matches = data.filter(matches); + var results = matches.slice(0, ctx.resultsList.maxResults); + ctx.feedback = { + query: query, + matches: matches, + results: results + }; + eventEmitter("results", ctx); + }; + + var Expand = "aria-expanded"; + var Active = "aria-activedescendant"; + var Selected = "aria-selected"; + var feedback = function feedback(ctx, index) { + ctx.feedback.selection = _objectSpread2({ + index: index + }, ctx.feedback.results[index]); + }; + var render = function render(ctx) { + var resultsList = ctx.resultsList, + list = ctx.list, + resultItem = ctx.resultItem, + feedback = ctx.feedback; + var matches = feedback.matches, + results = feedback.results; + ctx.cursor = -1; + list.innerHTML = ""; + if (matches.length || resultsList.noResults) { + var fragment = new DocumentFragment(); + results.forEach(function (result, index) { + var element = create(resultItem.tag, _objectSpread2({ + id: "".concat(resultItem.id, "_").concat(index), + role: "option", + innerHTML: result.match, + inside: fragment + }, resultItem["class"] && { + "class": resultItem["class"] + })); + if (resultItem.element) resultItem.element(element, result); + }); + list.append(fragment); + if (resultsList.element) resultsList.element(list, feedback); + open(ctx); + } else { + close(ctx); + } + }; + var open = function open(ctx) { + if (ctx.isOpen) return; + (ctx.wrapper || ctx.input).setAttribute(Expand, true); + ctx.list.removeAttribute("hidden"); + ctx.isOpen = true; + eventEmitter("open", ctx); + }; + var close = function close(ctx) { + if (!ctx.isOpen) return; + (ctx.wrapper || ctx.input).setAttribute(Expand, false); + ctx.input.setAttribute(Active, ""); + ctx.list.setAttribute("hidden", ""); + ctx.isOpen = false; + eventEmitter("close", ctx); + }; + var goTo = function goTo(index, ctx) { + var resultItem = ctx.resultItem; + var results = ctx.list.getElementsByTagName(resultItem.tag); + var cls = resultItem.selected ? resultItem.selected.split(" ") : false; + if (ctx.isOpen && results.length) { + var _results$index$classL; + var state = ctx.cursor; + if (index >= results.length) index = 0; + if (index < 0) index = results.length - 1; + ctx.cursor = index; + if (state > -1) { + var _results$state$classL; + results[state].removeAttribute(Selected); + if (cls) (_results$state$classL = results[state].classList).remove.apply(_results$state$classL, _toConsumableArray(cls)); + } + results[index].setAttribute(Selected, true); + if (cls) (_results$index$classL = results[index].classList).add.apply(_results$index$classL, _toConsumableArray(cls)); + ctx.input.setAttribute(Active, results[ctx.cursor].id); + ctx.list.scrollTop = results[index].offsetTop - ctx.list.clientHeight + results[index].clientHeight + 5; + ctx.feedback.cursor = ctx.cursor; + feedback(ctx, index); + eventEmitter("navigate", ctx); + } + }; + var next = function next(ctx) { + goTo(ctx.cursor + 1, ctx); + }; + var previous = function previous(ctx) { + goTo(ctx.cursor - 1, ctx); + }; + var select = function select(ctx, event, index) { + index = index >= 0 ? index : ctx.cursor; + if (index < 0) return; + ctx.feedback.event = event; + feedback(ctx, index); + eventEmitter("selection", ctx); + close(ctx); + }; + var click = function click(event, ctx) { + var itemTag = ctx.resultItem.tag.toUpperCase(); + var items = Array.from(ctx.list.querySelectorAll(itemTag)); + var item = event.target.closest(itemTag); + if (item && item.nodeName === itemTag) { + select(ctx, event, items.indexOf(item)); + } + }; + var navigate = function navigate(event, ctx) { + switch (event.keyCode) { + case 40: + case 38: + event.preventDefault(); + event.keyCode === 40 ? next(ctx) : previous(ctx); + break; + case 13: + if (!ctx.submit) event.preventDefault(); + if (ctx.cursor >= 0) select(ctx, event); + break; + case 9: + if (ctx.resultsList.tabSelect && ctx.cursor >= 0) select(ctx, event); + break; + case 27: + ctx.input.value = ""; + close(ctx); + break; + } + }; + + function start (ctx, q) { + var _this = this; + return new Promise(function ($return, $error) { + var queryVal, condition; + queryVal = q || getQuery(ctx.input); + queryVal = ctx.query ? ctx.query(queryVal) : queryVal; + condition = checkTrigger(queryVal, ctx.trigger, ctx.threshold); + if (condition) { + return getData(ctx, queryVal).then(function ($await_2) { + try { + if (ctx.feedback instanceof Error) return $return(); + findMatches(queryVal, ctx); + if (ctx.resultsList) render(ctx); + return $If_1.call(_this); + } catch ($boundEx) { + return $error($boundEx); + } + }, $error); + } else { + close(ctx); + return $If_1.call(_this); + } + function $If_1() { + return $return(); + } + }); + } + + var eventsManager = function eventsManager(events, callback) { + for (var element in events) { + for (var event in events[element]) { + callback(element, event); + } + } + }; + var addEvents = function addEvents(ctx) { + var events = ctx.events; + var run = debounce(function () { + return start(ctx); + }, ctx.debounce); + var publicEvents = ctx.events = _objectSpread2({ + input: _objectSpread2({}, events && events.input) + }, ctx.resultsList && { + list: events ? _objectSpread2({}, events.list) : {} + }); + var privateEvents = { + input: { + input: function input() { + run(); + }, + keydown: function keydown(event) { + navigate(event, ctx); + }, + blur: function blur() { + close(ctx); + } + }, + list: { + mousedown: function mousedown(event) { + event.preventDefault(); + }, + click: function click$1(event) { + click(event, ctx); + } + } + }; + eventsManager(privateEvents, function (element, event) { + if (!ctx.resultsList && event !== "input") return; + if (publicEvents[element][event]) return; + publicEvents[element][event] = privateEvents[element][event]; + }); + eventsManager(publicEvents, function (element, event) { + ctx[element].addEventListener(event, publicEvents[element][event]); + }); + }; + var removeEvents = function removeEvents(ctx) { + eventsManager(ctx.events, function (element, event) { + ctx[element].removeEventListener(event, ctx.events[element][event]); + }); + }; + + function init (ctx) { + var _this = this; + return new Promise(function ($return, $error) { + var placeHolder, resultsList, parentAttrs; + placeHolder = ctx.placeHolder; + resultsList = ctx.resultsList; + parentAttrs = { + role: "combobox", + "aria-owns": resultsList.id, + "aria-haspopup": true, + "aria-expanded": false + }; + create(ctx.input, _objectSpread2(_objectSpread2({ + "aria-controls": resultsList.id, + "aria-autocomplete": "both" + }, placeHolder && { + placeholder: placeHolder + }), !ctx.wrapper && _objectSpread2({}, parentAttrs))); + if (ctx.wrapper) ctx.wrapper = create("div", _objectSpread2({ + around: ctx.input, + "class": ctx.name + "_wrapper" + }, parentAttrs)); + if (resultsList) ctx.list = create(resultsList.tag, _objectSpread2({ + dest: [resultsList.destination, resultsList.position], + id: resultsList.id, + role: "listbox", + hidden: "hidden" + }, resultsList["class"] && { + "class": resultsList["class"] + })); + addEvents(ctx); + if (ctx.data.cache) { + return getData(ctx).then(function ($await_2) { + try { + return $If_1.call(_this); + } catch ($boundEx) { + return $error($boundEx); + } + }, $error); + } + function $If_1() { + eventEmitter("init", ctx); + return $return(); + } + return $If_1.call(_this); + }); + } + + function extend (autoComplete) { + var prototype = autoComplete.prototype; + prototype.init = function () { + init(this); + }; + prototype.start = function (query) { + start(this, query); + }; + prototype.unInit = function () { + if (this.wrapper) { + var parentNode = this.wrapper.parentNode; + parentNode.insertBefore(this.input, this.wrapper); + parentNode.removeChild(this.wrapper); + } + removeEvents(this); + }; + prototype.open = function () { + open(this); + }; + prototype.close = function () { + close(this); + }; + prototype.goTo = function (index) { + goTo(index, this); + }; + prototype.next = function () { + next(this); + }; + prototype.previous = function () { + previous(this); + }; + prototype.select = function (index) { + select(this, null, index); + }; + prototype.search = function (query, record, options) { + return search(query, record, options); + }; + } + + function autoComplete(config) { + this.options = config; + this.id = autoComplete.instances = (autoComplete.instances || 0) + 1; + this.name = "autoComplete"; + this.wrapper = 1; + this.threshold = 1; + this.debounce = 0; + this.resultsList = { + position: "afterend", + tag: "ul", + maxResults: 5 + }; + this.resultItem = { + tag: "li" + }; + configure(this); + extend.call(this, autoComplete); + init(this); + } + + return autoComplete; + +})); diff --git a/scripts/autocomplete/css/autoComplete.01.css b/scripts/autocomplete/css/autoComplete.01.css new file mode 100644 index 0000000..4df567e --- /dev/null +++ b/scripts/autocomplete/css/autoComplete.01.css @@ -0,0 +1,92 @@ +.autoComplete_wrapper { + display: inline-block; + position: relative; +} + +.autoComplete_wrapper > input { + width: 370px; + height: 40px; + padding-left: 20px; + font-size: 1rem; + color: rgba(123, 123, 123, 1); + border-radius: 8px; + border: 0; + outline: none; + background-color: #f1f3f4; +} + +.autoComplete_wrapper > input::placeholder { + color: rgba(123, 123, 123, 0.5); + transition: all 0.3s ease; +} + +.autoComplete_wrapper > ul { + position: absolute; + max-height: 226px; + overflow-y: scroll; + top: 100%; + left: 0; + right: 0; + padding: 0; + margin: 0.5rem 0 0 0; + border-radius: 0.6rem; + background-color: #fff; + box-shadow: 0 3px 6px rgba(149, 157, 165, 0.15); + border: 1px solid rgba(33, 33, 33, 0.07); + z-index: 1000; + outline: none; +} + +.autoComplete_wrapper > ul[hidden], +.autoComplete_wrapper > ul:empty { + display: block; + opacity: 0; + transform: scale(0); +} + +.autoComplete_wrapper > ul > li { + margin: 0.3rem; + padding: 0.3rem 0.5rem; + list-style: none; + text-align: left; + font-size: 1rem; + color: #212121; + transition: all 0.1s ease-in-out; + border-radius: 0.35rem; + background-color: rgba(255, 255, 255, 1); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: all 0.2s ease; +} + +.autoComplete_wrapper > ul > li::selection { + color: rgba(#ffffff, 0); + background-color: rgba(#ffffff, 0); +} + +.autoComplete_wrapper > ul > li:hover { + cursor: pointer; + background-color: rgba(123, 123, 123, 0.1); +} + +.autoComplete_wrapper > ul > li mark { + background-color: transparent; + color: rgba(255, 122, 122, 1); + font-weight: bold; +} + +.autoComplete_wrapper > ul > li mark::selection { + color: rgba(#ffffff, 0); + background-color: rgba(#ffffff, 0); +} + +.autoComplete_wrapper > ul > li[aria-selected="true"] { + background-color: rgba(123, 123, 123, 0.1); +} + +@media only screen and (max-width: 600px) { + .autoComplete_wrapper > input { + width: 18rem; + } +} diff --git a/scripts/autocomplete/css/autoComplete.02.css b/scripts/autocomplete/css/autoComplete.02.css new file mode 100644 index 0000000..e9e233c --- /dev/null +++ b/scripts/autocomplete/css/autoComplete.02.css @@ -0,0 +1,82 @@ +.autoComplete_wrapper { + display: inline-block; + position: relative; +} + +.autoComplete_wrapper > input { + width: 370px; + height: 40px; + padding-left: 10px; + font-size: 1rem; + color: rgb(116, 116, 116); + border-radius: 4px; + border: 1px solid rgba(33, 33, 33, 0.2); + outline: none; +} + +.autoComplete_wrapper > input::placeholder { + color: rgba(123, 123, 123, 0.5); + transition: all 0.3s ease; +} + +.autoComplete_wrapper > ul { + position: absolute; + max-height: 226px; + overflow-y: scroll; + top: 100%; + left: 0; + right: 0; + padding: 0; + margin: 0.5rem 0 0 0; + border-radius: 4px; + background-color: #fff; + border: 1px solid rgba(33, 33, 33, 0.1); + z-index: 1000; + outline: none; +} + +.autoComplete_wrapper > ul > li { + padding: 10px 20px; + list-style: none; + text-align: left; + font-size: 16px; + color: #212121; + transition: all 0.1s ease-in-out; + border-radius: 3px; + background-color: rgba(255, 255, 255, 1); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: all 0.2s ease; +} + +.autoComplete_wrapper > ul > li::selection { + color: rgba(#ffffff, 0); + background-color: rgba(#ffffff, 0); +} + +.autoComplete_wrapper > ul > li:hover { + cursor: pointer; + background-color: rgba(123, 123, 123, 0.1); +} + +.autoComplete_wrapper > ul > li mark { + background-color: transparent; + color: rgba(255, 122, 122, 1); + font-weight: bold; +} + +.autoComplete_wrapper > ul > li mark::selection { + color: rgba(#ffffff, 0); + background-color: rgba(#ffffff, 0); +} + +.autoComplete_wrapper > ul > li[aria-selected="true"] { + background-color: rgba(123, 123, 123, 0.1); +} + +@media only screen and (max-width: 600px) { + .autoComplete_wrapper > input { + width: 18rem; + } +} diff --git a/scripts/autocomplete/css/autoComplete.css b/scripts/autocomplete/css/autoComplete.css new file mode 100644 index 0000000..3bd94d2 --- /dev/null +++ b/scripts/autocomplete/css/autoComplete.css @@ -0,0 +1,128 @@ +.autoComplete_wrapper { + display: inline-block; + position: relative; +} + +.autoComplete_wrapper > input { + height: 3rem; + width: 370px; + margin: 0; + padding: 0 2rem 0 3.2rem; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + font-size: 1rem; + text-overflow: ellipsis; + color: rgba(255, 122, 122, 0.3); + outline: none; + border-radius: 10rem; + border: 0.05rem solid rgba(255, 122, 122, 0.5); + background-image: url(./images/search.svg); + background-size: 1.4rem; + background-position: left 1.05rem top 0.8rem; + background-repeat: no-repeat; + background-origin: border-box; + background-color: #fff; + transition: all 0.4s ease; + -webkit-transition: all -webkit-transform 0.4s ease; +} + +.autoComplete_wrapper > input::placeholder { + color: rgba(255, 122, 122, 0.5); + transition: all 0.3s ease; + -webkit-transition: all -webkit-transform 0.3s ease; +} + +.autoComplete_wrapper > input:hover::placeholder { + color: rgba(255, 122, 122, 0.6); + transition: all 0.3s ease; + -webkit-transition: all -webkit-transform 0.3s ease; +} + +.autoComplete_wrapper > input:focus::placeholder { + padding: 0.1rem 0.6rem; + font-size: 0.95rem; + color: rgba(255, 122, 122, 0.4); +} + +.autoComplete_wrapper > input:focus::selection { + background-color: rgba(255, 122, 122, 0.15); +} + +.autoComplete_wrapper > input::selection { + background-color: rgba(255, 122, 122, 0.15); +} + +.autoComplete_wrapper > input:hover { + color: rgba(255, 122, 122, 0.8); + transition: all 0.3s ease; + -webkit-transition: all -webkit-transform 0.3s ease; +} + +.autoComplete_wrapper > input:focus { + color: rgba(255, 122, 122, 1); + border: 0.06rem solid rgba(255, 122, 122, 0.8); +} + +.autoComplete_wrapper > ul { + position: absolute; + max-height: 226px; + overflow-y: scroll; + box-sizing: border-box; + left: 0; + right: 0; + margin: 0.5rem 0 0 0; + padding: 0; + z-index: 1; + list-style: none; + border-radius: 0.6rem; + background-color: #fff; + border: 1px solid rgba(33, 33, 33, 0.07); + box-shadow: 0 3px 6px rgba(149, 157, 165, 0.15); + outline: none; + transition: opacity 0.15s ease-in-out; + -moz-transition: opacity 0.15s ease-in-out; + -webkit-transition: opacity 0.15s ease-in-out; +} + +.autoComplete_wrapper > ul[hidden], +.autoComplete_wrapper > ul:empty { + display: block; + opacity: 0; + transform: scale(0); +} + +.autoComplete_wrapper > ul > li { + margin: 0.3rem; + padding: 0.3rem 0.5rem; + text-align: left; + font-size: 1rem; + color: #212121; + border-radius: 0.35rem; + background-color: rgba(255, 255, 255, 1); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: all 0.2s ease; +} + +.autoComplete_wrapper > ul > li mark { + background-color: transparent; + color: rgba(255, 122, 122, 1); + font-weight: bold; +} + +.autoComplete_wrapper > ul > li:hover { + cursor: pointer; + background-color: rgba(255, 122, 122, 0.15); +} + +.autoComplete_wrapper > ul > li[aria-selected="true"] { + background-color: rgba(255, 122, 122, 0.15); +} + +@media only screen and (max-width: 600px) { + .autoComplete_wrapper > input { + width: 18rem; + } +} diff --git a/scripts/autocomplete/css/autoComplete.custom.css b/scripts/autocomplete/css/autoComplete.custom.css new file mode 100644 index 0000000..c3a4d60 --- /dev/null +++ b/scripts/autocomplete/css/autoComplete.custom.css @@ -0,0 +1,129 @@ +.autoComplete_wrapper { + display: inline-block; + position: relative; +} + +.autoComplete_wrapper > input { + height: 5rem; + width: 520px; + margin: 0; + padding: 0 2rem 0 3.2rem; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + font-size: 2rem; + text-overflow: ellipsis; + outline: none; + border-radius: 12px; + border: none; + background-image: url(./images/search.svg); + background-size: 2rem; + background-position: left 1.05rem top 1.5rem; + background-repeat: no-repeat; + background-origin: border-box; + background-color: #fff; + transition: all 0.4s ease; + -webkit-transition: all -webkit-transform 0.4s ease; +} + +.autoComplete_wrapper > input::placeholder { + transition: all 0.3s ease; + -webkit-transition: all -webkit-transform 0.3s ease; +} + +.autoComplete_wrapper > input:hover::placeholder { + transition: all 0.3s ease; + -webkit-transition: all -webkit-transform 0.3s ease; +} + +.autoComplete_wrapper > input:focus::placeholder { + padding: 0.1rem 0.6rem; + font-size: 0.95rem; +} + +.autoComplete_wrapper > input:focus::selection { + background-color: rgba(255, 122, 122, 0.15); +} + +.autoComplete_wrapper > input::selection { + background-color: rgba(255, 122, 122, 0.15); +} + +.autoComplete_wrapper > input:hover { + transition: all 0.3s ease; + -webkit-transition: all -webkit-transform 0.3s ease; +} + +.autoComplete_wrapper > ul { + position: absolute; + max-height: 226px; + overflow-y: scroll; + box-sizing: border-box; + left: 0; + right: 0; + margin: 0.5rem 0 0 0; + padding: 0; + z-index: 1; + list-style: none; + border-radius: 0.6rem; + background-color: #fff; + border: 1px solid rgba(33, 33, 33, 0.07); + box-shadow: 0 3px 6px rgba(149, 157, 165, 0.15); + outline: none; + transition: opacity 0.15s ease-in-out; + -moz-transition: opacity 0.15s ease-in-out; + -webkit-transition: opacity 0.15s ease-in-out; +} + +.autoComplete_wrapper > ul[hidden], +.autoComplete_wrapper > ul:empty { + display: block; + opacity: 0; + transform: scale(0); +} + +.autoComplete_wrapper > ul > li { + margin: 0.3rem; + padding: 0.3rem 0.5rem; + text-align: left; + font-size: 2rem; + color: #212121; + border-radius: 0.35rem; + background-color: rgba(255, 255, 255, 1); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + transition: all 0.2s ease; +} + +.autoComplete_wrapper > ul > li mark { + background-color: transparent; + font-weight: bold; +} + +.autoComplete_wrapper > ul > li:hover { + cursor: pointer; + background-color: rgba(255, 122, 122, 0.15); +} + +.autoComplete_wrapper > ul > li[aria-selected='true'] { + background-color: rgba(255, 122, 122, 0.15); +} + +@media only screen and (max-width: 600px) { + .autoComplete_wrapper > input { + width: 30rem; + } +} + +@media only screen and (max-width: 320px) { + .autoComplete_wrapper > input { + width: 25rem; + } +} + +@media only screen and (max-width: 290px) { + .autoComplete_wrapper > input { + width: 20rem; + } +} diff --git a/scripts/autocomplete/css/images/magnifier.svg b/scripts/autocomplete/css/images/magnifier.svg new file mode 100644 index 0000000..2a0ee79 --- /dev/null +++ b/scripts/autocomplete/css/images/magnifier.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/scripts/autocomplete/css/images/search.svg b/scripts/autocomplete/css/images/search.svg new file mode 100644 index 0000000..0ad0df6 --- /dev/null +++ b/scripts/autocomplete/css/images/search.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/scripts/perguntas/listarPerguntas.js b/scripts/perguntas/listarPerguntas.js index 49ba09c..2ed95b2 100644 --- a/scripts/perguntas/listarPerguntas.js +++ b/scripts/perguntas/listarPerguntas.js @@ -5,10 +5,11 @@ export const listarPerguntas = async ({ pagina = 1, qtdPorPg = 5, order = 'asc', + titulo = '', } = {}) => { try { const response = await fetch( - `${apiUrl}/pergunta?mais-alta=${maisAlta}&pagina=${pagina}&quantidade_por_pagina=${qtdPorPg}&order=${order}`, + `${apiUrl}/pergunta?mais-alta=${maisAlta}&pagina=${pagina}&quantidade_por_pagina=${qtdPorPg}&order=${order}&titulo=${titulo}`, { method: 'GET', }, diff --git a/style.css b/style.css index 436bba7..165593e 100644 --- a/style.css +++ b/style.css @@ -11,6 +11,7 @@ section { .hamburger-open { margin-top: 15vh; } + .menu-hamburger-content { margin-top: 10px; } @@ -26,6 +27,7 @@ section { font-size: 4rem; font-weight: 500; color: var(--prata-base); + text-align: center; } #formulary { @@ -34,7 +36,7 @@ section { gap: 10px; } -#formulary #search-input { +#formulary .search-input { width: 100%; height: 100%; padding: 0 10px; @@ -46,11 +48,11 @@ section { padding: 0rem 5rem; } -#formulary #search-input::placeholder { +#formulary .search-input::placeholder { color: var(--cinza-texto); } -#formulary #search-input:focus { +#formulary .search-input:focus { outline: none; } @@ -216,7 +218,7 @@ main { margin: auto; } - #formulary #search-input { + #formulary .search-input { min-width: 300px; padding: 0 1rem; } diff --git a/styles/global.css b/styles/global.css index e1d3451..1d6c234 100644 --- a/styles/global.css +++ b/styles/global.css @@ -16,6 +16,8 @@ --cinza-hover: #e6e6e6; --preto-escuro: #121313; --preto-fraco: #262b2d; + --transition-1: all 0.3s ease-in-out; + --transition-2: all 0.2s ease-in-out; font-size: 62.5%; } From b6dcda5331db453d919d268d48770244840c7f5d Mon Sep 17 00:00:00 2001 From: rrafaelc Date: Mon, 20 Nov 2023 15:45:59 +0000 Subject: [PATCH 2/2] Prettified Code! --- scripts/autocomplete/autoComplete.js | 437 ++++++++++++------- scripts/autocomplete/css/autoComplete.01.css | 2 +- scripts/autocomplete/css/autoComplete.02.css | 2 +- scripts/autocomplete/css/autoComplete.css | 2 +- 4 files changed, 273 insertions(+), 170 deletions(-) diff --git a/scripts/autocomplete/autoComplete.js b/scripts/autocomplete/autoComplete.js index 30b8c2e..20788a3 100644 --- a/scripts/autocomplete/autoComplete.js +++ b/scripts/autocomplete/autoComplete.js @@ -1,17 +1,23 @@ (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.autoComplete = factory()); -})(this, (function () { 'use strict'; + typeof exports === 'object' && typeof module !== 'undefined' + ? (module.exports = factory()) + : typeof define === 'function' && define.amd + ? define(factory) + : ((global = typeof globalThis !== 'undefined' ? globalThis : global || self), + (global.autoComplete = factory())); +})(this, function () { + 'use strict'; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); - enumerableOnly && (symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - })), keys.push.apply(keys, symbols); + enumerableOnly && + (symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + })), + keys.push.apply(keys, symbols); } return keys; @@ -20,24 +26,39 @@ function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; - i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { - _defineProperty(target, key, source[key]); - }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); - }); + i % 2 + ? ownKeys(Object(source), !0).forEach(function (key) { + _defineProperty(target, key, source[key]); + }) + : Object.getOwnPropertyDescriptors + ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) + : ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); } return target; } function _typeof(obj) { - "@babel/helpers - typeof"; - - return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }, _typeof(obj); + '@babel/helpers - typeof'; + + return ( + (_typeof = + 'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator + ? function (obj) { + return typeof obj; + } + : function (obj) { + return obj && + 'function' == typeof Symbol && + obj.constructor === Symbol && + obj !== Symbol.prototype + ? 'symbol' + : typeof obj; + }), + _typeof(obj) + ); } function _defineProperty(obj, key, value) { @@ -46,7 +67,7 @@ value: value, enumerable: true, configurable: true, - writable: true + writable: true, }); } else { obj[key] = value; @@ -56,7 +77,12 @@ } function _toConsumableArray(arr) { - return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + return ( + _arrayWithoutHoles(arr) || + _iterableToArray(arr) || + _unsupportedIterableToArray(arr) || + _nonIterableSpread() + ); } function _arrayWithoutHoles(arr) { @@ -64,16 +90,21 @@ } function _iterableToArray(iter) { - if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + if ( + (typeof Symbol !== 'undefined' && iter[Symbol.iterator] != null) || + iter['@@iterator'] != null + ) + return Array.from(iter); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; - if (typeof o === "string") return _arrayLikeToArray(o, minLen); + if (typeof o === 'string') return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + if (n === 'Object' && o.constructor) n = o.constructor.name; + if (n === 'Map' || n === 'Set') return Array.from(o); + if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) + return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { @@ -85,14 +116,20 @@ } function _nonIterableSpread() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + throw new TypeError( + 'Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.', + ); } function _createForOfIteratorHelper(o, allowArrayLike) { - var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; + var it = (typeof Symbol !== 'undefined' && o[Symbol.iterator]) || o['@@iterator']; if (!it) { - if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if ( + Array.isArray(o) || + (it = _unsupportedIterableToArray(o)) || + (allowArrayLike && o && typeof o.length === 'number') + ) { if (it) o = it; var i = 0; @@ -101,27 +138,30 @@ return { s: F, n: function () { - if (i >= o.length) return { - done: true - }; + if (i >= o.length) + return { + done: true, + }; return { done: false, - value: o[i++] + value: o[i++], }; }, e: function (e) { throw e; }, - f: F + f: F, }; } - throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + throw new TypeError( + 'Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.', + ); } var normalCompletion = true, - didErr = false, - err; + didErr = false, + err; return { s: function () { it = it.call(o); @@ -141,26 +181,26 @@ } finally { if (didErr) throw err; } - } + }, }; } var select$1 = function select(element) { - return typeof element === "string" ? document.querySelector(element) : element(); + return typeof element === 'string' ? document.querySelector(element) : element(); }; var create = function create(tag, options) { - var el = typeof tag === "string" ? document.createElement(tag) : tag; + var el = typeof tag === 'string' ? document.createElement(tag) : tag; for (var key in options) { var val = options[key]; - if (key === "inside") { + if (key === 'inside') { val.append(el); - } else if (key === "dest") { + } else if (key === 'dest') { select$1(val[0]).insertAdjacentElement(val[1], el); - } else if (key === "around") { + } else if (key === 'around') { var ref = val; ref.parentNode.insertBefore(el, ref); el.append(ref); - if (ref.getAttribute("autofocus") != null) ref.focus(); + if (ref.getAttribute('autofocus') != null) ref.focus(); } else if (key in el) { el[key] = val; } else { @@ -170,11 +210,18 @@ return el; }; var getQuery = function getQuery(field) { - return field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement ? field.value : field.innerHTML; + return field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement + ? field.value + : field.innerHTML; }; var format = function format(value, diacritics) { value = String(value).toLowerCase(); - return diacritics ? value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").normalize("NFC") : value; + return diacritics + ? value + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .normalize('NFC') + : value; }; var debounce = function debounce(callback, duration) { var timer; @@ -189,20 +236,26 @@ return condition ? condition(query) : query.length >= threshold; }; var mark = function mark(value, cls) { - return create("mark", _objectSpread2({ - innerHTML: value - }, typeof cls === "string" && { - "class": cls - })).outerHTML; + return create( + 'mark', + _objectSpread2( + { + innerHTML: value, + }, + typeof cls === 'string' && { + class: cls, + }, + ), + ).outerHTML; }; - var configure = (function (ctx) { + var configure = function (ctx) { var name = ctx.name, - options = ctx.options, - resultsList = ctx.resultsList, - resultItem = ctx.resultItem; + options = ctx.options, + resultsList = ctx.resultsList, + resultItem = ctx.resultItem; for (var option in options) { - if (_typeof(options[option]) === "object") { + if (_typeof(options[option]) === 'object') { if (!ctx[option]) ctx[option] = {}; for (var subOption in options[option]) { ctx[option][subOption] = options[option][subOption]; @@ -211,40 +264,44 @@ ctx[option] = options[option]; } } - ctx.selector = ctx.selector || "#" + name; + ctx.selector = ctx.selector || '#' + name; resultsList.destination = resultsList.destination || ctx.selector; - resultsList.id = resultsList.id || name + "_list_" + ctx.id; - resultItem.id = resultItem.id || name + "_result"; + resultsList.id = resultsList.id || name + '_list_' + ctx.id; + resultItem.id = resultItem.id || name + '_result'; ctx.input = select$1(ctx.selector); - }); + }; - var eventEmitter = (function (name, ctx) { - ctx.input.dispatchEvent(new CustomEvent(name, { - bubbles: true, - detail: ctx.feedback, - cancelable: true - })); - }); + var eventEmitter = function (name, ctx) { + ctx.input.dispatchEvent( + new CustomEvent(name, { + bubbles: true, + detail: ctx.feedback, + cancelable: true, + }), + ); + }; - var search = (function (query, record, options) { + var search = function (query, record, options) { var _ref = options || {}, - mode = _ref.mode, - diacritics = _ref.diacritics, - highlight = _ref.highlight; + mode = _ref.mode, + diacritics = _ref.diacritics, + highlight = _ref.highlight; var nRecord = format(record, diacritics); record = String(record); query = format(query, diacritics); - if (mode === "loose") { - query = query.replace(/ /g, ""); + if (mode === 'loose') { + query = query.replace(/ /g, ''); var qLength = query.length; var cursor = 0; - var match = Array.from(record).map(function (character, index) { - if (cursor < qLength && nRecord[index] === query[cursor]) { - character = highlight ? mark(character, highlight) : character; - cursor++; - } - return character; - }).join(""); + var match = Array.from(record) + .map(function (character, index) { + if (cursor < qLength && nRecord[index] === query[cursor]) { + character = highlight ? mark(character, highlight) : character; + cursor++; + } + return character; + }) + .join(''); if (cursor === qLength) return match; } else { var _match = nRecord.indexOf(query); @@ -254,7 +311,7 @@ return _match; } } - }); + }; var getData = function getData(ctx, query) { return new Promise(function ($return, $error) { @@ -262,14 +319,14 @@ data = ctx.data; if (data.cache && data.store) return $return(); return new Promise(function ($return, $error) { - if (typeof data.src === "function") { + if (typeof data.src === 'function') { return data.src(query).then($return, $error); } return $return(data.src); }).then(function ($await_4) { try { ctx.feedback = data.store = $await_4; - eventEmitter("response", ctx); + eventEmitter('response', ctx); return $return(); } catch ($boundEx) { return $error($boundEx); @@ -279,29 +336,32 @@ }; var findMatches = function findMatches(query, ctx) { var data = ctx.data, - searchEngine = ctx.searchEngine; + searchEngine = ctx.searchEngine; var matches = []; data.store.forEach(function (value, index) { var find = function find(key) { var record = key ? value[key] : value; - var match = typeof searchEngine === "function" ? searchEngine(query, record) : search(query, record, { - mode: searchEngine, - diacritics: ctx.diacritics, - highlight: ctx.resultItem.highlight - }); + var match = + typeof searchEngine === 'function' + ? searchEngine(query, record) + : search(query, record, { + mode: searchEngine, + diacritics: ctx.diacritics, + highlight: ctx.resultItem.highlight, + }); if (!match) return; var result = { match: match, - value: value + value: value, }; if (key) result.key = key; matches.push(result); }; if (data.keys) { var _iterator = _createForOfIteratorHelper(data.keys), - _step; + _step; try { - for (_iterator.s(); !(_step = _iterator.n()).done;) { + for (_iterator.s(); !(_step = _iterator.n()).done; ) { var key = _step.value; find(key); } @@ -319,39 +379,48 @@ ctx.feedback = { query: query, matches: matches, - results: results + results: results, }; - eventEmitter("results", ctx); + eventEmitter('results', ctx); }; - var Expand = "aria-expanded"; - var Active = "aria-activedescendant"; - var Selected = "aria-selected"; + var Expand = 'aria-expanded'; + var Active = 'aria-activedescendant'; + var Selected = 'aria-selected'; var feedback = function feedback(ctx, index) { - ctx.feedback.selection = _objectSpread2({ - index: index - }, ctx.feedback.results[index]); + ctx.feedback.selection = _objectSpread2( + { + index: index, + }, + ctx.feedback.results[index], + ); }; var render = function render(ctx) { var resultsList = ctx.resultsList, - list = ctx.list, - resultItem = ctx.resultItem, - feedback = ctx.feedback; + list = ctx.list, + resultItem = ctx.resultItem, + feedback = ctx.feedback; var matches = feedback.matches, - results = feedback.results; + results = feedback.results; ctx.cursor = -1; - list.innerHTML = ""; + list.innerHTML = ''; if (matches.length || resultsList.noResults) { var fragment = new DocumentFragment(); results.forEach(function (result, index) { - var element = create(resultItem.tag, _objectSpread2({ - id: "".concat(resultItem.id, "_").concat(index), - role: "option", - innerHTML: result.match, - inside: fragment - }, resultItem["class"] && { - "class": resultItem["class"] - })); + var element = create( + resultItem.tag, + _objectSpread2( + { + id: ''.concat(resultItem.id, '_').concat(index), + role: 'option', + innerHTML: result.match, + inside: fragment, + }, + resultItem['class'] && { + class: resultItem['class'], + }, + ), + ); if (resultItem.element) resultItem.element(element, result); }); list.append(fragment); @@ -364,22 +433,22 @@ var open = function open(ctx) { if (ctx.isOpen) return; (ctx.wrapper || ctx.input).setAttribute(Expand, true); - ctx.list.removeAttribute("hidden"); + ctx.list.removeAttribute('hidden'); ctx.isOpen = true; - eventEmitter("open", ctx); + eventEmitter('open', ctx); }; var close = function close(ctx) { if (!ctx.isOpen) return; (ctx.wrapper || ctx.input).setAttribute(Expand, false); - ctx.input.setAttribute(Active, ""); - ctx.list.setAttribute("hidden", ""); + ctx.input.setAttribute(Active, ''); + ctx.list.setAttribute('hidden', ''); ctx.isOpen = false; - eventEmitter("close", ctx); + eventEmitter('close', ctx); }; var goTo = function goTo(index, ctx) { var resultItem = ctx.resultItem; var results = ctx.list.getElementsByTagName(resultItem.tag); - var cls = resultItem.selected ? resultItem.selected.split(" ") : false; + var cls = resultItem.selected ? resultItem.selected.split(' ') : false; if (ctx.isOpen && results.length) { var _results$index$classL; var state = ctx.cursor; @@ -389,15 +458,24 @@ if (state > -1) { var _results$state$classL; results[state].removeAttribute(Selected); - if (cls) (_results$state$classL = results[state].classList).remove.apply(_results$state$classL, _toConsumableArray(cls)); + if (cls) + (_results$state$classL = results[state].classList).remove.apply( + _results$state$classL, + _toConsumableArray(cls), + ); } results[index].setAttribute(Selected, true); - if (cls) (_results$index$classL = results[index].classList).add.apply(_results$index$classL, _toConsumableArray(cls)); + if (cls) + (_results$index$classL = results[index].classList).add.apply( + _results$index$classL, + _toConsumableArray(cls), + ); ctx.input.setAttribute(Active, results[ctx.cursor].id); - ctx.list.scrollTop = results[index].offsetTop - ctx.list.clientHeight + results[index].clientHeight + 5; + ctx.list.scrollTop = + results[index].offsetTop - ctx.list.clientHeight + results[index].clientHeight + 5; ctx.feedback.cursor = ctx.cursor; feedback(ctx, index); - eventEmitter("navigate", ctx); + eventEmitter('navigate', ctx); } }; var next = function next(ctx) { @@ -411,7 +489,7 @@ if (index < 0) return; ctx.feedback.event = event; feedback(ctx, index); - eventEmitter("selection", ctx); + eventEmitter('selection', ctx); close(ctx); }; var click = function click(event, ctx) { @@ -437,13 +515,13 @@ if (ctx.resultsList.tabSelect && ctx.cursor >= 0) select(ctx, event); break; case 27: - ctx.input.value = ""; + ctx.input.value = ''; close(ctx); break; } }; - function start (ctx, q) { + function start(ctx, q) { var _this = this; return new Promise(function ($return, $error) { var queryVal, condition; @@ -483,11 +561,14 @@ var run = debounce(function () { return start(ctx); }, ctx.debounce); - var publicEvents = ctx.events = _objectSpread2({ - input: _objectSpread2({}, events && events.input) - }, ctx.resultsList && { - list: events ? _objectSpread2({}, events.list) : {} - }); + var publicEvents = (ctx.events = _objectSpread2( + { + input: _objectSpread2({}, events && events.input), + }, + ctx.resultsList && { + list: events ? _objectSpread2({}, events.list) : {}, + }, + )); var privateEvents = { input: { input: function input() { @@ -498,7 +579,7 @@ }, blur: function blur() { close(ctx); - } + }, }, list: { mousedown: function mousedown(event) { @@ -506,11 +587,11 @@ }, click: function click$1(event) { click(event, ctx); - } - } + }, + }, }; eventsManager(privateEvents, function (element, event) { - if (!ctx.resultsList && event !== "input") return; + if (!ctx.resultsList && event !== 'input') return; if (publicEvents[element][event]) return; publicEvents[element][event] = privateEvents[element][event]; }); @@ -524,36 +605,59 @@ }); }; - function init (ctx) { + function init(ctx) { var _this = this; return new Promise(function ($return, $error) { var placeHolder, resultsList, parentAttrs; placeHolder = ctx.placeHolder; resultsList = ctx.resultsList; parentAttrs = { - role: "combobox", - "aria-owns": resultsList.id, - "aria-haspopup": true, - "aria-expanded": false + role: 'combobox', + 'aria-owns': resultsList.id, + 'aria-haspopup': true, + 'aria-expanded': false, }; - create(ctx.input, _objectSpread2(_objectSpread2({ - "aria-controls": resultsList.id, - "aria-autocomplete": "both" - }, placeHolder && { - placeholder: placeHolder - }), !ctx.wrapper && _objectSpread2({}, parentAttrs))); - if (ctx.wrapper) ctx.wrapper = create("div", _objectSpread2({ - around: ctx.input, - "class": ctx.name + "_wrapper" - }, parentAttrs)); - if (resultsList) ctx.list = create(resultsList.tag, _objectSpread2({ - dest: [resultsList.destination, resultsList.position], - id: resultsList.id, - role: "listbox", - hidden: "hidden" - }, resultsList["class"] && { - "class": resultsList["class"] - })); + create( + ctx.input, + _objectSpread2( + _objectSpread2( + { + 'aria-controls': resultsList.id, + 'aria-autocomplete': 'both', + }, + placeHolder && { + placeholder: placeHolder, + }, + ), + !ctx.wrapper && _objectSpread2({}, parentAttrs), + ), + ); + if (ctx.wrapper) + ctx.wrapper = create( + 'div', + _objectSpread2( + { + around: ctx.input, + class: ctx.name + '_wrapper', + }, + parentAttrs, + ), + ); + if (resultsList) + ctx.list = create( + resultsList.tag, + _objectSpread2( + { + dest: [resultsList.destination, resultsList.position], + id: resultsList.id, + role: 'listbox', + hidden: 'hidden', + }, + resultsList['class'] && { + class: resultsList['class'], + }, + ), + ); addEvents(ctx); if (ctx.data.cache) { return getData(ctx).then(function ($await_2) { @@ -565,14 +669,14 @@ }, $error); } function $If_1() { - eventEmitter("init", ctx); + eventEmitter('init', ctx); return $return(); } return $If_1.call(_this); }); } - function extend (autoComplete) { + function extend(autoComplete) { var prototype = autoComplete.prototype; prototype.init = function () { init(this); @@ -614,17 +718,17 @@ function autoComplete(config) { this.options = config; this.id = autoComplete.instances = (autoComplete.instances || 0) + 1; - this.name = "autoComplete"; + this.name = 'autoComplete'; this.wrapper = 1; this.threshold = 1; this.debounce = 0; this.resultsList = { - position: "afterend", - tag: "ul", - maxResults: 5 + position: 'afterend', + tag: 'ul', + maxResults: 5, }; this.resultItem = { - tag: "li" + tag: 'li', }; configure(this); extend.call(this, autoComplete); @@ -632,5 +736,4 @@ } return autoComplete; - -})); +}); diff --git a/scripts/autocomplete/css/autoComplete.01.css b/scripts/autocomplete/css/autoComplete.01.css index 4df567e..4879f8c 100644 --- a/scripts/autocomplete/css/autoComplete.01.css +++ b/scripts/autocomplete/css/autoComplete.01.css @@ -81,7 +81,7 @@ background-color: rgba(#ffffff, 0); } -.autoComplete_wrapper > ul > li[aria-selected="true"] { +.autoComplete_wrapper > ul > li[aria-selected='true'] { background-color: rgba(123, 123, 123, 0.1); } diff --git a/scripts/autocomplete/css/autoComplete.02.css b/scripts/autocomplete/css/autoComplete.02.css index e9e233c..5eef083 100644 --- a/scripts/autocomplete/css/autoComplete.02.css +++ b/scripts/autocomplete/css/autoComplete.02.css @@ -71,7 +71,7 @@ background-color: rgba(#ffffff, 0); } -.autoComplete_wrapper > ul > li[aria-selected="true"] { +.autoComplete_wrapper > ul > li[aria-selected='true'] { background-color: rgba(123, 123, 123, 0.1); } diff --git a/scripts/autocomplete/css/autoComplete.css b/scripts/autocomplete/css/autoComplete.css index 3bd94d2..68cde7a 100644 --- a/scripts/autocomplete/css/autoComplete.css +++ b/scripts/autocomplete/css/autoComplete.css @@ -117,7 +117,7 @@ background-color: rgba(255, 122, 122, 0.15); } -.autoComplete_wrapper > ul > li[aria-selected="true"] { +.autoComplete_wrapper > ul > li[aria-selected='true'] { background-color: rgba(255, 122, 122, 0.15); }