Browse Source

Process tags to left of comma only

If user types "tag1 tag2" then adds a comma between,
it should respect the comma to give "tag1" and "tag2".

We use keydown and setTimeout because keyup
works on a keyboard but not reliably on mobile.

Nonzero timeout is needed or else the comma is sometimes
inserted too late and not seen by addChip(),
tested on desktop Firefox.
merge-requests/135/head
Andrew Shu 4 years ago
committed by Deimos
parent
commit
0404d0dfa2
  1. 72
      tildes/static/js/behaviors/autocomplete-input.js

72
tildes/static/js/behaviors/autocomplete-input.js

@ -2,7 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
$.onmount("[data-js-autocomplete-input]", function() { $.onmount("[data-js-autocomplete-input]", function() {
function addChip($input) {
function addChip($input, userTypedComma) {
var $autocompleteContainer = $input var $autocompleteContainer = $input
.parents("[data-js-autocomplete-container]") .parents("[data-js-autocomplete-container]")
.first(); .first();
@ -11,7 +11,8 @@ $.onmount("[data-js-autocomplete-input]", function() {
.first(); .first();
var $tagsHiddenInput = $("[data-js-autocomplete-hidden-input]"); var $tagsHiddenInput = $("[data-js-autocomplete-hidden-input]");
$input
var remaining = "";
var inputTags = $input
.val() .val()
.split(",") .split(",")
.map(function(tag) { .map(function(tag) {
@ -19,36 +20,43 @@ $.onmount("[data-js-autocomplete-input]", function() {
}) })
.filter(function(tag) { .filter(function(tag) {
return tag !== ""; return tag !== "";
})
.forEach(function(tag) {
if (!$tagsHiddenInput.val().match(new RegExp("(^|,)" + tag + ","))) {
var clearIcon = document.createElement("a");
clearIcon.classList.add("btn");
clearIcon.classList.add("btn-clear");
clearIcon.setAttribute("data-js-autocomplete-chip-clear", "");
clearIcon.setAttribute("aria-label", "Close");
clearIcon.setAttribute("role", "button");
clearIcon.setAttribute("tabindex", $chips.children().length);
var $chip = $(document.createElement("div"));
$chip.addClass("chip");
$chip.html(tag);
$chip.append(clearIcon);
if (!tag.match(/^[\w .]+$/)) {
$chip.addClass("error");
$chip.attr(
"title",
"Tags may only contain letters, numbers, and spaces."
);
}
});
$chips.append($chip);
// process only first tag, to left of comma, if user typed comma
if (userTypedComma && $input.val().indexOf(",") !== -1) {
remaining = inputTags.slice(1).join(", ");
inputTags = inputTags.slice(0, 1);
}
$tagsHiddenInput.val($tagsHiddenInput.val() + tag + ",");
inputTags.forEach(function(tag) {
if (!$tagsHiddenInput.val().match(new RegExp("(^|,)" + tag + ","))) {
var clearIcon = document.createElement("a");
clearIcon.classList.add("btn");
clearIcon.classList.add("btn-clear");
clearIcon.setAttribute("data-js-autocomplete-chip-clear", "");
clearIcon.setAttribute("aria-label", "Close");
clearIcon.setAttribute("role", "button");
clearIcon.setAttribute("tabindex", $chips.children().length);
var $chip = $(document.createElement("div"));
$chip.addClass("chip");
$chip.html(tag);
$chip.append(clearIcon);
if (!tag.match(/^[\w .]+$/)) {
$chip.addClass("error");
$chip.attr(
"title",
"Tags may only contain letters, numbers, and spaces."
);
} }
});
$autocompleteContainer.find("[data-js-autocomplete-input]").val("");
$chips.append($chip);
$tagsHiddenInput.val($tagsHiddenInput.val() + tag + ",");
}
});
$autocompleteContainer.find("[data-js-autocomplete-input]").val(remaining);
$autocompleteContainer.find("[data-js-autocomplete-suggestions]").html(""); $autocompleteContainer.find("[data-js-autocomplete-suggestions]").html("");
$.onmount(); $.onmount();
@ -102,6 +110,7 @@ $.onmount("[data-js-autocomplete-input]", function() {
}); });
$(this).keydown(function(event) { $(this).keydown(function(event) {
var $this = $(this);
var $autocompleteMenu = $("[data-js-autocomplete-menu]").first(); var $autocompleteMenu = $("[data-js-autocomplete-menu]").first();
var $nextActiveItem = null; var $nextActiveItem = null;
@ -111,6 +120,11 @@ $.onmount("[data-js-autocomplete-input]", function() {
$(this).blur(); $(this).blur();
break; break;
case ",": case ",":
// wait for comma to be added to text so addChip() sees it
setTimeout(function() {
addChip($this, true);
}, 100);
break;
case "Enter": case "Enter":
event.preventDefault(); event.preventDefault();
addChip($(this)); addChip($(this));

Loading…
Cancel
Save