РЭДЛАЙН
Лучшие решения для Вас и Вашего бизнеса!
На нашем сайте вы можете получить информацию о веб-разработке, обслуживании и продвижении сайта. Интернет-маркетинге. SEO (поисковой оптимизации). Контекстной и медийной рекламе в Интернете. SMM. Регистрации доменов и хостинговых услугах. И современном дизайне сайтов. Вообщем того что касается веб-разработки, а также много другой полезной информации из мира интернета, бизнеса и интернет-технологий...
Создаем доступные и современные сайты, которые работают! Обслуживаем и эффективно продвигаем интернет-проекты с 2006 года!
Главная Web-мастеру Создаем прокрутку списка записей по типу Твиттера без jQuery


Создаем прокрутку списка записей по типу Твиттера без jQuery

jQuery - удивительный инструмент. Но когда его не стоит использовать? В данном уроке мы рассмотрим  вопрос, как создать интересную прокрутку содержания, а затем пересмотрим наш проект на предмет улучшения посредством потенциального отказа от jQuery там, где будет возможно.

 

Введение.

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

Целью нашего материала является показать, что на jQuery можно смотреть как на обычный JavaScript, в котором нет ничего магического. Иногда, ваш код может обладать большей "магией, если из него исключить немного великолепия jQuery.  Очень может быть, что после усвоения данного урока вы будете понимать JavaScript немного лучше.

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

 

Шаг 1. Проект

Вот что мы будем строить. Твиттер для Mac показал отличную идею для реализации. Если запустить приложение и перейти на чью-нибудь страницу, то при прокрутке вниз  станет видно, что иконка аватара присутствует не у всех записей, а "следует" за прокруткой страницы. Если встречаются следующие подряд несколько записей, то аватара выводится только для одной, расположенной на самом верху. При изменении автора записи изменяется и аватар.

Именно такой функционал мы и реализуем. С использованием jQuery выполнить задачу будет достаточно просто.

 

Шаг 2. HTML и CSS

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

<!DOCTYPE HTML>
<html lang="ru">
    <head>
        <meta charset="UTF-8">
        <title>Прокрутка списка в стиле Twitter | Демонстрация для сайта RUSELLER.COM</title>
        <link rel="stylesheet" href="/style.css" />
    </head>
    <body>
        <section>
            <article>
            <img class="avatar" src="/images/one.jpg" />
            <p> Запись, сделанная пользователем.</p>
            </article>
            <article>
            <img class="avatar" src="/images/two.jpg" />
            <p> Запись, сделанная пользователем.</p>
            </article>
            <article>
            <img class="avatar" src="/images/one.jpg" />
            <p>  Запись, сделанная пользователем. 
            Просто текст для демонстрации.</p>
            </article>
            <article>
            <img class="avatar" src="/images/one.jpg" />
            <p> Запись, сделанная пользователем.</p>
            </article>

            <!-- Здесь добавляем еще записей!-->

        </section>

        <script src="/jquery.js"></script>
        <script src="/twitter-scrolling.js"></script>

        <script>
            $("section").twitter_scroll(".avatar");
        </script>
    </body>
</html>

Да, код получился длинным.

Теперь добавим CSS.

body {
    font:13px/1.5 "helvetica neue", helvetica, arial, san-serif;
}
article {
    display:block;
    background: #ececec;
    width:380px;
    padding:10px;
    margin:10px;
    overflow:hidden;
}
article img {
    float:left;
}
article p {
    margin:0;
    padding-left:60px;
}

Здесь только то, что действительно нужно для нашего урока.

 

Шаг 3. JavaScript. Раунд 1.

Надо сказать, что задача выходит за рамки создания виджета JavaScript средней сложности. Вот несколько моментов, которые надо принять во внимание при разработке:

  • Нужно скрывать каждое изображение, если оно одинаковое с предыдущей записью.
  • При прокрутке страницы надо определять, какая запись находится наиболее близко к верху страницы.
  • Если запись является первой в серии, сделанной одной персоной, то необходимо зафиксировать аватар, чтобы он не прокручивался с остальным содержанием страницы.
  • Когда запись является последней в серии одного автора, нужно оставить аватар на соответствующей строке.
  • Все выше описанные моменты должны работать при прокрутке и вверх и вниз.
  • Так как все выполняется каждый раз, при генерации события scroll, то код должен работать быстро.

В начале разработки нужно беспокоиться о работоспособности кода, а оптимизацию выполнять позже. Первая версия будет игнорировать несколько лучших методов работы с jQuery. Версия два предназначена именно для оптимизации кода jQuery.

Будем писать код в виде плагина jQuery:

$(wrapper_element).twitter_scroll(entries_element, unscrollable_element);  

Объект jQuery, для которого вызывается плагин, содержит записи. Первый параметр плагина является селектором элементов, которые будут прокручиваться: записей. Второй параметр - селектор элементов, которые остаются на месте при необходимости (в плагине предполагается, что это будут изображения, но для других элементов плагин легко перенастроить). Итак, для кода HTML, который используется в нашей демонстрации, вызов плагина будет выглядеть следующим образом:

$("section").twitter_scroll("article", ".avatar");

// или

$("section").twitter_scroll(".avatar");

Первый параметр будет опциональным: если он опущен, то мы считаем, что задан селектор элементов, которые не прокручиваются (не прокручиваются - плохой термин, но в рамках урока вполне понятный), а первый селектор будет определяться как непосредственный родитель.

Оболочка плагина:

(function ($) {

    jQuery.fn.twitter_scroll = function (entries, unscrollable) { 

    };
}(jQuery));

 

Установки плагина

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

if (!unscrollable) {
    unscrollable = $(entries);
    entries = unscrollable.parent();
} else {
    unscrollable = $(unscrollable);
    entries = $(entries);
}

Первый параметр: если unscrollable имеет значение false, то мы с помощью jQuery и селектора entries мы устанавливаем значение unscrollable , а самой переменной  entries присваиваем значение родителя unscrollable. Иначе, с помощью jQuery устанавливаются оба параметра. Теперь (если пользователь правильно установил разметку) у нас есть два объекта jQuery, которые соответствуют друг другу и имеют одинаковый индекс: unscrollable[i] является потомком entries[i]. Это пригодиться в дальнейшем. Если предполагать, что пользователь разметил свой документ не правильно, или что используются селекторы, которые выбирают элементы вне нужных нам областей, то можно использовать  this в качестве параметра контекста или метод find для this.

Далее, определим несколько переменных:

var parent_from_top  = this.offset().top,
    entries_from_top = entries.offset().top,
    img_offset       = unscrollable.offset(),
    prev_item        = null,
    starter          = false,
    margin           = 2,
    anti_repeater    = null,
    win              = $(window),
    scroll_top       = win.scrollTop();

Смещения элементов, с которыми мы работаем, очень важны. Метод jQuery offset возвращает объект со свойствами top и left. Для родительского элемента (this внутри плагина) и для самого элемента entries нам нужны только смещения сверху. Для непрокручиваемых  элементов нам нужно использовать смещения сверху и слева.

Переменные prev_item, starter, и anti_repeater будут использоваться далее в обработчика события scroll, где нужны будут значения, существующие независимо от вызовов функций. Переменная win будет использована в нескольких местах. А переменная scroll_top содержит расстояние панели прокрутки от верха экрана. Мы будем использовать ее для определения направления прокрутки.

Далее мы определим, какие элементы являются первым и последним в полосе записей. Существует несколько способов выполнить задачу. Мы будем использовать атрибут HTML5 data для соответствующих элементов.

entries.each(function (i) {
    var img = unscrollable[i];
    if ($.contains(this, img)) {
        if (img.src === prev_item) {
            img.style.visibility = "hidden";
            if (starter) {
                entries[i-1].setAttribute("data-8088-starter", "true");
                starter = false;
            }
            if (!entries[i+1]) {
                entries[i].setAttribute("data-8088-ender", "true");
            }
        } else {
            prev_item = img.src;
            starter = true;
            if (entries[i-1] && unscrollable[i-1].style.visibility === "hidden") {
                entries[i-1].setAttribute("data-8088-ender", "true");
            }
        }
    }
});

prev_item = null;

Мы используем метод jQuery each для объекта entries. Помните, что внутри функции this указывает на текущий элемент из entries. Также у нас есть параметр индекс, который мы используем. Мы получаем соответствующий элемент из объекта unscrollable и сохраняем его в img. Затем, если  наш элемент содержит img (так должно быть, но нам нужно проверить), мы проверяем, что источник изображения тот же, что и prev_item. Если это верно, то мы знаем, что изображение такое же, как и у предыдущей записи. Следовательно, надо скрыть изображение. Использовать свойство display нельзя, так как такое действие будет вызывать удаление изображения из потока документа, а нам не нужно перемещение других элементов на пустое место.

