Как привязать событие прокрутки к Live()?

Некоторое время назад я решил проблему для кого-то, кто хотел, чтобы его текстовое поле росло. Я сделал функцию, которая прослушивает события scroll и keyup области и пересчитывает количество строк. Я хотел использовать код в другом проекте, но есть проблема. Текстовые области не известны. Чтобы решить эту проблему, я использую live вместо bind, так что будущие области также будут связаны.

Теперь я обнаружил, что live выполняется намного медленнее, чем bind. Я создал упрощенный пример на jsFiddle. Верхняя текстовая область ведет себя так, как я хочу, но недавно добавленные мерцают из-за поздней сигнализации (я использую Chrome).

Как сделать live таким же быстрым, как bind? Проблема в том, что scroll нельзя использовать с оператором live. Есть ли способ включить scroll для live? Возможно, есть событие jQuery, которое сигнализирует мне о добавлении новой TextArea, поэтому я могу использовать привязку, чтобы добавить scroll к вновь созданному элементу?

Я с нетерпением жду ваших идей.

EDIT: Изменена ссылка на код. Удален код прокрутки. Добавлена ​​еще одна кнопка для создания другого текстового поля. Проблема связана с «прокруткой». Он не срабатывает.

Пояснение: я не знаю, какая функция создаст текстовое поле. Я вижу мерцание динамически добавляемых полей в Chrome.

Для будущих читателей:

В jQuery 1.3.x с помощью .live() можно было связать только следующие события JavaScript (в дополнение к пользовательским событиям): click, dblclick, keydown, keypress, keyup, mousedown, mousemove, mouseout, mouseover, and mouseup. Начиная с jQuery 1.4 метод .live() поддерживает пользовательские события, а также все события JavaScript, которые всплывают. Начиная с jQuery 1.4.1, даже фокусировка и размытие работают с живыми событиями (сопоставление с более подходящим, всплывающим, события фокусируются и фокусируются). Начиная с jQuery 1.4.1 можно указать событие наведения (сопоставление с mouseenter и mouseleave, которые, в свою очередь, сопоставляются с mouseover и mouseout).


person Kees C. Bakker    schedule 22.01.2011    source источник
comment
@Pointy, да, это правда, поэтому я создаю текстовое поле, которое будет достаточно большим, чтобы его нельзя было прокручивать. Я только слегка прокручиваю, когда пользователь вводит новые данные, и он срабатывает до нажатия клавиши. Попробуйте удалить прокрутку из примера, и вы увидите, что все пойдет не так гладко.   -  person Kees C. Bakker    schedule 22.01.2011
comment
@Kees, да, я вижу это, поиграв с ним. Ваш jsFiddle зависает в моем браузере, когда я пытаюсь ввести статическое текстовое поле, и, я думаю, он отлично работает, когда я набираю добавленное текстовое поле. Одна вещь: почему код вызывает scrollTop(0) в циклах увеличения/уменьшения?   -  person Pointy    schedule 22.01.2011
comment
@Pointy elem.scrollTop(0); можно удалить :-). Это было из-за того, что я пытался: P.   -  person Kees C. Bakker    schedule 22.01.2011
comment
@Pointy Я вижу такое же падение производительности. Когда я убиваю «живое» событие, «привязка» делает хорошую работу. Но с «bind» и «live» мой браузер тоже немного зависает. Верид!   -  person Kees C. Bakker    schedule 22.01.2011
comment
Что бы это ни стоило, у меня это работает, если функция изменения размера переписана так, чтобы она была просто: elem.height(elem.attr('scrollHeight') - elem.attr('clientHeight') + elem.height());   -  person Pointy    schedule 22.01.2011
comment
Кроме того, с этой однострочной версией resizeTextArea я не вижу никаких различий в поведении между статической текстовой областью и добавленными.   -  person Pointy    schedule 22.01.2011
comment
@Pointy, насчет увеличения ты прав, но как насчет уменьшения ;-)   -  person Kees C. Bakker    schedule 22.01.2011
comment
Уменьшение размера не работает для меня в любом случае, старый код или новый код.   -  person Pointy    schedule 22.01.2011
comment
@Pointy, @Kees - посмотрите мой обновленный ответ с короткой функцией изменения размера.   -  person gblazex    schedule 22.01.2011
comment
@galambalazs, можно еще короче! elem.height(1); elem.height(elem[0].scrollHeight - elem[0].clientHeight + elem.height()); - это работает как для увеличения, так и для уменьшения.   -  person Pointy    schedule 22.01.2011
comment
@Pointy Да, это еще короче. :) В любом случае оригинал слишком многословен.   -  person gblazex    schedule 22.01.2011
comment
Да, кстати, блестящее понимание проблемы прокрутки   -  person Pointy    schedule 22.01.2011
comment
@Pointy Хм. Ваш не работает в IE, как я сейчас проверил: jsbin.com/edove4/4< /а>   -  person gblazex    schedule 22.01.2011
comment
@Pointy - Nvm, я исправил это и добавил к ответу. :)   -  person gblazex    schedule 22.01.2011
comment
@galambalazs - ну, у меня не работала виртуальная машина Windows, поэтому я не мог попробовать :-)   -  person Pointy    schedule 22.01.2011
comment
@galambalazs @Pointy... спасибо за понимание. Это облегчает жизнь!   -  person Kees C. Bakker    schedule 23.01.2011


