Полезное для программистов:

Фриланс
Новости
Статьи
   
Рубрики:


Как вставить текст под курсором

Поиск:
Вопрос: Как вставить текст под курсором.

Столкнулся сегодня с этой задачей, решил ответить на него один раз с рабочим кодом. Надеюсь больше этот вопрос не всплывёт :)

В разных браузерах по разному можно узнать где находится каретка в текстовом поле. Точнее только в Мозилле на данный момент есть возможность узнать положение каретки опрашивая поля:
  • selectionStart - начало селекции, в символах
  • selectionEnd - конец селекции, в символах
Таким образом можно разбить содержимое на подстроки: до селекции, селекция, после селекции.

В ИЕ есть полезный обьект document.selection который может достать нам обьект DOM'овский обьект(ну почти DOM'овский :) ) TextRange. Изменяя этот обьект мы изменяем содержимое селекции.
Селекция здесь в самом широком смысле! То есть мы можем таким же образом работать над всем содержимым страницы.

В Опере код работать не будет, по старинке текст добавляется в конец.

Следующая сложность это не потерять селекцию(положение курсора) при клике на внешний элемент. Будем отлавливать события потери фокуса, клика и т.д., записывать "позицию курсора" и использовать её когда нужно.
В моём коде есть потенциальная ошибка: если отселектировать текст, затем кликнуть где нибудь по странице, а затем по кнопке вставляющей новый текст, то он будет вставлен в записанную позицию, что не совсем верно - селекция должна исчезнуть если кликаем не по кнопке. Решается отловом событий на body и сбросом записанной селекции, но это по вкусу :)

Код с коментариями:
Код
/**
* Обьект через который мы и будем работать с текстовыми полями.
* Содержит все необходимые поля, легко расширяем по вкусу =)
* @argument  obj  HTMLElment  - текстовое поле с кторым предстоит работать
*
* Author: Sardar <Sardar@vingrad.ru>
*/
function TextAreaSelectionHelper(obj) {
 this.target=obj;
 this.target.carretHandler=this; //ссылка самого на себя для текстового поля
 /**
 * Помним что события могут быть уже опредлеенны, тогда нужно использовать
 * очереди. Конечно реализация для ИЕ и Мозиллы в корне различаются, почитать
 * и достать готовый код можно здесь: http://forum.vingrad.ru/index.php?showtopic=32350
 */
 this.target.onchange=_textareaSaver;
 this.target.onclick=_textareaSaver;
 this.target.onkeyup=_textareaSaver;
 this.target.onfocus=_textareaSaver;
 if(!document.selection) this.target.onSelect=_textareaSaver; //для Мозиллы
 
 this.start=-1;
 this.end=-1;
 this.scroll=-1;
 this.iesel=null; //для ИЕ
}
/**
* Достать отселектированный текст
*/
TextAreaSelectionHelper.prototype.getSelectedText=function() {
  return this.iesel? this.iesel.text: (this.start>=0&&this.end>this.start)? this.target.value.substring(this.start,this.end): "";
}
/**
* Вставить код под курсором. Если текст не отселектирован(не фокуса) и
* позиция не взята, то вставить в конец текстового поля.
*
* @argument text String - заменить селекцию на этот текст
* @argument secondtag String - если задан, то селекция не заменяется, а обрамляется этими тегами
*/
TextAreaSelectionHelper.prototype.setSelectedText=function(text, secondtag) {
 if(this.iesel) {
if(typeof(secondtag)=="string") {
  var l=this.iesel.text.length;
     this.iesel.text=text+this.iesel.text+secondtag;
  this.iesel.moveEnd("character", -secondtag.length);
   this.iesel.moveStart("character", -l);  
} else {
  this.iesel.text=text;
}
   this.iesel.select();
 } else if(this.start>=0&&this.end>=this.start) {
    var left=this.target.value.substring(0,this.start);
    var right=this.target.value.substr(this.end);
 var scont=this.target.value.substring(this.start, this.end);
 if(typeof(secondtag)=="string") {
   this.target.value=left+text+scont+secondtag+right;
   this.end=this.target.selectionEnd=this.start+text.length+scont.length;
   this.start=this.target.selectionStart=this.start+text.length;    
 } else {
      this.target.value=left+text+right;
   this.end=this.target.selectionEnd=this.start+text.length;
   this.start=this.target.selectionStart=this.start+text.length;
 }
 this.target.scrollTop=this.scroll;
 this.target.focus();
 } else {
   this.target.value+=text + ((typeof(secondtag)=="string")? secondtag: "");
if(this.scroll>=0) this.target.scrollTop=this.scroll;
 }
}
/**
* Это функции для веса =)
*/
TextAreaSelectionHelper.prototype.getText=function() {
 return this.target.value;
}
TextAreaSelectionHelper.prototype.setText=function(text) {
 this.target.value=text;
}
/**
* Приватная фукнкция, записывающая позицию курсора
*/
function _textareaSaver() {
 if(document.selection) {
   this.carretHandler.iesel = document.selection.createRange().duplicate();
 } else if(typeof(this.selectionStart)!="undefined") {
   this.carretHandler.start=this.selectionStart;
this.carretHandler.end=this.selectionEnd;
this.carretHandler.scroll=this.scrollTop;
 } else {this.carretHandler.start=this.carretHandler.end=-1;}
}

..........
//Пример использования
var text=new TextAreaSelectionHelper(document.getElementById("textarea"));
function test() {
text.setSelectedText("[test]","[/test]");
// text.setSelectedText("[test]");
}
<textarea id="textarea" cols=80 rows=20></textarea>
<span onClick="test()">Test</span>
Автор: Sardar






Просмотров: 3839

 

 

Новые статьи:


Популярные:
  1. Как сделать цикличным проигрывание MIDI-файла?
  2. Создание AVI файла из рисунков
  3. Как устройство "отключить в данной конфигурации"?
  4. Kто в данный момент присоединен через Сеть?
  5. Как узнать количество доступной памяти?
  6. Как реализовать в RichEdit разноцветный текст?
  7. Как скрыть свое приложение от ProcessViewer
  8. Как программно нажать/скрыть/показ кнопку "Start"?
  9. Модуль работы с ресурсами в PE файлах
10. Функции вызова диалоговых окон выбора
11. Проверка граматики средствами Word'а из Delphi.
12. Модуль для упрощенного вызова сообщений
13. Функции для записи и чтение своих данных в, ЕХЕ- файле
14. Рекурсивный просмотр директорий
15. Network Traffic Monitor
16. Разные модули
17. Универсальная функция для обращения к любым экспортируем функциям DLL
18. Библиотека от VladS
19. Протектор для UPX'а
20. Еще об ICQ, сообщения по контакт листу?
21. Использование открытых интерфейсов
22. Теория и практика использования RTTI
23. Работа с TApplication
24. Примеры использования Drag and Drop для различных визуальных компонентов
25. Что такое порт? Правила для работы с портами
26. Симфония на клавиатуре
27. Загрузка DLL
28. Исправление автоинкремента
29. Взаимодействие с чужими окнами
30. Проверить дубляжи в столбце


 

 

 
 
На главную