Затем, если значение startertrue, мы устанавливаем предыдущему элементу атрибут data-8088-starter. Все атрибуты HTML5 data должны начинаться с “data-“. А использование собственного суффикса позволяет избежать конфликта с кодом других разработчиков (в данном случае используется код 8088). Атрибут HTML5 data должен иметь строковое значение, но в нашем случае мы используем его только как маркер элемента. Затем устанавливаем значение starterfalse. И если это последний элемент, то маркируем соответствующим образом.

Если источник изображения не совпадает с предыдущим элементом, то изменяем значение prev_item.  Затем устанавливаем значение startertrue. Таким образом, если следующее изображение будет иметь такой же источник, мы промаркируем данный элемент как стартовый. Далее, если есть элемент перед текущим, и его изображение скрыто, то мы знаем, что он является последним в серии с одинаковым изображением (потому что текущий элемент имеет другое изображение). Следовательно, нужно установить соответствующий атрибут маркер.

По завершению обработки установим значение prev_item  null, так как вскоре будем использовать его снова.

Теперь, если взглянуть на разметку после работы функции (например, с помощью Firebug), можно увидеть следующую структуру:

 

Обработчик события scroll

Теперь напишем обработчик события scroll. Здесь есть две задачи, которые надо решить. Первая - нужно найти самый близкий к верху страницы элемент. Вторая -  сделать соответствующие манипуляции с изображением.

$(document).bind("scroll", function (e) {
    var temp_scroll = win.scrollTop(),
        down = ((scroll_top - temp_scroll) < 0) ? true : false,
        top_item = null, child = null;

    scroll_top = temp_scroll;

    // Здесь будет вставляться код

});

Это оболочка нашего обработчика. Создаем несколько переменных. Переменная down определяет направление прокрутки. Переменная scroll_top содержит расстояние от верха, на которое произошла прокрутка.

Теперь присвоим переменной  top_item самый близкий к верху страницы элемент:

top_item = entries.filter(function (i) {
    var distance = $(this).offset().top - scroll_top;
    return ( distance < (parent_from_top + margin) && distance > (parent_from_top - margin) );
});

Мы просто используем метод filter для определения элемента, который должен попасть в перменную top_item. Сначала определяем значение distance как разность уже прокрученного расстояния и смещения элемента сверху. Затем, возвращаем true, если значение distance находится между parent_from_top + margin и parent_from_top - margin. Нам необходимо учесть смещение контейнера сверху. Кроме того, событие scroll может генерироваться при некотором смещении от точного значения положения верха. Поэтому надо учесть поле, чтобы использовать диапазон, а не определённую точку.

Теперь у нас есть верхний элемент и можно работать дальше.

if (top_item) {
    if (top_item.attr("data-8088-starter")) {
        if (!anti_repeater) {
            child = top_item.children(unscrollable.selector);
            anti_repeater = child.clone().appendTo(document.body);
            child.css("visibility", "hidden");
            anti_repeater.css({
                'position' : 'fixed',
                'top'      : img_offset.top + 'px',
                'left'     : img_offset.left + "px"
            });
        }
    } else if (top_item.attr("data-8088-ender")) {
        top_item.children(unscrollable.selector).css("visibility", "visible");
        if (anti_repeater) { anti_repeater.remove(); }
        anti_repeater = null;
    } 

    if (!down) {
        if (top_item.attr("data-8088-starter")) {
            top_item.children(unscrollable.selector).css("visibility", "visible");
            if (anti_repeater) { anti_repeater.remove(); }
            anti_repeater = null;
        } else if (top_item.attr("data-8088-ender")) {
            child = top_item.children(unscrollable.selector);
            anti_repeater = child.clone().appendTo(document.body);
            child.css("visibility", "hidden");
            anti_repeater.css({
                'position' : 'fixed',
                'top'      : img_offset.top + 'px',
                'left'     : img_offset.left + "px"
            });
        }
    }
}

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

Если верхний элемент имеет атрибут data-8088-starter , то поверяем значение переменной anti_repeater. Данная переменная указывает на элемент изображения, который фиксируется при прокрутке. Если значение anti_repeater еще не установлено, то получаем наследника нашего элемента top_item, который имеет такой же селектор, как и unscrollable (далее код будет оптимизирован). Затем мы клонируем его и добавляем к body.  Затем скрываем оригинал, а клон размещаем туда, куда нужно.

Если элемент не имеет атрибута data-8088-starter, то проверяем наличие атрибута data-8088-ender. Если данный атрибут присутствует, находим потомка и делаем его видимым, а затем устанавливаем значение переменной anti_repeater  null.

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

 

Проверка производительности

Итак, наш код делает то, что нужно. Но при проверке видно, что прокрутка осуществляется очень медленно. Можно добавить строки console.profile("scroll") и console.profileEnd() к первой и последней строкам функции обработки события scroll. Обработка может занять от 2.5ms до  4ms, и будет сделано 166 – 170 вызовов функции.

Очень медленная обработка. Некоторые функции вызываются 30-31 раз. В нашем тестовом списке 30 элементов. Поэтому, чем больше элементов мы будем иметь в списке, тем медленнее будет работать прокрутка! Нужно искать пути оптимизации процесса.

 

Шаг 4. JavaScript. Раунд 2

Если вы подозреваете, что jQuery является главным виновником данного безобразия, то окажетесь правы. Библиотеки, подобные jQuery очень удобны и облегчают работу с DOM, но плата за удобство - производительность. В нашем случае нужно использовать более продуктивный код. Откажемся от части кода jQuery в пользу непосредственной работы со структурой DOM, что, на самом деле, окажется не таким уж сложным процессом.

 

Обработчик события Scroll

Разберемся с очевидной частью, с тем, что мы делаем с top_item, как только находим его. В текущий момент top_item является объектом jQuery. Однако, все что мы делаем с помощью jQuery с top_item тривиально сделать без использования библиотеки.

Вот что можно изменить для ускорения процесса:

  • Перестроить выражение if для исключения повторений (это, скорее, касается структуры кода, а не производительности).
  • Можно использовать метод JavaScript  getAttribute вместо метода jQuery attr.
  • Можно получать элемент из unscrollable, который соответствует элементу top_item, вместо использования unscrollable.selector.
  • Можно использовать методы JavaScript clodeNode и appendChild вместо версий jQuery.
  • Можно использовать свойство style вместо метода jQuery css.
  • можно использовать метод JavaScript removeNode вместо метода jQuery remove.

Применив все идеи, получим следующий код:

if (top_item) {
    if ( (down && top_item.getAttribute("data-8088-starter")) || ( !down && top_item.getAttribute("data-8088-ender") ) ) {
        if (!anti_repeater) {
            child = unscrollable[ entries.indexOf(top_item) ];
            anti_repeater = child.cloneNode(false);
            document.body.appendChild(anti_repeater);
            child.style.visibility = "hidden";
            style = anti_repeater.style;
            style.position = 'fixed';
            style.top = img_offset.top + 'px';
            style.left= img_offset.left + 'px';
        }
    }
    if ( (down && top_item.getAttribute("data-8088-ender")) || (!down && top_item.getAttribute("data-8088-starter")) ) {
        unscrollable[ entries.indexOf(top_item) ].style.visibility = "visible";
        if (anti_repeater) { anti_repeater.parentNode.removeChild(anti_repeater); }
        anti_repeater = null;
    }
}


Данный код существенно лучше не только потому, что выброшены повторения, но и не используется jQuery.

Также оптимизации можно подвергнуть процесс получения  top_item. В текущий момент мы используем метод jQuery filter. Если вы хорошо подумаете, то распознаете ущербность такого способа. Мы знаем, что будем получать только один элемент с помощью фильтра, но метод filter об этом не знает и продолжает работать после того, как нужный элемент найден. В тестовом списке 30 элементов, так что перебор занимает достаточное количество времени. Сделаем вот так:

for (i = 0; entries[i]; i++) {
    distance = $(entries[i]).offset().top - scroll_top;
    if ( distance < (parent_from_top + margin) && distance > (parent_from_top - margin) ) {
        top_item = entries[i];
        break;
    }
}

(В качестве альтернативы можно использовать цикл while с условием !top_item. Разницы, практически, никакой нет.)

