Учимся работать с jQuery шаблонами

В этом уроке, мы рассмотрим, как можно использовать jQuery шаблоны для того, чтобы окончательно и бесповоротно отделить наш HTML код от JavaScript скриптов. Так же мы быстро пройдёмся по новой структуре AJAX модуля, который был введён в JQuery 1.5.

Что такое шаблоны?

С выпуском jQuery, жизнь разработчиков стала значительно проще. Например мы без труда можем сделать следующее:

$("#someElement").children().each(function() {
    $(this).wrap($("<div></div>"));
});

Этот код поместит всех потомков элемента с id #someElement в тег <div>. В подобных операциях нет ничего плохого; это выражение абсолютно верно составлено и является очень удобным в некоторых ситуациях. Но HTML код, помещённый в наш сценарий – это нарушение структурной логики кода. В этом простом примере это нарушение не является существенным, однако в реальных проектах это очень распространено. Обычно подобный код содержит множество HTML фрагменты, которые выстраиваются в DOM после получения данных из AJAX запросов. Такой стиль может быстро превратиться в нечто, что будет крайне не читабельно.

Использование шаблонов позволит нам устранить этот недостаток, путём отделения HTML фрагментов от скриптов, таким образом разделить логику содержания разных видов кода. В процессе, я не могу не показать вам некоторые супер интересные нововведения, касающиеся AJAX, введённые jQuery 1.5.

Начало

В этом примере мы будем разрабатывать Twitter виджет, который будет загружать не только наши самые последние сообщения, но и список друзей и последователей. Я выбрал Twitter для этого примера, потому что он взаимодействует с данными в формате JSON с которыми работать легко и весело.

Давайте же начнем; сам виджет будет построен на базе следующей HTML структуры:

<!DOCTYPE HTML>
<html>
    <head>
        <meta charset="utf-8">
        <title>jQuery, AJAX and Templating</title>
        <link rel="stylesheet" href="/tweetbox.css">
        <!--[if lte IE 8]>
            <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    </head>
        <body>
        <aside id="tweetbox">
            <div id="user">
                <h2><a href="http://twitter.com/danwellman" title="Visit Dan Wellman on Twitter">Dan Wellman</a></h2>
                <a href="http://twitter.com/danwellman" title="Dan Wellman"><img src="/img/me.png" alt="Dan Wellman"></a>
                <p>Husband, father, front-end developer and author. Writes for Nettuts and Packt Publishing. Works for <a href="http://twitter/.com/designhaus" title="Design Haus">@designhaus</a> | jQuery fanatic <img src="http://net.tutsplus.com/wp-includes/images/smilies/icon_biggrin.gif" alt=":D" class="wp-smiley"> </p>
            </div>
            <ul id="tools">
                <li><a href="#tweets" title="Recent Tweets" class="on">Tweets</a></li>
                <li><a href="#friends" title="Recent Friends">Friends</a></li>
                <li><a href="#follows" title="Recent Followers">Followers</a></li>
            </ul>
            <div id="feed">
                <div id="tweets">
                    <noscript>This widget has super-awesome features which require the use of JavaScript. Please enable it for a better internet experience</noscript>
                </div>
                <div id="friends"></div>
                <div id="follows"></div>
            </div>
        </aside>
        <script src="/jquery.js"></script>
        <script src="/jquery.tmpl.min.js"></script>
        <script src="/tweetbox.js"></script>
    </body>
</html>

В этом примере мы используем HTML5. Для этого мы указали упрощенный DOCTYPE и элемент мета. Так же вы можете заметить в коде подключение к таблицам стилей, которые будут описаны через пару минут. В целях поддержки текущей версии IE8 и ниже, используем условные комментарии на специальный плагин html5shiv.

Используем aside

Вероятнее всего этот виджет, будет выглядеть как боковая панель, и отображать содержание указанного пользователя Twitter. Учитывая это, я решил поместить содержимое в тег <aside>. Для того чтобы с лёгкостью получить доступ к этому элементы выставим ему ID.

К слову о разметке. Все заголовки сообщений пользователя Twitter будут включены в тег <h2>, а изображение и всё остальное в теге <p>. Вы можете изменить это на своё собственное предпочтение, когда будете реконструировать данный пример. Мы могли бы получить все необходимые данные через JSON, что мы и сделаем, однако, если в процессе загрузки возникнет задержка, посетителю будет отображено множество пустых блоков. Так что лучше нам дождаться полной загрузки и затем произвести заполнение блоков.

