Нововведения в jQuery 1.6

    jquery
    Совсем недавно (3 мая) был зарелизен jQuery 1.6 и вот что нового появилось в этой js-библиотеке давайте и посмотрим.

    Самое «веселое» то, что в новом релизе есть важные изменения, которые несовместимы с предыдущими версиями jQuery. И в результате при переходе на новую версию, вполне возможно, что придётся просматривать и изменять уже существующий код.

    Критические изменения


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

    Доступ к данным в data-атрибутах

    Теперь доступ к значениям в этих атрибутах соответствует спецификации W3C HTML5 spec, т.е. ключи надо передавать в camel-case формате.
    <div id="div1" data-test-value="123"></div>
    

    Для jQuery 1.5 писали так:
    var tv = $('#div1').data('test-value'); // => 123
    // или так
    var d = $('#div1').data(); // => { "test-value": 123 }
    tv = d['test-value']; // => 123
    

    Теперь для jQuery 1.6 надо писать так:
    var tv = $('#div1').data('testValue'); // => 123
    // или так
    var d = $('#div1').data(); // => { "testValue": 123 }
    tv = d.testValue; // => 123
    


    .prop(), .removeProp() и .attr()

    Также теперь отделены свойства элементов от их атрибутов. Для доступа к атрибутам остался метод .attr(), а для доступа к свойствам элемента, которые могут меняться динамически (значения атрибутов при этом не меняются), теперь нужно делать через .prop(). Самым простым примером может быть поведение <input type="checkbox" />: в 1.5 вызов .attr('checked') возвращал true/false в зависимости от установки флага, в версии же 1.6 .attr('checked') вернёт строковое значение, записанное в атрибут, или undefined, если атрибут отсутствует, а состояние флага нужно получать через .prop('checked').
    Поиграться с примерами можно тут: на 1.5 jsfiddle.net/dV27a/1, на 1.6 jsfiddle.net/9zEC9/1
    .removeProp() следует использовать с особой осторожностью, т.к. чревато глюками в некоторых браузерах.
    Во втором примере можно наблюдать глюк в Google Chrome, и это глюк именно браузера — воспроизводится и без jQuery. Глюк в следующем: если у элемента <input type="checkbox" /> через его js-объектную модель устанавливать свойство checked — то флаг изначально меняется, но если удалить это свойство так delete cb.checked, то после этого изменение свойства не приводит к изменению состояния флага.

    В связи с описанным выше, появились некоторые изменения для булевых атрибутов (таких как checked, selected и подобных), теперь .attr('checked', true/false) добавляет или удаляет указанный атрибут (а мы помним, что теперь эта функция работает именно с атрибутом, а не со свойством объекта).

    Некритические изменения


    Расширяемость .attr() и .val()


    В новой версии была добавлена возможность влиять на работу функций .attr() через объект jQuery.attrHooks и на функцию .val() через объект jQuery.valHooks. Например:
    jQuery.attrHooks.selected = {
        set: function( elem, value ) {
            if ( value === false ) {
                jQuery.removeAttr(elem, “selected”);
                return value;
            }
        }
    };
    


    jQuery.map(Object)


    Теперь функция jQuery.map() может принимать первым аргументом не только массив, но и объект, однако возвращать будет массив значений в любом случае.
    $.map({ f: 1, s: 2 }, function(v, k) { return ++v; }); // => [ 2, 3 ]
    


    Зависимое изменение CSS


    Разработчики добавили возможность изменения css-свойств элементов функцией .css() в зависимости от их значения с помощью инструкций "+=" и "-=", как это сделано в .animate().
    $("#item").css("left", "+=10px");
    


    Deferred-объекты


    Были внесены улучшения и в deferred-объекты, которые добавлены в 1.5 (тем, кто про них ещё не знает, советую почитать jQuery Deferred Object (подробное описание))

    deferred.always()

    Когда нужно, чтобы некоторый обработчик вызывался при любом исходе раньше приходилось писать deferred.then(handler, handler), а теперь можно написать deferred.always(handler)

    deferred.pipe()

    Это новый метод и решает сразу несколько проблем, во-первых с помощью него можно создавать фильтры значений, передаваемых в обработчики параметрами, во-вторых можно строить цепочки из отложенных-заданий (например, асинхронных запросов — эта тема поднималась в комментариях к моей предыдущей статье и вот разработчики предоставили решение этой проблемы).
    Пример фильтра (для deferred.reject — аналогично), во второй обработчик первым и единственным параметром попадает значение, которое вернёт первый обработчик.
    var defer = $.Deferred(),
        filtered = defer.pipe(function( value ) {
            return value * 2;
        });
    defer.resolve( 5 );
    filtered.done(function( value ) {
        alert( "Value is ( 2*5 = ) 10: " + value ); // value = 10
    });
    

    Запустить: jsfiddle.net/txzPj

    Пример цепочки асинхронных запросов, во второй обработчик будут переданы параметры, с которыми будет завершен второй deferred-объект.
    var request = $.ajax( '/echo/json/', { dataType: "json", type: 'post', data: { json: '{ "test": 8 }' }, delay: 3 } ),
        chained = request.pipe(function( data ) {
            console.log(data);
            alert('first response');
            return $.ajax( '/echo/json/', { type: 'post', data: { delay: 3, json: '' + data.test } } );
        });
    
    chained.done(function( data ) {
        console.log(data);
        alert('second response');
    });
    

    Запустить: jsfiddle.net/5gfS8

    Анимация


    Кроме улучшения в самом процессе анимирования, в версии 1.6 можно использовать deferred-объекты, завязанные на анимацию. Нет, метод .animate() (и его сокращения .fadeOut(), slideUp() и пр.) не стали возвращать deferred, вместо этого появилась возможность использовать любой jquery-объект в качестве параметра функции $.when(), и если среди выбранных элементов есть какие-то с анимацией, то полученный deferred-объект будет завершён после завершения всей анимации.
    $(".elements").fadeOut();
    
    $.when($(".elements")).done(function(elements) {
        // здесь для всех ".elements" анимация завершена
    });
    


    jQuery.holdReady()


    Этот метод позволяет приостановить выполнение обработчиков события ready, использоваться он будет преимущественно разработчиками плагинов (по крайней мере, так планируют авторы jQuery).
    jQuery.holdReady( true ); // приостановили выполнение обработчиков
    // запустили какой-то код, например асинхронный запрос
    // и когда наш асинхронный запрос выполнился, можем разрешить выполнение остальных обработчиков
    jQuery.holdReady( false );
    


    Селектор ":focus"


    Теперь стало совсем просто найти в документе элемент, на котором установлен фокус.

    Дополнительные возможности в функциях обхода DOM


    В новой версии добавили возможность передавать аргументом в функции .find(), .closest() и .is() ещё и jquery-объекты, наконец-то…



    Текст этой статьи — это вольный пересказ blog.jquery.com/2011/05/03/jquery-16-released (не перевод, хотя и очень близко к тексту).
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 46
    • +4
      Забыли еще одно важное изменение — скорость выполнения .data() наконец-то сопоставима со скоростью выполнения .attr(). При тысячах вызовов разница в скорости была довольно весомой и приходилось использовать второе.
      • +3
        Мде… а я еще с 1.5 не успел наиграться…
        • +1
          Кстати, по непонятным причинам CDN от гугла до сих пор не имеет 1.6 ( docs.jquery.com/Downloading_jQuery и code.google.com/intl/uk-UA/apis/libraries/devguide.html#jquery — только 1.5.2)

          Хотя Micrsoft уже CDN-ят… странно как-то.
        • +64
          Хороший топик. Именно так должны выглядеть топики про новый релиз jQuery, а не «Вышел jQuery 1.6»
          • +3
            Капец, как же быстро она развивается!
          • +2
            tv = ['test-value'];

            видимо имелось в виду

            tv = d['test-value'];
            • 0
              абсолютно верно, спасибо.
              • 0
                id=«div1» data-test-value=«0»
                видимо имелось ввиду
                id=«div1» data-test-value=«123»
                • +1
                  Простите меня, ночь уже была… :)
            • +6
              Разработчики добавили возможность изменения css-свойств элементов функцией .css() в зависимости от их значения с помощью инструкций "+=" и "-="

              Как же я рад! Спасибо!
              • 0
                Эх, еще бы в сам CSS такую фичу! Мечты-мечты…
              • 0
                а есть что то типа visualjquery, но посвежей ?) а то больно хороший ман был
              • 0
                C каждой версией всё лучше и лучше, и нет ощущения «нагроможденности» )
                • +4
                  ого, jqapi.com/ уже для 1.6
                  Шустро, молодцы.
                  • 0
                    «ключи надо передавать в camel-case формате» — насколько я знаю camelcase — это записьТакогоФормата, а в примере идет разделение дефисом.
                    • +1
                      Читайте внимательнее, пример есть и для версии 1.5 — там-дефисом, есть и для 1.6 — тамCamelCase
                      • +1
                        Простите, был напуган, все верно.
                      • +2
                        Ну, формально, записьТакогоФормата — это camelBack :)
                        CamelCase — это ЗаписьТакогоФормата.
                        • +1
                          Не согласен. Есть lowerCamelCase & UpperCamelCase.
                          • 0
                            Понапридумывают терминов…
                            • 0
                              Термины не новые и давно известные.
                            • 0
                              встречал то, что второе называется PascalCase
                        • 0
                          Интересно зачем было ломать старый attr, а не ввести просто новый метод attr2?
                          Возможно это проблема авторов плагинов, но вот у меня 7 из 9 сторонних плагинов из нового attr отвалились.
                          • +2
                            Очень часто авторы библиотек и фреймворков становятся перед выбором: новые костыли для обратной совместимости или изменение интерфейса. Как правило, первый подход сильно усложняет код и в конечном итоге ведет к удорожанию поддержки и снижению эффективности, а второй может вызвать неприятие сообщества. Как правило фреймворки идут по первому пути и в итоге задыхаются под собственной тяжестью, вытесняемые молодыми конкурентами. Второй путь требует определенного мужества и сопряжен с риском. Но я рад, что ребята из jQuery выбрали именно его
                            • 0
                              Старый attr() работает отлично. Мне лично код для совместимости с новым его поведением править не пришлось. Просто не надо было делать вот так:
                              var a = $('input').attr('value');
                              var b = $('[type=checkbox]').attr('checked')

                              Это мало того что некрасиво, так теперь еще и неправильно.
                              • 0
                                Вот здесь я, кстати, наврал. Обратите внимание на
                                $('.mycheckbox').attr('checked', true);
                                $('.mycheckbox').attr('checked', false);

                                Не самый красивый код для временной совместимости 1.5 и 1.6
                                $('.mycheckbox:not(:checked)').click();
                                $('.mycheckbox:checked').click();


                                Код работает только в базовых случаях, на практике все может пройти не так гладко.
                                • 0
                                  Для совместимости проще, наверное, работать напрямую со свойствами, а не с атрибутами:
                                  var a = ($('.mycheckbox')[0] || {}).checked; // чтение
                                  $('.mycheckbox').each(function() { this.checked = true; }); // запись
                                  

                                  По сути, именно так и работает .prop()
                            • 0
                              Для тех кто не очень глубоко в теме — это сильно страшно, нет?
                              • +3
                                Не забудьте о найденном неприятном баге — jQuery 1.6 отправляет IE6 в бесконечный цикл. Исправление будет в 1.6.1 в конце недели. Если прямо так уж не терпится выпустить 1.6 в продакшн — ручки в помощь. Мне вот, например, не терпится, поскольку data наконец соответсвует спецификации и ей можно пользоваться.
                                • 0
                                  о. теперь понятно, что изза attr у меня был баг на одном сайте (:
                                  • 0
                                    Подскажите где почитать подробнее про data (желательно на русском)?
                                  • 0
                                    А вот только что вышел jQuery 1.6.1 RC1
                                  • 0
                                    Давайте на чистоту, что-то перемудрили
                                    • 0
                                      $("#id INPUT, #id SELECT").attr(«disabled»,""); — не пашет (работало в 1.5 )

                                      $("#id INPUT, #id SELECT").attr(«disabled»,false); — пашет (работает в 1.6)

                                      мне кажется это противоречит их нововведениям: «в 1.5 вызов .attr('checked') возвращал true/false в зависимости от установки флага, в версии же 1.6 .attr('checked') вернёт строковое значение, записанное в атрибут»

                                      а вы как считаете?

                                      извините, предыдущий коммент сам запостился при вставке строк через (Ctrl + V) удалять или исправлять свои комменты похоже нельзя
                                      • 0
                                        Если исходить из того, что было в 1.5 и что стало в 1.6, то может быть и перемудрили, но вот если бы они так делали изначально — то это было бы правильнее, на мой взгляд, чем было в 1.5. Поэтому они внесли нужные изменения, которые да, вызвали проблемы с переходом на сл. версию, но, ИМХО, изменения нужные.
                                        • 0
                                          мне кажется вы недопоняли мой пост, в 1.6 они сделали:
                                          $("#id").attr(«checked»,«checked»)
                                          а было:
                                          $("#id").attr(«checked»,true)
                                          и я согласен, правильно сделали, но зачем менять
                                      • 0
                                        … продолжаю (у хабра проблемы с сочетаниями клавишь в ФФ):
                                        но зачем менять
                                        $("#id").attr(«disabled»,false);
                                        когда было
                                        • 0
                                          $("#id").attr(«disabled»,""); — это ведь правильней, они же так поступили с «checked», зачем менять на противоположный для «disabled»?
                                          • 0
                                            извините за комментарий который получился по кусочкам, хабр реально глючит, пришлось это сообщения сначала набрать в блокноте )))

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