Таким образом, как только мы находим top_item, поиск прекращается. Однако можно еще улучшить алгоритм. Так как прокрутка линейна, то можно предположить, какой элемент окажется ближе всего к верху страницы. Если прокрутка была вниз, то поиск нужно вести с последнего самого близкого элемента вниз по списку. А при прокрутке вверх - с последнего самого близкого элемента вверх по списку. Однако в текущий момент поиск всегда ведется от самого верхнего элемента на странице.

Как реализовать задуманные изменения? Начнем с сохранения top_item от предыдущего запуска обработчика события scroll:

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

if (prev_item) {
    prev_item = $(prev_item);
    height = height || prev_item.outerHeight();
    if ( down && prev_item.offset().top - scroll_top + height < margin) {
        top_item = entries[ entries.indexOf(prev_item[0]) + 1];
    } else if ( !down && (prev_item.offset().top - scroll_top - height) > (margin + parent_from_top)) {
        top_item = entries[ entries.indexOf(prev_item[0]) - 1];
    } else {
        top_item = prev_item[0];
    }
} else {
    for (i = 0; entries[i]; i++) {
        distance = $(entries[i]).offset().top - scroll_top;
        if ( distance < (parent_from_top + margin) && distance > (parent_from_top - margin) ) {
            top_item = entries[i];
            break;
        }
    }
}

Если переменная prev_item имеет значение, значит, мы можем использовать ее для поиска следующего элемента top_item. Здесь используется небольшой трюк:

  • Если предыдущий элемент находится полностью над верхом страницы, берем следующий элемент  (можно использовать индекс prev_item + 1 для получения нужного элемента в entries).
  • Если прокрутка происходит вверх, и предыдущий элемент достаточно далеко под страницей, берем предшествующий ему элемент.
  • В противном случае используем тот же элемент, что и в последний раз.
  • Если нет значения в top_item, то используем цикл для поиска.

Есть еще несколько моментов. Что такое переменная height? Если все элементы имеют одинаковую высоту, то мы можем исключить вычисление высоты при каждом вызове обработчика события scroll, перенеся вычисления в установки плагина. Добавляем в раздел установок:

height = entries.outerHeight();
if (entries.length !== entries.filter(function () { return $(this).outerHeight() === height; }).length) {
    height = null;
}

Метод jQuery outerHeight возвращает высоту элемента, включая отступы и поля. Если все элементы имеют одинаковую высоту с первым элементом, то height будет установлена, а в противном случае значение height будет null. При определении top_item можно использовать height, если она имеет значение.

Есть еще один момент. Можно подумать, что вычисление  prev_item.offset().top выполняется дважды. В действительности оно выполняется только один раз, так как второе выражение if  выполняется только в случае, если значение down является false. Так как мы используем логический оператор AND, то вторая часть двух выражений if никогда не будет вызываться в одно и то же время. Конечно же, вы можете использовать перменную, если считаете нужным в данном случае, но она никак не повлияет на производительность.

Однако есть еще над чем поработать. Безусловно, наш обработчик стал быстрее, но мы можем сделать дополнительные улучшения. Мы используем jQuery только для двух процессов: получаем outerHeight для prev_item, и получаем смещение от верха для prev_item. Для таких мелочей слишком большое расточительство, использовать объекты jQuery. Но моментального решения для замещения jQuery в данном случае нет. Нужно погрузиться в код jQuery, чтобы точно определить, что делает библиотека.  Таким образом, мы сможем заменить небольшую часть кода без использования избыточного веса остального jQuery.

Начнем со смещения от верха. Вот код jQuery для метода offset:

function (options) {
    var elem = this[0];

    if (!elem || !elem.ownerDocument) {
        return null;
    }

    if (options) {
        return this.each(function (i) {
            jQuery.offset.setOffset(this, options, i);
        });
    }

    if (elem === elem.ownerDocument.body) {
        return jQuery.offset.bodyOffset(elem);
    }

    var box = elem.getBoundingClientRect(),
        doc = elem.ownerDocument,
        body = doc.body,
        docElem = doc.documentElement,
        clientTop = docElem.clientTop || body.clientTop || 0,
        clientLeft = docElem.clientLeft || body.clientLeft || 0,
        top = box.top + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop) - clientTop,
        left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;

    return {
        top: top,
        left: left
    };
}

Выглядит сурово. Однако не все так плохо. Нам нужно только смещение сверху. Поэтому можно смело выкинуть часть кода, которая касается смещения слева и сделать свою функцию:

function get_top_offset(elem) {
    var doc = elem.ownerDocument,
        body = doc.body,
        docElem = doc.documentElement;

    return elem.getBoundingClientRect().top +
        (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop) -
            docElem.clientTop || body.clientTop || 0;
}


Все, что нужно сделать - это передать в нее элемент DOM. И мы получим смещение! Теперь можно заменить все вызовы offset().top нашей функцией.

А как на счет outerHeight? Здесь будет небольшой трюк, так как в данном случае используется внутренняя функция jQuery.

function (margin) {
    return this[0] ? jQuery.css(this[0], type, false, margin ? "margin" : "border") : null;
}

В действительности здесь происходит только вызов функции css с параметрами: элемент, “margin”, “border”, и false. Вот как она выглядит:

function (elem, name, force, extra) {
    if (name === "width" || name === "height") {
        var val, props = cssShow,
            which = name === "width" ? cssWidth : cssHeight;

        function getWH() {
            val = name === "width" ? elem.offsetWidth : elem.offsetHeight;

            if (extra === "border") {
                return;
            }

            jQuery.each(which, function () {
                if (!extra) {
                    val -= parseFloat(jQuery.curCSS(elem, "padding" + this, true)) || 0;
                }

                if (extra === "margin") {
                    val += parseFloat(jQuery.curCSS(elem, "margin" + this, true)) || 0;
                } else {
                    val -= parseFloat(jQuery.curCSS(elem, "border" + this + "Width", true)) || 0;
                }
            });
        }

        if (elem.offsetWidth !== 0) {
            getWH();
        } else {
            jQuery.swap(elem, props, getWH);
        }

        return Math.max(0, Math.round(val));
    }

    return jQuery.curCSS(elem, name, force);
}

В данной функции можно легко потеряться, но распутать логику стоит... Потому что решение удивительно! Все, что нам нужно - использовать свойство элемента offsetHeight!

Таким образом, наш код превращается в:

if (prev_item) {
    height = height || prev_item.offsetHeight;
    if ( down && get_top_offset(prev_item) - scroll_top + height < margin) {
        top_item = entries[ entries.indexOf(prev_item) + 1];
    } else if ( !down && (get_top_offset(prev_item) - scroll_top - height) > (margin + parent_from_top)) {
        top_item = entries[ entries.indexOf(prev_item) - 1];
    } else {
        top_item = prev_item;
    }
} else {
    for (i = 0; entries[i]; i++) {
        distance = get_top_offset(entries[i]) - scroll_top;
        if ( distance < (parent_from_top + margin) && distance > (parent_from_top - margin) ) {
            top_item = entries[i];
            break;
        }
    }
}

Теперь нет необходимости в объекте jQuery! И если запустить проверку производительности опять, то результат будет существенно лучше и иметь только пару вызовов функций.

 

Полезный инструмент

В таких случаях очень полезным инструментом является проект jQuery Source Viewer, с помощью которого можно исследовать внутренности jQuery.

 

Заключение

В данном уроке мы рассмотрели процесс создания прокрутки списка записей. Но главное заключается в другом:

  • Факт, что ваш код выполняет то, что задумывалось, не означает, что он ясный, или быстрый, или его нельзя улучшить
  • jQuery — или другая ваша любимая библиотека — это простой JavaScript. Она тоже может быть медленной и иногда от нее лучше отказаться.
  • Лучший способ для развития разработчика - выйти из зоны комфорта.

 

Источник: http://feedproxy.google.com/~r/ruseller/CdHX/~3/F64BkzIs_-s/lessons.php

Создаем прокрутку списка записей по типу Твиттера без jQuery | | 2012-06-19 12:08:29 | | Статьи Web-мастеру | | jQuery - удивительный инструмент. Но когда его не стоит использовать? В данном уроке мы рассмотрим  вопрос, как создать интересную прокрутку содержания, а затем пересмотрим наш проект на предмет | РэдЛайн, создание сайта, заказать сайт, разработка сайтов, реклама в Интернете, продвижение, маркетинговые исследования, дизайн студия, веб дизайн, раскрутка сайта, создать сайт компании, сделать сайт, создание сайтов, изготовление сайта, обслуживание сайтов, изготовление сайтов, заказать интернет сайт, создать сайт, изготовить сайт, разработка сайта, web студия, создание веб сайта, поддержка сайта, сайт на заказ, сопровождение сайта, дизайн сайта, сайт под ключ, заказ сайта, реклама сайта, хостинг, регистрация доменов, хабаровск, краснодар, москва, комсомольск |
 
Дайджест новых статей по интернет-маркетингу на ваш email
Подписаться

Продающие сайты "под ключ"!

Наши сайты зарабытывают вам деньги. Landing-page. Эффективные продающие сайты точно в срок и под ключ! Всего от 14700 рублей
Подробнее...

Интернет-магазины и каталоги "под ключ"!

Эффективные и удобные инструменты торговли (электронной торговли) "под ключ". Продают, даже когда вы спите! Всего от 33800 рублей
Подробнее...

Комплексный интернет-маркетинг и продвижение сайтов

Максимальную эффективность дает не какой-то конкретный метод, а их комбинация. Комбинация таких методов и называется комплексным интернет-маркетингом. Всего от 8000 рублей в месяц
Подробнее...

Реклама в Yandex и Google

Контекстная реклама нацелена лишь на тех пользователей, которые непосредственно заинтересованы в рекламе Ваших услуг или товаров. Всего от 8000 рублей в месяц
Подробнее...

Social media marketing (SMM) — продвижение в социальных медиа

Реклама в Однокласcниках и на Mail.ru Создание, ведение и раскрутка групп и реклама ВКонтакте и Facebook. Всего от 8000 рублей в месяц
Подробнее...

Приглашаем к сотрудничеству рекламные агентства и веб-студии!

Внимание Акция! Приглашаем к сотрудничеству рекламные агентства и различные веб-студии России! Индивидуальные и взаимовыгодные условия сотрудничества.
Подробнее...

Ускоренная разработка любого сайта от 5 дней!

Внимание Акция! Ускоренная разработка любого сайта! Ваш сайт будет готов за 5-10 дней. Вы можете заказать разработку любого сайта "под ключ" за 5-10 рабочих дней, с доплатой всего 30% от его стоимости!
Подробнее...

Ждем новых друзей!

Внимание Акция! Ждем новых друзей! Скидка 10% на услуги по созданию и(или) обслуживанию вашего сайта при переходе к нам от другого разработчика.
Подробнее...

Приведи друга и получи скидку!

Внимание Акция! Приведи друга и получи скидку! Скидка 10% на услуги по созданию и(или) обслуживанию вашего сайта, если клиент заказавший наши услуги, пришел по Вашей рекомендации.
Подробнее...

1 2 3 4 5 6 7 8 9

Новые статьи и публикации


Услуги интернет компании Редлайн

На голодный желудок русский человек ничего делать и думать не хочет, а на сытый - не может

Раневская Фаина Георгиевна - (1896-1984) - выдающаяся советская актриса театра и кино

Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!

Качественное и объемное представление своего бизнеса в Сети требуется любой растущей коммерческой структуре, стремящейся увеличить продажи, именно по этой причине среди наших клиентов как крупные так и небольшие компании во многих городах России и ближнего зарубежья.
Как мы работаем

Заявка
Позвоните или оставьте заявку на сайте.


Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!


Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.


Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.


Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.

Остались еще вопросы? Просто позвоните и задайте их специалистам
с 2:30 до 11:30 по Мск, звонок бесплатный
Или напишите нам в WhatsApp
с 9:30 до 18:30 по Хабаровску
Или напишите нам в WhatsApp
Веб-студия и агентство комплексного интернет-маркетинга «РЭДЛАЙН» © 2006 - 2024

Профессиональная Веб-разработка. Создание сайтов и магазинов "под ключ" , а также по всей России и зарубежью. Продвижение и реклама. Веб-дизайн. Приложения. Сопровождение. Модернизация. Интеграции. Консалтинг. Продвижение и реклама. Комплексный Интернет-маркетинг.

Оставьте заявку / Задайте вопрос

Нажимая на кнопку ОТПРАВИТЬ, я даю согласие на обработку персональных данных
×

Заказать услугу

Нажимая на кнопку ОТПРАВИТЬ, я даю согласие на обработку персональных данных
×

Обратный звонок

Нажимая на кнопку ОТПРАВИТЬ, я даю согласие на обработку персональных данных
×

Подписка на дайджест новостей

Нажимая на кнопку ОТПРАВИТЬ, я даю согласие на обработку персональных данных
×

Заказать услуги со скидкой \ Бесплатная консультация







КАКИЕ УСЛУГИ ВАС ИНТЕРЕСУЮТ?

