Автозаполнение в стиле Twitter в текстовом поле
Я ищу реализацию автозаполнения Javascript, которая включает в себя следующее:
- Может использоваться в текстовом поле HTML
- Позволяет печатать обычный текст без вызова автозаполнения
- Обнаруживает символ
@
и запускает автозаполнение при его вводе
- Загружает список опций через AJAX
Я считаю, что это похоже на то, что делает Twitter при пометке в твиттере, но я не могу найти хорошую, многоразовую реализацию.
Решение с jQuery было бы идеальным.
Спасибо.
Ответы
Ответ 1
Я не смог найти решение, которое идеально соответствовало моим требованиям, поэтому я получил следующее:
Я использую событие jQuery keypress()
, чтобы проверить, что пользователь нажимает символ @
.
Если это так, отображается модальный диалог с использованием jQuery UI. Это диалоговое окно содержит текстовое поле автозаполнения (здесь можно использовать множество опций, но я рекомендую jQuery Tokeninput)
Когда пользователь выбирает параметр в диалоговом окне, тег добавляется в текстовое поле и диалог закрывается.
Это не самое элегантное решение, но оно работает, и для него не требуются дополнительные нажатия клавиш по сравнению с моим оригинальным дизайном.
Edit
Таким образом, у нас есть большое текстовое поле, в котором пользователь может вводить текст. Он должен иметь возможность "пометить" пользователя (это просто означает вставку #<userid>
в текст). Я присоединяюсь к событию keyup jQuery и обнаруживаю символ @
, используя (e.which == 64)
, чтобы показать модальное текстовое поле для выбора тегов пользователей.
Мягкость решения - это просто модальный диалог с текстовым полем jQuery Tokeninput. Поскольку пользователь вводит здесь, список пользователей загружается через AJAX. Для правильного использования см. Примеры на веб-сайте. Когда пользователь закрывает диалог, я вставляю выбранные идентификаторы в большое текстовое поле.
Ответ 2
Я уверен, что ваша проблема давно решена, но jquery-textcomplete выглядит так, как будто это выполнит эту работу.
Ответ 3
Другая великая библиотека, которая решает эту проблему At.js
Источник
Демо
Ответ 4
Попробуйте следующее:
(function($){
$.widget("ui.tagging", {
// default options
options: {
source: [],
maxItemDisplay: 3,
autosize: true,
animateResize: false,
animateDuration: 50
},
_create: function() {
var self = this;
this.activeSearch = false;
this.searchTerm = "";
this.beginFrom = 0;
this.wrapper = $("<div>")
.addClass("ui-tagging-wrap");
this.highlight = $("<div></div>");
this.highlightWrapper = $("<span></span>")
.addClass("ui-corner-all");
this.highlightContainer = $("<div>")
.addClass("ui-tagging-highlight")
.append(this.highlight);
this.meta = $("<input>")
.attr("type", "hidden")
.addClass("ui-tagging-meta");
this.container = $("<div></div>")
.width(this.element.width())
.insertBefore(this.element)
.addClass("ui-tagging")
.append(
this.highlightContainer,
this.element.wrap(this.wrapper).parent(),
this.meta
);
var initialHeight = this.element.height();
this.element.height(this.element.css('lineHeight'));
this.element.keypress(function(e) {
// activate on @
if (e.which == 64 && !self.activeSearch) {
self.activeSearch = true;
self.beginFrom = e.target.selectionStart + 1;
}
// deactivate on space
if (e.which == 32 && self.activeSearch) {
self.activeSearch = false;
}
}).bind("expand keyup keydown change", function(e) {
var cur = self.highlight.find("span"),
val = self.element.val(),
prevHeight = self.element.height(),
rowHeight = self.element.css('lineHeight'),
newHeight = 0;
cur.each(function(i) {
var s = $(this);
val = val.replace(s.text(), $("<div>").append(s).html());
});
self.highlight.html(val);
newHeight = self.element.height(rowHeight)[0].scrollHeight;
self.element.height(prevHeight);
if (newHeight < initialHeight) {
newHeight = initialHeight;
}
if (!$.browser.mozilla) {
if (self.element.css('paddingBottom') || self.element.css('paddingTop')) {
var padInt =
parseInt(self.element.css('paddingBottom').replace('px', '')) +
parseInt(self.element.css('paddingTop').replace('px', ''));
newHeight -= padInt;
}
}
self.options.animateResize ?
self.element.stop(true, true).animate({
height: newHeight
}, self.options.animateDuration) :
self.element.height(newHeight);
var widget = self.element.autocomplete("widget");
widget.position({
my: "left top",
at: "left bottom",
of: self.container
}).width(self.container.width()-4);
}).autocomplete({
minLength: 0,
delay: 0,
maxDisplay: this.options.maxItemDisplay,
open: function(event, ui) {
var widget = $(this).autocomplete("widget");
widget.position({
my: "left top",
at: "left bottom",
of: self.container
}).width(self.container.width()-4);
},
source: function(request, response) {
if (self.activeSearch) {
self.searchTerm = request.term.substring(self.beginFrom);
if (request.term.substring(self.beginFrom - 1, self.beginFrom) != "@") {
self.activeSearch = false;
self.beginFrom = 0;
self.searchTerm = "";
}
if (self.searchTerm != "") {
if ($.type(self.options.source) == "function") {
self.options.source(request, response);
} else {
var re = new RegExp("^" + escape(self.searchTerm) + ".+", "i");
var matches = [];
$.each(self.options.source, function() {
if (this.label.match(re)) {
matches.push(this);
}
});
response(matches);
}
}
}
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function(event, ui) {
self.activeSearch = false;
//console.log("@"+searchTerm, ui.item.label);
this.value = this.value.replace("@" + self.searchTerm, ui.item.label) + ' ';
self.highlight.html(
self.highlight.html()
.replace("@" + self.searchTerm,
$("<div>").append(
self.highlightWrapper
.text(ui.item.label)
.clone()
).html()+' ')
);
self.meta.val((self.meta.val() + " @[" + ui.item.value + ":]").trim());
return false;
}
});
}
});
body, html {
font-family: "lucida grande",tahoma,verdana,arial,sans-serif;
}
.ui-tagging {
position: relative;
border: 1px solid #B4BBCD;
height: auto;
}
.ui-tagging .ui-tagging-highlight {
position: absolute;
padding: 5px;
overflow: hidden;
}
.ui-tagging .ui-tagging-highlight div {
color: transparent;
font-size: 13px;
line-height: 18px;
white-space: pre-wrap;
}
.ui-tagging .ui-tagging-wrap {
position: relative;
padding: 5px;
overflow: hidden;
zoom: 1;
border: 0;
}
.ui-tagging div > span {
background-color: #D8DFEA;
font-weight: normal !important;
}
.ui-tagging textarea {
display: block;
font-family: "lucida grande",tahoma,verdana,arial,sans-serif;
background: transparent;
border-width: 0;
font-size: 13px;
height: 18px;
outline: none;
resize: none;
vertical-align: top;
width: 100%;
line-height: 18px;
overflow: hidden;
}
.ui-autocomplete {
font-size: 13px;
background-color: white;
border: 1px solid black;
margin-bottom: -5px;
width: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea></textarea>
Ответ 5
Вы пробовали это
GITHUB: https://github.com/podio/jquery-mentions-input
DEMO/CONFIG: http://podio.github.io/jquery-mentions-input/
Это довольно просто реализовать.
Ответ 6
Я создал Meteor пакет для этой цели. Модель данных Meteor позволяет осуществлять быстрый поиск нескольких правил с помощью настраиваемых списков. Если вы не используете Meteor для своего веб-приложения, (я полагаю), вы, к сожалению, не найдете ничего такого удивительного для автозаполнения.
Автообновление пользователей с помощью @
, где онлайн-пользователи отображаются зеленым цветом:
![enter image description here]()
В той же строке автозаполнение чего-то еще с метаданными и значками начальной загрузки:
![enter image description here]()
Вилка, натяжение и улучшение:
https://github.com/mizzao/meteor-autocomplete
Ответ 7
Недавно мне пришлось столкнуться с этой проблемой, и вот как я прибил...
- Получить индекс строки в позиции курсора в текстовом поле, используя selectionStart
- отрезать строку от индекса 0 до положения курсора
- Вставьте его в диапазон (поскольку span имеет несколько пограничных полей)
- Получить размеры поля с помощью element.getClientRects() относительно порта представления. (здесь Справочник по MDN)
- Рассчитайте верхнюю и левую и подайте их в раскрывающийся список
Это работает во всех последних браузерах. не тестировались на старых
Вот Рабочий ящик
Ответ 8
ЭТО должно работать. Что касается @, начинающего поиск, просто добавьте (динамически или нет) символ к началу каждого возможного условия поиска.