-
Content assist для элемента textarea
Очередной эксперимент в поисках идеального средства для простого и быстрого написания кода.
<textarea>
, да и веб-технологии в целом привлекают меня своей простотой, доступностью и возможностью сделать так, как нужно мне. Есть Zen Coding, который позволяет быстро и удобно работать с большим объёмом XHTML-данных, но для пущего удобства не хватает автодополнения кода. Поиск в интернете не дал никаких вменяемых результатов, поэтому решил написать свой:Проверить автодополнение можно на тестовой странице. Попробуйте написать несколько английских слов, начинающихся на «a» (awesome, animal, amazing). Должно работать везде, включая IE6.
Само по себе автодополнение, по большому счёту, практически бесполезно: непонятно, в какой момент какие данные нужно показывать. Поэтому решение представляет из себя несколько отдельных классов, каждый из которых можно переопределить, расширить и дополнить. За основу была взята архитектура автодополнения для Eclipse IDE, поэтому ряд классов и методов называются одинаково.
TextViewer
— по сути, обёртка для<textarea>
. Основное предназначение: дать удобный интерфейс для получения содержимого элемента. Один из основных методов —getCharacterCoords(char_ix)
, возвращает координаты для определённого символа. Метод возвращает объект со свойствамиx
иy
в пикселях, отсчёт идёт от левого верхнего угла<textarea>
до левого верхнего угла нужного символа. МетодgetAbsoluteCharacterCoords(char_ix)
возвращает то же самое, только относительноoffsetParent
. Как не трудно догадаться, этот класс можно переписать для работы с content-editable блоком, и у вас будет автодополнение для более серьёзного редактора.ContentAssistProcessor
— процессор, который высчитывает и предлагает список дополнений. По умолчанию ищет левую и правую границу английского слова (см. методisAllowedChar
), ищет префикс (от левой границы слова до каретки) и предлагет по этому префиксу список дополнений.CompletionProposal
— предложение для автодополнения. Главный метод —apply()
, который применяет текущее предложение кTextViewer
-объекту.ContentAssist
— основной класс. Связывает между собойTextViewer
иContentAssistProcessor
, а также управляет всплывающим окном с подсказками.tx_utils
— набор всяких DOM-утилит.
Для добавления поддержки автодополнения для
<textarea>
нужно инициализировать все эти классы:var viewer = new TextViewer(document.getElementById('my-textarea')); var processor = new ContentAssistProcessor(['word1', 'word2', 'word3']); var content_assist = new ContentAssist(viewer, processor);
Для удобства есть класс
BasicContentAssist
, который делает всё то же самое для простых случаев (автодополнение по фиксированному словарю):new BasicContentAssist(document.getElementById('my-textarea'), ['word1', 'word2', 'word3']);
У класса
ContentAssistProcessor
есть методcompletitionProposalFactory
, который должен возвращать объект классаCompletionProposal
. Внешний вид попапа с предложениями был нагло позаимствован из редактора Espresso и полностью управляется через CSS. Окошко с предложениями можно вызвать принудительно по Ctrl+Space (не работает в Опере и немного тупит в Файерфоксе) либо по Alt+Space (хвала разработчикам Оперы: это тоже не работает, по крайней мере на Маке) и заменить текущее слово (зависит от позиции каретки).Как видите, все классы можно удобно перекрывать, расширять и наследовать для достижения необходимого функционала. Баги, предложения и улучшения принимаются в комментариях и на странице проекта.
UPD: немного дотюнил процессор, теперь он находит границы слов вне зависимости от языка (то есть можно отдавать словарь с русскими словами), а также немного улучшил поддержку больших словарей.
34 комментария
Попытка потянуть за скролл в вариантах дополнения у меня стабильно крешит 5 сафари.
Chrome 5 тоже крашится при перетягивании скролла в вариантах дополнения. Похоже, что это общая проблема у вебкитовских браузеров.
ну круто. Даже на флэше такого еще не видал
Попробуйте сейчас потаскать, не должен крэшиться
Да, риальне очень круто.
Ого! Крутая штука! Напиши автору akshell.com, наверняка ему понравится.
И неплохо бы сделать jQuery-плагином, кстати 😉
P.S. ЕМНИП, в Опере на Маке событие по ctrl срабатывает по cmd.
Очень круто!
Жду мануала «How to create predefined dictionary for assist» 🙂
То есть мануал «как создать массив слов»?
нажатие кнопки вниз и _удерживание_ должно запускать прокрутку. удобнее будет
а фишка удобная
Сергей, вы в очередной раз меня удивили и порадовали прекрасной разработкой. Уже внедрил в один из своих проектов. По какой лицензии распространяете?
Лицензия MIT
Спасибо
Спасибо! Обязательно заюзаю в своем проекте.
Пардон, про массив ступил, сейчас уже все понятно.
Единственное что не очень логично — регистрозависимость…
Немного дотюнил процессор, теперь он находит границы слов вне зависимости от языка (то есть можно отдавать словарь с русскими словами), а также немного улучшил поддержку больших словарей. А также добавил в демку пример с
<input type="text">
С регистрозависимостью всё не так просто. Например, я могу набирать слово «amazing» как Amazing, AMAZING или AmAZing и в зависимости от префикса нужно делать автодополнение. Для этих целей я и разбил весь проект на несколько классов, чтобы можно было допилить до нужного функционала.
как же мне надоели эти jQueryкодеры (пренебрежительно). Ну на фига на всякую полезность писать «И неплохо бы сделать jQuery-плагином»
Зачем? Что не даёт вам пользоватся скриптом втом виде в каком он есть сейчас?
вот вам плагин
jQuery.fn.content_assit = function(words) {
return this.each(function(){
new BasicContentAssist(this, words)
});
};
использовать так
$("selector").content_assit(['word1', 'word2', 'word3']);
Григорий я надеюсь теперь вам стало легче? можете добавлять на http://plugins.jquery.com/
Немножко оффтопика (tx_utils.js):
createElement: function(name, class_name) {
var elem = document.createElement('div');
if (class_name)
elem.className = class_name;
return elem;
}
аттрибут
name не используется ;)
А кто скажет поподробней про BasicContentAssist…
Ви, спасибо, поправлю.
CTAC9H, а что там рассказывать? Это простая обёртка, которая инициализирует три объект и связывает их между собой. Удобно использовать в случае, если у вас фиксированный словарь дополнений. Если словарь нужно высчитывать динамически либо список дополнений должен зависеть от контекста, то нужно написать свой
ContentAssistProcessor
и инициализировать автодополнение по образу и подобиюBasicContentAssist
This is so awesome!!!
Много глюков в IE7: прокрутка показывается не сразу, после выбора значения в попапе перепрыгивает не на конец слова, попап не переносится на новую строку при вводе символа в конце строки. Во всех браузерах: попап начинает съезжать при увеличении/уменьшении размера шрифта, при выборе слова при наличии скрола у textarea перепрыгивает в начало текста.
похоже координаты коретки в textarea неправильно вычисляются http://img.skitch.com/20100618-p4jutegamritnp635mcq249wwu.png (safari5)
http://img10.imageshack.us/img10/7937/contentassist.jpg
с координатами явно проблемы!!!
Были такие проблемы, но я их вроде исправлял. У вас не могло ничего закэшироваться?
В ИЕ6 не работает вставка выбранного значения по энтеру. То есть когда всплывает список с вариантами — приходится браться за мышку, чтобы кликнуть на нужное значение. Мне кажется нужно либо вообще забить на ИЕ6, либо уж тогда полностью там все отладить.
Добрый день!
1. Наверное слишком мудрено, но если бы можно было сделать поддержку атрибутов при вводе тегов. Что-то на подобии помощника в Dreamweaver. Это возможно/планируется?
2. Когда в список слов вставляю » — ничего не срабатывает. Без угловых скобок — работает.
Да, планируется, но как отдельный подпроект. Смысл написанного — предоставить фрэймворк, из которого можно делать свой content assist. Сейчас пока застопорился в выборе движка для лексического анализа.
Повторю предыдущее собещение — в переменную для слов вставляю <txp:article /> — с угловыми скобками вообще не работает выпадающее меню
Посмотрите http://github.com/sergeche/tx-content-assist/issues/issue/3/#issue/3
Что-то типа такого можно посмотреть в гугловском RichTextSpeelChecker.
http://closure-library.googlecode.com/svn/trunk/closure/goog/demos/richtextspellchecker.html
Там правда не совсем то, что у тебя, но допиливанием можно привести к какому-нить общему знаменателю.
http://youtrack.jetbrains.net/ — в тему топика. Но как я понимаю, там реализация замера проще, т.к. используется моноширинный шрифт.
по поводу лексического анализатора могу предложить использовать вообще бэкэнд для этого, на котором лежит длинно-частотный словарь. Можно сделать простейшее обучение для него. У меня есть SQL база со всеми словоформами русского языка. Было бы очень интересно развивать проект.
Хммм, странно видеть свой дизайн от чужих людей…
Год назад рисовал для одного театра http://s46.radikal.ru/i113/1108/59/601f0cd2b958.jpg (вариант принят не был).
Промазал комментом, сорри. Это было к http://chikuyonok.ru/2011/08/optimize-with-canvas/