Ответы (4)


Ответ прост. scroll — это то, что предотвращает мерцание, потому что оно срабатывает в самый первый момент изменения размера. Но scroll не влияет на live (поскольку он не всплывает), поэтому ваши вновь созданные текстовые области будут изменены в размере keyup, но сработают позже (таким образом, мерцание).

Обновление: Конечно, я даже могу решить вашу проблему. Вам просто нужно спросить :) [Демо]

$('textarea.autoresize').live('keyup', function() {
    var el = $(this);
    if (!el.data("has-scroll")) {
        el.data("has-scroll", true);
        el.scroll(function(){
           resizeTextArea(el);
        });
    }
    resizeTextArea(el);
});

Дело в том, что он смешивает live с bind. Событие keyup, которое срабатывает для всех элементов (из-за live), условно добавляет уникальное событие scroll.

Обновление 2. Да, и, кстати, весь код изменения размера можно было бы лучше записать так:

// resize text area (fixed version of Pointy's)
function resizeTextArea(elem) {
    elem.height(1); elem.scrollTop(0);
    elem.height(elem[0].scrollHeight - elem[0].clientHeight + elem.height())
}​
person gblazex    schedule 22.01.2011
comment
??? Удалите keyup из live, и вы увидите, что live("scroll") даже не вызывается. quirksmode.org/dom/events/scroll.html - person gblazex; 22.01.2011
comment
О да, я понял! Можно ли сделать какое-то «живое» действие, чтобы добавить действие прокрутки вручную? - person Kees C. Bakker; 22.01.2011
comment
Ну... проблема с демонстрацией заключалась в том, что статическая текстовая область перестала работать :-). Вот почему я хотел добавить его в свой «распутанный» источник, хахаха. Но это работает per-fec-ta-men-to! :D Большое спасибо! :D - person Kees C. Bakker; 22.01.2011
comment
@Kees - потому что я случайно удалил начальный размер вместе с начальным bind :) Обновил демо. - person gblazex; 22.01.2011

Попробуйте это (JSFiddle):

$('#Add').click(function(){
    var id = "newtextarea"+Math.floor(Math.random()*1000);
   $('#pane').append($('<textarea class="new" rows="1" cols="40" id="'+id+'"></textarea><br/>'));
    $('textarea:last').focus();
    bindAgain(id);
});

//inital resize
resizeTextArea($('#tst'));

//'live' event
$('textarea.new').bind('keyup scroll', function() {
    resizeTextArea($(this));
});

function bindAgain(id)
{
    $('#'+id).bind('keyup scroll', function() {
    resizeTextArea($(this));
});

}

По сути, он перепривязывает событие, используя динамически созданный идентификатор. Не так элегантно, как решение karim79, но работает.

person Yahel    schedule 22.01.2011
comment
Проблема в том, что я не знаю, какая функция создает текстовое поле. Это будет поведение по умолчанию для всех текущих и будущих текстовых полей на странице. - person Kees C. Bakker; 22.01.2011

Я привязываю его к пользовательскому событию, которое вызываю всякий раз, когда происходит что-то важное. Нравится:

$(body).live('MyCustomEvent', function() {
    $("#MyScrollItem").scroll(function() {
       // Do things here
    }
});

Надеюсь, это поможет. Коротко и мило.

person Community    schedule 18.05.2011
comment
вы правы, но это уже было в разделе Для будущих читателей, и я цитирую: начиная с jQuery 1.4.1 даже фокус и размытие работают с живыми (отображение на более подходящее, всплытие, события focusin и focusout). Начиная с jQuery 1.4.1 можно указать событие наведения (сопоставление с mouseenter и mouseleave, которые, в свою очередь, сопоставляются с mouseover и mouseout). Вопрос был задан для 1.3.* - person Kees C. Bakker; 19.05.2011
comment
Ой, извините, я пропустил это. Думаю, это все еще может быть полезно для будущих читателей ;-) - person ; 19.05.2011

Я нашел решение этой проблемы: проблема в том, что .live и прокрутка не работают.

Мое решение - использовать событие привязки ... и тайм-аут. Тайм-аут даст DOM время для обновления, например.

Приведенный ниже код используется для загрузки содержимого при прокрутке вниз страницы. Взгляните на setTimeout и привязку.

$('.list').bind("scroll",function(){
    $('.list').height()));
    if($('.list').scrollTop() >= ($('.list').height()+ $(window).height())){        
      setTimeout(function(){    //Time out is used as there is a possibility that
        last_function();
      },200);   
    }
});
person Alex Force    schedule 15.05.2012
comment
Пожалуйста, перепроверьте свой код. Могут быть лишние скобки. - person Zeeshan; 10.06.2013