После тщательного анализа я предлагаю это как более чистое решение в этой теме:
$("input").focus(function(){
$(this).on("click.a keyup.a", function(e){
$(this).off("click.a keyup.a").select();
});
});
Эта проблема:
Вот немного объяснения:
Во-первых, давайте посмотрим на порядок событий, когда вы щелкаете мышью или вкладываете в поле.
Мы можем регистрировать все соответствующие события, как это:
$("input").on("mousedown focus mouseup click blur keydown keypress keyup change",
function(e) { console.log(e.type); });
Примечание : я изменил это решение, чтобы использовать его, click
а не так, mouseup
как это происходит позже в конвейере событий, и, похоже, вызывает некоторые проблемы в Firefox согласно комментарию @ Jocie.
Некоторые браузеры пытаются позиционировать курсор во время событий mouseup
или click
. Это имеет смысл, поскольку вы можете запустить каретку в одной позиции и перетащить ее, чтобы выделить текст. Он не может обозначать положение каретки, пока вы на самом деле не подняли мышь. Таким образом, функции, которые обрабатывают focus
, обречены реагировать слишком рано, оставляя браузер переопределять ваше позиционирование.
Но проблема в том, что мы действительно хотим справиться с фокусным событием. Это позволяет нам узнать, когда кто-то вышел на поле. После этого мы не хотим продолжать переопределять поведение выбора пользователя.
Решение:
Вместо этого, в focus
обработчике событий мы можем быстро подключить прослушиватели для событий click
(click in) и keyup
(tab in), которые будут запущены.
Примечание : Keyup события табуляции будет фактически запускаться в новом поле ввода, а не в предыдущем
Мы хотим запустить событие только один раз. Мы могли бы использовать .one("click keyup)
, но это вызвало бы обработчик события один раз для каждого типа события . Вместо этого, как только будет нажата мышь или клавиша, мы вызовем нашу функцию. Первое, что мы сделаем, это удалим обработчики для обоих. Таким образом, не имеет значения, будем ли мы вкладывать или вкладывать. Функция должна выполняться ровно один раз.
Примечание . Большинство браузеров естественным образом выделяют весь текст во время события табуляции, но, как указывает animatedgif , мы по-прежнему хотим обрабатывать keyup
событие, в противном mouseup
случае событие все равно будет задерживаться в любое время, когда мы добавили вкладку. Мы слушаем оба, чтобы мы могли включить от слушателей, как только мы обработали выбор.
Теперь мы можем позвонить select()
после того, как браузер сделал свой выбор, поэтому мы обязательно переопределим поведение по умолчанию.
Наконец, для дополнительной защиты, мы можем добавить пространство имен событий к mouseup
и keyup
функциям , поэтому .off()
метод не удаляет другие слушателей , которые могут быть в игре.
Протестировано в IE 10+, FF 28+ и Chrome 35+
В качестве альтернативы, если вы хотите расширить jQuery с помощью функции, once
которая будет запускаться ровно один раз для любого количества событий :
$.fn.once = function (events, callback) {
return this.each(function () {
var myCallback = function (e) {
callback.call(this, e);
$(this).off(events, myCallback);
};
$(this).on(events, myCallback);
});
};
Тогда вы можете упростить код так:
$("input").focus(function(){
$(this).once("click keyup", function(e){
$(this).select();
});
});