Как вы устанавливаете позицию курсора в текстовом поле с помощью jQuery? У меня есть текстовое поле с контентом, и я хочу, чтобы курсор пользователя располагался с определенным смещением, когда они фокусировались на поле. Код должен выглядеть примерно так:
$('#input').focus(function() {
$(this).setCursorPosition(4);
});
Как бы выглядела реализация этой функции setCursorPosition? Если у вас есть текстовое поле с содержимым abcdefg, этот вызов приведет к тому, что курсор будет расположен следующим образом: abcd ** | ** efg.
Java имеет аналогичную функцию, setCaretPosition. Существует ли аналогичный метод для javascript?
Обновление: я изменил код CMS для работы с jQuery следующим образом:
new function($) {
$.fn.setCursorPosition = function(pos) {
if (this.setSelectionRange) {
this.setSelectionRange(pos, pos);
} else if (this.createTextRange) {
var range = this.createTextRange();
range.collapse(true);
if(pos < 0) {
pos = $(this).val().length + pos;
}
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
}(jQuery);
У меня есть две функции:
function setSelectionRange(input, selectionStart, selectionEnd) {
if (input.setSelectionRange) {
input.focus();
input.setSelectionRange(selectionStart, selectionEnd);
}
else if (input.createTextRange) {
var range = input.createTextRange();
range.collapse(true);
range.moveEnd('character', selectionEnd);
range.moveStart('character', selectionStart);
range.select();
}
}
function setCaretToPos (input, pos) {
setSelectionRange(input, pos, pos);
}
Затем вы можете использовать setCaretToPos следующим образом:
setCaretToPos(document.getElementById("YOURINPUT"), 4);
Живой пример с textarea
и input
, показывающий использование jQuery:
function setSelectionRange(input, selectionStart, selectionEnd) {
if (input.setSelectionRange) {
input.focus();
input.setSelectionRange(selectionStart, selectionEnd);
} else if (input.createTextRange) {
var range = input.createTextRange();
range.collapse(true);
range.moveEnd('character', selectionEnd);
range.moveStart('character', selectionStart);
range.select();
}
}
function setCaretToPos(input, pos) {
setSelectionRange(input, pos, pos);
}
$("#set-textarea").click(function() {
setCaretToPos($("#the-textarea")[0], 10)
});
$("#set-input").click(function() {
setCaretToPos($("#the-input")[0], 10);
});
<textarea id="the-textarea" cols="40" rows="4">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea>
<br><input type="button" id="set-textarea" value="Set in textarea">
<br><input id="the-input" type="text" size="40" value="Lorem ipsum dolor sit amet, consectetur adipiscing elit">
<br><input type="button" id="set-input" value="Set in input">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Начиная с 2016 года, тестировалось и работало в Chrome, Firefox, IE11, даже в IE8 (см. последний здесь; Фрагменты стека не поддерживают IE8).
<input>
.
Здесь решение jQuery:
$.fn.selectRange = function(start, end) {
if(end === undefined) {
end = start;
}
return this.each(function() {
if('selectionStart' in this) {
this.selectionStart = start;
this.selectionEnd = end;
} else if(this.setSelectionRange) {
this.setSelectionRange(start, end);
} else if(this.createTextRange) {
var range = this.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', start);
range.select();
}
});
};
С этим вы можете сделать
$('#elem').selectRange(3,5); // select a range of text
$('#elem').selectRange(3); // set cursor position
Решения здесь правы, за исключением кода расширения jQuery.
Функция расширения должна перебирать каждый выбранный элемент и возвращать this
для поддержки цепочки. Вот правильная версия:
$.fn.setCursorPosition = function(pos) {
this.each(function(index, elem) {
if (elem.setSelectionRange) {
elem.setSelectionRange(pos, pos);
} else if (elem.createTextRange) {
var range = elem.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
});
return this;
};
return this.each(function...)
и удалить отдельную строку.
Я нашел решение, которое работает для меня:
$.fn.setCursorPosition = function(position){
if(this.length == 0) return this;
return $(this).setSelection(position, position);
}
$.fn.setSelection = function(selectionStart, selectionEnd) {
if(this.length == 0) return this;
input = this[0];
if (input.createTextRange) {
var range = input.createTextRange();
range.collapse(true);
range.moveEnd('character', selectionEnd);
range.moveStart('character', selectionStart);
range.select();
} else if (input.setSelectionRange) {
input.focus();
input.setSelectionRange(selectionStart, selectionEnd);
}
return this;
}
$.fn.focusEnd = function(){
this.setCursorPosition(this.val().length);
return this;
}
Теперь вы можете перемещать фокус до конца любого элемента, вызывая:
$(element).focusEnd();
this.scrollTop(this[0].scrollHeight);
, чтобы прокрутить текстовую область, чтобы сделать видимой точку вставки.
Это сработало для меня в Safari 5 на Mac OSX, jQuery 1.4:
$("Selector")[elementIx].selectionStart = desiredStartPos;
$("Selector")[elementIx].selectionEnd = desiredEndPos;
Я понимаю, что это очень старый пост, но я подумал, что я должен предложить, возможно, более простое решение для его обновления, используя только jQuery.
function getTextCursorPosition(ele) {
return ele.prop("selectionStart");
}
function setTextCursorPosition(ele,pos) {
ele.prop("selectionStart", pos + 1);
ele.prop("selectionEnd", pos + 1);
}
function insertNewLine(text,cursorPos) {
var firstSlice = text.slice(0,cursorPos);
var secondSlice = text.slice(cursorPos);
var new_text = [firstSlice,"\n",secondSlice].join('');
return new_text;
}
Использование для использования ctrl-enter для добавления новой строки (например, в Facebook):
$('textarea').on('keypress',function(e){
if (e.keyCode == 13 && !e.ctrlKey) {
e.preventDefault();
//do something special here with just pressing Enter
}else if (e.ctrlKey){
//If the ctrl key was pressed with the Enter key,
//then enter a new line break into the text
var cursorPos = getTextCursorPosition($(this));
$(this).val(insertNewLine($(this).val(), cursorPos));
setTextCursorPosition($(this), cursorPos);
}
});
Я открыт для критики. Спасибо.
UPDATE: это решение не позволяет работать с нормальной копией и вставкой (т.е. ctrl-c, ctrl-v), поэтому мне нужно будет изменить это в будущем, чтобы убедиться, что эта часть работает снова. Если у вас есть идея, как это сделать, прокомментируйте здесь, и я буду рад проверить это. Спасибо.
Установите фокус, прежде чем вставлять текст в текстовую область?
$("#comments").focus();
$("#comments").val(comments);
Я использую это: http://plugins.jquery.com/project/jCaret
Это работает для меня в хроме.
$('#input').focus(function() {
setTimeout( function() {
document.getElementById('input').selectionStart = 4;
document.getElementById('input').selectionEnd = 4;
}, 1);
});
По-видимому, вам нужна задержка в микросекунду или больше, потому что обычно пользователь фокусируется на текстовом поле, щелкая в какой-либо позиции в текстовом поле (или на вкладке), которое вы хотите переопределить, поэтому вам нужно подождать до позиция устанавливается щелчком пользователя, а затем меняет его.
В IE для перемещения курсора на некоторую позицию достаточно этого кода:
var range = elt.createTextRange();
range.move('character', pos);
range.select();
Небольшая модификация кода, который я нашел в bitbucket
Теперь код может выбирать/выделять с начальными/конечными точками, если заданы 2 позиции. Протестировано и отлично работает в FF/Chrome/IE9/Opera.
$('#field').caret(1, 9);
Код указан ниже, изменилось только несколько строк:
(function($) {
$.fn.caret = function(pos) {
var target = this[0];
if (arguments.length == 0) { //get
if (target.selectionStart) { //DOM
var pos = target.selectionStart;
return pos > 0 ? pos : 0;
}
else if (target.createTextRange) { //IE
target.focus();
var range = document.selection.createRange();
if (range == null)
return '0';
var re = target.createTextRange();
var rc = re.duplicate();
re.moveToBookmark(range.getBookmark());
rc.setEndPoint('EndToStart', re);
return rc.text.length;
}
else return 0;
}
//set
var pos_start = pos;
var pos_end = pos;
if (arguments.length > 1) {
pos_end = arguments[1];
}
if (target.setSelectionRange) //DOM
target.setSelectionRange(pos_start, pos_end);
else if (target.createTextRange) { //IE
var range = target.createTextRange();
range.collapse(true);
range.moveEnd('character', pos_end);
range.moveStart('character', pos_start);
range.select();
}
}
})(jQuery)
Основываясь на этом question, ответ не будет работать отлично для ie и opera, когда в текстовой области есть новая строка. Ответ объясняет, как настроить selectionStart, selectEnd перед вызовом setSelectionRange.
Я попробовал setupOffset из другого вопроса с помощью решения, предложенного @AVProgrammer, и он работает.
function adjustOffset(el, offset) {
/* From https://stackoverflow.com/a/8928945/611741 */
var val = el.value, newOffset = offset;
if (val.indexOf("\r\n") > -1) {
var matches = val.replace(/\r\n/g, "\n").slice(0, offset).match(/\n/g);
newOffset += matches ? matches.length : 0;
}
return newOffset;
}
$.fn.setCursorPosition = function(position){
/* From https://stackoverflow.com/a/7180862/611741 */
if(this.lengh == 0) return this;
return $(this).setSelection(position, position);
}
$.fn.setSelection = function(selectionStart, selectionEnd) {
/* From https://stackoverflow.com/a/7180862/611741
modified to fit https://stackoverflow.com/a/8928945/611741 */
if(this.lengh == 0) return this;
input = this[0];
if (input.createTextRange) {
var range = input.createTextRange();
range.collapse(true);
range.moveEnd('character', selectionEnd);
range.moveStart('character', selectionStart);
range.select();
} else if (input.setSelectionRange) {
input.focus();
selectionStart = adjustOffset(input, selectionStart);
selectionEnd = adjustOffset(input, selectionEnd);
input.setSelectionRange(selectionStart, selectionEnd);
}
return this;
}
$.fn.focusEnd = function(){
/* From https://stackoverflow.com/a/7180862/611741 */
this.setCursorPosition(this.val().length);
}
Не забудьте вернуть false сразу после вызова функции, если вы используете клавиши со стрелками, так как Chrome фрикирует в противном случае.
{
document.getElementById('moveto3').setSelectionRange(3,3);
return false;
}
return false;
, Вы хотите event.preventDefault();
вместо. Если вы возвращаете false, вы подразумеваете event.stopPropagation()
что не всегда желательно
Мне пришлось заставить эту работу работать с доступными для контента элементами и jQuery и требовать, чтобы кто-то захотел ее использовать:
$.fn.getCaret = function(n) {
var d = $(this)[0];
var s, r;
r = document.createRange();
r.selectNodeContents(d);
s = window.getSelection();
console.log('position: '+s.anchorOffset+' of '+s.anchorNode.textContent.length);
return s.anchorOffset;
};
$.fn.setCaret = function(n) {
var d = $(this)[0];
d.focus();
var r = document.createRange();
var s = window.getSelection();
r.setStart(d.childNodes[0], n);
r.collapse(true);
s.removeAllRanges();
s.addRange(r);
console.log('position: '+s.anchorOffset+' of '+s.anchorNode.textContent.length);
return this;
};
Использование $(selector).getCaret()
возвращает смещение числа, а $(selector).setCaret(num)
устанавливает смещение и устанавливает фокус на элементе.
Также небольшой совет, если вы запустите $(selector).setCaret(num)
с консоли, он вернет console.log, но вы не будете визуализировать фокус, поскольку он установлен в окне консоли.
Bests; D
Вы можете напрямую изменить прототип, если setSelectionRange не существует.
(function() {
if (!HTMLInputElement.prototype.setSelectionRange) {
HTMLInputElement.prototype.setSelectionRange = function(start, end) {
if (this.createTextRange) {
var range = this.createTextRange();
this.collapse(true);
this.moveEnd('character', end);
this.moveStart('character', start);
this.select();
}
}
}
})();
document.getElementById("input_tag").setSelectionRange(6, 7);
jsFiddle ссылка
$(this).get(0).setSelectionRange)
? Вы знаете, что это точно так же, какthis.setSelectionRange
, только медленнее и труднее читать, верно? JQuery здесь буквально ничего не делает для вас.