КАКИЕ ДОПОЛНИТЕЛЬНЫЕ УСЛУГИ ПОТРЕБУЮТСЯ?

Нажимая на кнопку ОТПРАВИТЬ, я даю согласие на обработку персональных данных
×

Высококачественные сайты по доступным ценамМы создаем практически любые сайты от продающих страниц до сложных, высоконагруженных и нестандартных веб приложений! Наши сайты это надежные маркетинговые инструменты для успеха Вашего бизнеса и увеличения вашей прибыли! Мы делаем красивые и максимально эффектные сайты по доступным ценам уже много лет!

Что нужно сделать, чтобы заказать создание сайта у нас?

Ну для начала вам нужно представлять (хотя бы в общих чертах), что вы хотите получить от сайта и возможно каким вы хотите его видеть. А дальше все просто. Позвоните нам или оставьте заявку нашим менеджерам, чтобы они связались с Вами, проконсультировали и помогли определиться с подходящим именно Вам сайтом по цене, сроку, дизайну или функционалу. Если вы все ещё не уверены, какой сайт вам нужен, просто обратитесь к нам! Мы вместе проанализируем вашу ситуацию и определим максимально эффективный для вас вариант.

Быстрый заказ \ Консультация

Для всех тарифных планов на создание и размещение сайтов включено:

Комплексная раскрутка сайтов и продвижение сайта Комплексный подход это не просто продвижение сайта, это целый комплекс мероприятий, который определяется целями и задачами поставленными перед сайтом и организацией, которая за этим стоит. Время однобоких методов в продвижении сайтов уже прошло, конкуренция слишком высока, чтобы была возможность расслабиться и получать \ удерживать клиентов из Интернета, просто сделав сайт и не занимаясь им...

Комплексная раскрутка работает в рамках стратегии развития вашего бизнеса в сети и направлена

Быстрый заказ \ Консультация

ЭФФЕКТИВНОЕ СОПРОВОЖДЕНИЕ (ПОДДЕРЖКА, ОБСЛУЖИВАНИЕ) САЙТОВ

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

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

Наша компания осуществляет техническую и информационную поддержку уже имеющихся сайтов. В понятие «поддержка сайтов» также входят услуги администрирования сайтов, обновления сайтов и их модернизация.

Быстрый заказ \ Консультация

Редизайн сайта и Адаптивный веб дизайн

Современный, технологичный, кроссбраузерный ... Профессиональный дизайн сайтов и веб-приложений

Редизайн сайта — создание нового дизайна сайта с целью улучшения внешнего вида, функциональности и удобства использования. Редизайн сайта – это способ преобразовать проект к извлечению из него максимальной отдачи и средств. В современном мире задачами редизайна является поднятие существующего сайта на новый уровень для внедрения новых технологий, при этом сохраняя многолетний сформировавшийся опыт и успешные решения компаний.

Адаптивный дизайн сайтов и веб-приложений

Все больше людей пользуются мобильными устройствами (телефонами, планшетами и прочими) для посещения Интернета, это не для кого уже не новость. Количество таких людей в процентном отношении будет только больше с каждым годом, потому что это удобно и по многим другим причинам.

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

Быстрый заказ \ Консультация

Контекстная реклама в Яндекс и GoogleКонтекстная реклама - это эффективный инструмент в интернет маркетинге, целью которого является увеличение продаж. Главный плюс контекстной рекламы заключается в том, что она работает избирательно.

Реклама в поисковых системах Яндекс и Google. Профессиональная настройка рекламы и отслеживание эффективности!

Рекламные объявления показываются именно тем пользователям, которые ищут информацию о Ваших товарах или услугах, поэтому такая реклама не является навязчивой и раздражающей в отличие от других видов рекламы, с которыми мы сталкиваемся на телевидении или радио. Контекстная реклама нацелена лишь на тех пользователей, которые непосредственно заинтересованы в рекламе Ваших услуг или товаров.

Быстрый заказ \ Консультация

Скидка

1500 руб.
Заинтересовались услугами создания, обслуживания или продвижения вашей компании в Интернете?!
Получите 1500 руб.
за он-лайн заявку
Предложение ограничено.

После получения заявки с Вами свяжутся наши специалисты и уточнят все детали по интересующей вас услуге.
«Нажимая на кнопку "Получить скидку", я даю согласие на обработку персональных данных»
×
Получите 1500 рублей!
×
×