Ещё у нас на странице будут реализованы вкладки для переключения между списками сообщений, друзей и подписчиков. Все они будут заключены в теги <ul>, <li> и <a>. Вкладка со списком сообщений будет отображаться по умолчанию, поэтому нам необходимо указать специальный класс CSS для активной вкладки. В более крупном проекте предпочтительнее использовать jQuery для переключения вкладок интерфейса, но я не хотел концентрировать внимание на этом, т.к. тема урока другая.

Наконец, у нас есть всё что нужно для того, чтобы разместить все входящие данные: внешний контейнер с ID, три вкладки для сообщений, друзей и последователей, которые также имеют свои ID для удобства выборки. Мы также добавили элемент <noscript> для тех посетителей, которые не используют JavaScript при просмотре web-страниц. Обратите внимание, что мы будем использовать плагин tmpl, который даст нам возможность использовать шаблоны jQuery. Этот плагин можно скачать тут.

Чуть ранее я упомянул о специальных таблицах стилей. Откройте новый файл в вашем любимом текстовом редакторе и добавить следующий код:

#tweetbox {
    display:block; width:300px; padding:10px; border:1px solid #aaa; -moz-border-radius:5px;
    border-radius:5px; font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
    background-color:#eee;
}
#tweetbox img { display:block; }
#user { margin-bottom:10px; float:left; }
#user h2 { margin:0 0 10px 0; position:relative; font-size:18px; }
#user img { float:left; }
#user p { width:230px; margin:0; position:relative; float:left; font-size:10px; color:#333; }
#user img { display:block; margin-right:10px; border:3px solid #333; }
#tools { margin:0; *margin-bottom:-10px; padding:0; clear:both; list-style-type:none; }
#tools li {  float:left; }
#tools a {
    display:block; height:20px; padding:3px 24px; border:1px solid #aaa; border-bottom:none;
    -moz-border-radius:5px 5px 0 0; border-radius:5px 5px 0 0; margin-right:-1px;
    position:relative; font-size:14px; outline:none; background-color:#d6d6d6;
    background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0.5, #E8E8E8), color-stop(0, #DBDBDB), color-stop(0.5, #D6D6D6));
    background-image: -moz-linear-gradient(center top, #E8E8E8 50%, #DBDBDB 0%, #D6D6D6 50%);
}
a { text-decoration:none; color:#333; }
#tools .on { height:21px; margin-top:-1px; top:1px; }
#feed { width:298px; border:1px solid #aaa; clear:both; background-color:#d6d6d6; }
#feed > div { display:none; }
noscript { display:block; padding:10px; font-size:13px; color:#333; }

Сохраните этот файл как tweetbox.css в том же каталоге, где находятся ваши HTML страницы. Это лишь малое, что мы можем указать для дизайна нашего виджета. В коде, который мы только что привели, вы можете заметить несколько приёмов CSS3: округлённые углы (обратите внимание, мы больше не нуждаемся в -WebKit- для этих целей!), а так же некоторые градиенты для вкладок. Следует отметить, что мы прячем все блоки, за исключением одного - активного. На данный момент виджет должен выглядеть так:

Добавляем скрипт

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

(function($) {
    //табы
    var tweetbox = $("#tweetbox"),
        tweetData = null,
        friendData = null,
        followData = null;

    tweetbox.find("#tools a").click(function(e) {
        e.preventDefault();

        var link = $(this),
            target = link.attr("href").split("#")[1];

        tweetbox.find(".on").removeClass("on");
        link.addClass("on");
        tweetbox.find("#feed > div").hide();
        tweetbox.find("#" + target).show();
    });
})(jQuery);

Сохраните этот файл (tweetbox.js) в том же каталоге, где и всё остальное. Тут ничего сложного нет. Вкладки не является сутью урока, так что я не буду долго на этом останавливаться. Скрип работает следующим образом: мы используем анонимную функцию, которая отлавливает тот контейнер который является активным. Мы также инициализируем три переменные, которые будем использовать в дальнейшем. Выставляем их значение в null.

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

Получаем данные

Теперь начинается самое интересное. Мы будем делать запрос на Twitter для того, чтобы получить данные для всех 3х вкладок, а так же применим плагин для того, чтобы иметь возможность использовать jQuery шаблоны. Добавьте этот код после предыдущего:

$.ajaxSetup({
    dataType: "jsonp"
});

function getTweets() {
    $.ajax("http://api.twitter.com/statuses/user_timeline/danwellman.json", {
        success: function(data) {
            var arr = [];

            for (var x = 0; x < 5; x++) {
                var dataItem = {};
                dataItem["tweetlink"] = data[x].id_str;
                dataItem["timestamp"] = convertDate(data, x);
                dataItem["text"] = breakTweet(data, x);
                arr.push(dataItem);
            }

            tweetData = arr;
        }
    });
}
function getFriends() {
    return $.ajax("http://api.twitter.com/1/statuses/friends/danwellman.json", {
        dataType: "jsonp",
        success: function(data) {
            var arr = [];

            for (var x = 0; x < 5; x++) {
                var dataItem = {};
                dataItem["screenname"] = data[x].screen_name;
                dataItem["img"] = data[x].profile_image_url;
                dataItem["name"] = data[x].name;
                dataItem["desc"] = data[x].description;
                arr.push(dataItem);
            }

            friendData = arr;
        }
    });
}
function getFollows() {
    return $.ajax("http://api.twitter.com/1/statuses/followers/danwellman.json", {
        dataType: "jsonp",
        success: function(data) {
            var arr = [];

            for (var x = 0; x < 5; x++) {
                var dataItem = {};
                dataItem["screenname"] = data[x].screen_name;
                dataItem["img"] = data[x].profile_image_url;
                dataItem["name"] = data[x].name;
                dataItem["desc"] = data[x].description;
                arr.push(dataItem);
            }

            followData = arr;
        }
    });
}

$.when(getTweets(), getFriends(), getFollows()).then(function(){
    // используем шаблоны
});

Сначала мы используем метод ajaxSetup() для того, чтобы указать формат данных, с которыми мы будем иметь дело – jsonp. Поскольку нам предстоит выполнить несколько запросов, лучше один раз указать данное значение.

Далее мы пишем 3 стандартные по функционалу метода, в которых используем отдельные метод ajax(). Он будет делать запрос на сервис Twitter и возвращать данные. Для запроса мы будем использовать специальные ключевые слова: user_timeline, friends и followers. Чтобы быть уверенными, что данные будут сформированы после удачного запроса, включим наш код в блок success. Каждая из этих функций будет возвращать по 100 хорошо упакованных объектов с Twitter данными.

Для крока нам не нужно такое количество данных, поэтому мы поместим в массив только по 5 объектов. Для того чтобы быть уверенными, что мы формируем JSON данные в правильном формате, ключи каждого элемента помещаем в двойные кавычки.

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

Заметьте, что мы не просто вызываем наши три метода – а используем метод when(), который запустит своё содержание только тогда, когда эти три метода закончат свою работу. После того как все три функции вернут success, мы запустим метод then(), где будет располагаться функциональность, касающаяся шаблонов.

К слову сказать. В данном контексте можно указать и метод fail(), который запустится в том случае, если запросы на Twitter пройдут с ошибкой.

Всё это очень круто, поскольку в ранних версиях jQuery не был предусмотрен подобный функционал.

Вспомогательные функции

В предыдущем примере мы используем некоторые вспомогательные функции convertDate() и breakTweet(). Вот их содержание:

//формат даты 
convertDate = function(obj, i) {

    if (window.ActiveXObject) {
        obj[i].created_at = obj[i].created_at.replace(/[+]\d{4}/, "");
    }

    var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
        date = new Date(obj[i].created_at),
        formattedTimeStampArray = [days[obj[i].created_at], date.toLocaleDateString(), date.toLocaleTimeString()];

    return formattedTimeStampArray.join(" ");
}

breakTweet = function(obj, i) {

    var text = obj[i].text,
        brokenTweet = [],
        atExpr = /(@[\w]+)/;

    if (text.match(atExpr)) {
        var splitTweet = text.split(atExpr);

        for (var x = 0, y = splitTweet.length; x < y; x++) {

            var tmpObj = {};

            if (splitTweet[x].indexOf("@") != -1) {
                tmpObj["Name"] = splitTweet[x];
            } else {
                tmpObj["Text"] = splitTweet[x];
            }

            brokenTweet.push(tmpObj);
        }
    } else {
        var tmpObj = {};
            tmpObj["Text"] = text;
        brokenTweet.push(tmpObj);
    }

    return brokenTweet;
}

Функция convertDate(): в первую очередь проверяем, использует ли браузер window.ActiveXObject. Если да, то мы используем JavaScript метод replace(), чтобы удалить Timezone, которая содержится в JSON объекте, возвращённом от Twitter. Этот метод использует регулярные выражения для того чтобы найти и заменить строку.

Далее мы создаём некоторые переменные; массив, который содержит сокращённые названия месяцев. Дни в датах JavaScript начинаются с 0. Затем мы создаём объект Date, используя конструктор new Date(, и передаём дату, которая хранится в свойстве created_at объекта, переданного в функцию.

Создадим ещё один массив из 3х элементов: первый это день недели, второй – локализованная дата, третий – локализованное время. После формирования массива, мы его возвращаем.

Функция breakTweet() немого сложнее. Тут нам необходимо преобразовать обычный текст в JSON массив, в котором каждый элемент это объект, содержащий свойства Name или Text. Они будут использоваться в шаблоне. Сначала мы получаем текст из объекта, который вернул нам Twitter (передали его в функцию). Так же тут применяем регулярное выражение, которое отлавливает наличие @usernames.

Далее мы сканируем текст, чтобы найти имя пользователя; если оно присутствует, вытаскиваем его. У нас получается массив из текстовых значений. Проходимся по этому массиву, ищем тест содержащий символ @; Если данный символ присутствует, то записываем его с ключом Name. Остальной текст записываем с ключом Text. Сформированные объекты помещаем в массив.

Вот и всё. Мы только что сформировали объект, который можем передать в jQuery шаблон.

Работа с шаблоном

Теперь когда все необходимые данные сформированы, можем приступать к последней части нашего урока: шаблонам. Вернёмся к содержанию блока метода then(). Вставьте код внутри данного блока:

//применяем шаблоны
tweetbox.find("#tweetTemplate").tmpl(tweetData).appendTo("#tweetList");
tweetbox.find("#ffTemplate").tmpl(friendData).appendTo("#friendList");
tweetbox.find("#ffTemplate").tmpl(followData).appendTo("#followList");

//показываем сообщения
tweetbox.find("#tweets").show();

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

Добавляем jQuery шаблоны

Снова вернёмся к HTML. Первое что мы сделаем, добавим тег <script> сразу же после пустого ul с id “tweetList”:

<script id="tweetTemplate" type="text/x-jquery-tmpl">
<li>
    <p>
        {{each text}}
            {{if Name}}
                {{tmpl(Name) "#atTemplate"}}
            {{else}}
                ${Text}
            {{/if}}
        {{/each}}
        <a class="tweet-link" href="http://twitter.com/danwellman/status/${tweetlink}">${timestamp}</a>
    </p>
</li>
</script>
<script id="atTemplate" type="text/x-jquery-tmpl">
<a href="http://twitter.com/${$item.data}">${$item.data}</a>
</script>

jQuery шаблоны добавляются на страницу HTML непосредственно через элемент <script>. У каждого такого элемента должен быть выставлен элемент id для того, чтобы они могли быть распознаны и обработаны методом tmpl(). Так же атрибут type должен хранить следующее значение - text/x-jquery-tmpl.

В первом шаблоне, мы добавляем структуру, которую в последствии хотим выводить в DOM. В частности каждое Twitter сообщение будет заключено в теги <li>, <p> и <а>. Чтобы вставить данные из JSON объекта, переданного через метод tmpl(), мы используем серию шаблонных тегов. Затем используем {{each}} для того, чтобы пройтись по каждому элементу, которое хранится в массиве.

Это массив содержит все Twitter сообщения. Для каждого из них мы делаем проверку на наличие ключа Name. Если ключ присутствует, используем {{tmpl}} тег. Имя функции, через которую будут проходить данные, мы указываем в скобках после tmpl, а также указываем id шаблона, который будем использовать (более детально рассмотрим его через несколько минут). Если объект не содержит ключ Name, то значит мы имеем дело с обычным текстом, который вставим с помощью ${text}. Это условное достигается с помощью тега {{if}} и {{else}}. После этого мы должны закрыть условие, используя {{/if}, и аналогично завершить цикл {{/foreach}}.

Теперь нам необходимо создать ссылку, которая будет вести непосредственно на Twitter. Для этого используем ${tweetlink} как часть атрибута href, и свойство ${timestamp}. Это данные, которые мы создали и успешно обработали по запросу user_timeline.

В atTemplate мы также создаём ссылку, которая будет вести на страницу пользователя, чьи сообщения мы только что вывели. Доступ к информации осуществляем посредством обращения к свойству data тега ${item}.

Таким же образом нам необходимо создать вкладки для отображения наших друзей и подписчиков. Их мы создадим по точно такому же принципу. База для всех одна:

<script id="ffTemplate" type="text/x-jquery-tmpl">
    <li>
        <p>
            <a class="img-link" href="http://twitter.com/${screenname}"><img src="/${img}" alt="${name}"></a>
            <span class="username"><a href="http://twitter.com/${screenname}">${screenname}</a></span>
            <span class="bio">${desc}</span>
        </p>
    </li>
</script>

Вот мы и научились передавать данные в шаблон с помощью json и выводить их при помощи конструкции ${data};

Последний штрих

Теперь, когда почти всё готово, мы можем добавить еще несколько CSS стилей для того, чтобы всё это выглядело более менее прилично. Добавьте следующий код в конец файла tweetbox.css:

#feed ul { padding:0; margin:0; }
#feed li { padding:0; border-bottom:1px solid #aaa; list-style-type:none; font-size:11px; }
#feed li:last-child, #feed li:last-child p { border-bottom:none; }
#feed p { padding:10px; margin:0; border-bottom:1px solid #eee; background-image:-webkit-gradient(linear, left bottom, left top, color-stop(0.48, #c2c2c2), color-stop(0.71, #d6d6d6)); background-image:-moz-linear-gradient(center bottom, #c2c2c2 48%, #d6d6d6 71%); }
#feed p:after { content:""; display:block; width:100%; height:0; clear:both; }
.tweet-link { display:block; margin-top:5px; color:#777; }
.img-link { display:block; margin:4px 10px 0 0; float:left; }
#feed .username a { font-size:14px; font-weight:bold; }
#feed .bio { display:block; margin-top:10px; }

После сохранения файла, наше приложение будет выглядеть следующим образом:

Есть еще одна вещь, которую нам, вероятно, следует реализовать: на данный момент, наше форматирования не работает в IE, поскольку IE не дружит с методом split(). Чтобы устранить эту проблему, мы можем использовать превосходный JavaScript патч, созданный Steven Levithan. Он может быть загружен с: http://blog.stevenlevithan.com/archives/cross-browser-split. Подключим этот код с помощью условного комментария:

<!--[if IE]>
    <script src="/fixSplit.js"></script>
<![endif]-->

Этот код надо добавить непосредственно перед подключением файла tweetbox.js.

Заключение

В этом уроке мы рассмотрели некоторые более продвинутые возможности шаблонов в jQuery. Мы познакомились с итерационным циклом {{each}} и условиями {{if}} и {{else}}.

Ключевым моментом является то, что новая система шаблонов в jQuery позволяет нам разделить наш код, перемещая все HTML фрагменты из файлов JS и обратно в HTML файл.

Некоторые могут возразить, что мы сейчас просто увеличиваем количество тегов <script> на нашей странице.

Однако я думаю, что эта альтернатива более предпочтительна. Элементы в формате $ ("<div>") просто строки (конечно же до того момента как браузер запустится, и они создадутся и вставятся в DOM).

Мы также посмотрели на новый метод when(), добавленный в JQuery 1.5, который позволяет управлять множеством асинхронных запросов. Далее мы использовали метод then(). Данная функция запустит своё содержание только после завершения всех асинхронных процессов.

Надеюсь, статья была для вас полезна. Спасибо за внимание.

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

Читать комменты и комментировать

Добавить комментарий / отзыв



Защитный код
Обновить

Учимся работать с jQuery шаблонами | | 2012-06-29 06:31:38 | | Статьи Web-мастеру | | В этом уроке, мы рассмотрим, как можно использовать jQuery шаблоны для того, чтобы окончательно и бесповоротно отделить наш HTML код от JavaScript скриптов. Так же мы быстро пройдёмся по новой | РэдЛайн, создание сайта, заказать сайт, разработка сайтов, реклама в Интернете, продвижение, маркетинговые исследования, дизайн студия, веб дизайн, раскрутка сайта, создать сайт компании, сделать сайт, создание сайтов, изготовление сайта, обслуживание сайтов, изготовление сайтов, заказать интернет сайт, создать сайт, изготовить сайт, разработка сайта, web студия, создание веб сайта, поддержка сайта, сайт на заказ, сопровождение сайта, дизайн сайта, сайт под ключ, заказ сайта, реклама сайта, хостинг, регистрация доменов, хабаровск, краснодар, москва, комсомольск |
 
Поделиться с друзьями: