2010-07-20 5 views
13

У меня есть html textarea, который будет периодически обновляться с помощью javascript.обновить значение textarea, но сохранить позицию курсора

когда я делаю это:

$("#textarea").val(new_val); 

Курсор перемещается в конец текста.

Я хотел был бы обновить текст без изменения положения курсора. Кроме того, если у пользователя выбран диапазон текста, подсветка должна быть сохранена.

ответ

23

Вот пара функций, которые получают и устанавливают позицию выбора/каретки в текстовой области во всех основных браузерах.

Примечание: если вам не нужно поддерживать IE < = 8, просто использовать selectionStart и selectionEnd свойства (MDN). Весь сложный код, приведенный ниже, предназначен только для поддержки старых версий IE.

function getInputSelection(el) { 
    var start = 0, end = 0, normalizedValue, range, 
     textInputRange, len, endRange; 

    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") { 
     start = el.selectionStart; 
     end = el.selectionEnd; 
    } else { 
     range = document.selection.createRange(); 

     if (range && range.parentElement() == el) { 
      len = el.value.length; 
      normalizedValue = el.value.replace(/\r\n/g, "\n"); 

      // Create a working TextRange that lives only in the input 
      textInputRange = el.createTextRange(); 
      textInputRange.moveToBookmark(range.getBookmark()); 

      // Check if the start and end of the selection are at the very end 
      // of the input, since moveStart/moveEnd doesn't return what we want 
      // in those cases 
      endRange = el.createTextRange(); 
      endRange.collapse(false); 

      if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { 
       start = end = len; 
      } else { 
       start = -textInputRange.moveStart("character", -len); 
       start += normalizedValue.slice(0, start).split("\n").length - 1; 

       if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { 
        end = len; 
       } else { 
        end = -textInputRange.moveEnd("character", -len); 
        end += normalizedValue.slice(0, end).split("\n").length - 1; 
       } 
      } 
     } 
    } 

    return { 
     start: start, 
     end: end 
    }; 
} 

function offsetToRangeCharacterMove(el, offset) { 
    return offset - (el.value.slice(0, offset).split("\r\n").length - 1); 
} 

function setInputSelection(el, startOffset, endOffset) { 
    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") { 
     el.selectionStart = startOffset; 
     el.selectionEnd = endOffset; 
    } else { 
     var range = el.createTextRange(); 
     var startCharMove = offsetToRangeCharacterMove(el, startOffset); 
     range.collapse(true); 
     if (startOffset == endOffset) { 
      range.move("character", startCharMove); 
     } else { 
      range.moveEnd("character", offsetToRangeCharacterMove(el, endOffset)); 
      range.moveStart("character", startCharMove); 
     } 
     range.select(); 
    } 
} 

При изменении значения текстового поля, сначала сохраните выбор, а затем восстановить его впоследствии:

var t = document.getElementById("textarea"); 
var sel = getInputSelection(t); 
t.value = some_new_value; 
setInputSelection(t, sel.start, sel.end); 
+0

Имеет ли 'setInputSelection' функцию работать только в IE? Я спрашиваю, потому что метод 'createTextRange' не существует (для элементов ввода) в других браузерах, поэтому возникает ошибка. –

+0

@ Šime: О, да, извините. Копирование/вставка из вопроса только для IE. Пересмотр теперь ... –

+0

@ Šime: ... и сделано. –

Смежные вопросы