Статьи

Как построить виджет для отображения вашего жужжания

Пару месяцев назад Google выпустил новый Twitter-сервис под названием Buzz . Мы можем использовать этот сервис для отображения наших последних новостей на любом сайте. Итак, в этом уроке я проведу вас через процесс создания собственного виджета Buzz.


На данный момент нет API для работы с сервисом Buzz; Ожидается, что Google предоставит его в течение следующих нескольких месяцев, однако на данный момент публичные обновления доступны в виде каналов Atom.

Во-первых, нам нужно получить данные из сервиса Buzz. Для этого мы настроим скрипт PHP, который считывает данные из сервиса Buzz. Этот скрипт будет своего рода прокси, который мы будем использовать для получения данных. Делая это, мы можем сделать запрос AJAX и получить XML-документ, который содержит нужные обновления.

Google Buzz Flow

Вот начальный код PHP:

01
02
03
04
05
06
07
08
09
10
header(‘Content-type: application/xml’);
$handle = fopen($_GET[‘url’], «r»);
 
if ($handle) {
    while (!feof($handle)) {
        $buffer = fgets($handle, 4096);
        echo $buffer;
    }
    fclose($handle);
}

Сохраните этот файл как «readfeed.php» и помните, что это всего лишь пример. В реальном проекте вы должны очистить параметр url и убедиться, что пользователь не открывает что-то важное в вашей файловой системе.


Как только мы сможем прочитать эти данные, нам нужно создать объект, содержащий наш код в JavaScript. Создайте новый файл и назовите его «buzz-widget.js». Чтобы расширить объект, нам нужно использовать свойство «prototype»; если у вас есть вопросы по этому поводу, вы должны посмотреть учебник, в котором Джеффри показывает нам, как это работает с нативными объектами.

Структура нашего объекта будет примерно такой:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var BuzzReader = function(options){ //Step 1
    //code for the constructor
};
 
BuzzReader.prototype = { //Step 2
    renderTo: «»,
    proxy : «readfeed.php»,
    user : «»,
    url : «»,
    items : 10,
    onLoad : function(){},
    onRender: function(){},
     
    render : function(element){
         
    },
     
    read : function(){
         
    },
     
    parse : function(xml,success,response){
 
    },
 
    format : function(date){
 
    },
     
    createDate : function(str){
         
    }
};

На первом этапе мы создали функцию конструктора для нашего объекта. Теперь мы собираемся проверить необходимые конфигурации и прочитать обновления с нашего прокси.

  • renderTo : элемент, в котором будет отображаться виджет; это свойство также может быть селектором jQuery.
  • proxy : URL-адрес, по которому мы сделаем AJAX-запрос для получения наших данных. Мы уже создали файл PHP, который считывает информацию из сервиса Buzz; по умолчанию это «readfeed.php».
  • user : пользователь Buzz, от которого мы хотим получать обновления.
  • items : количество обновлений, которые мы собираемся отобразить в виджете.
  • onLoad : событие, которое мы собираемся вызвать, когда данные загружаются в виджет; по умолчанию это пустая функция.
  • onRender : это событие вызывается, когда виджет собирается отображаться на странице; пустая функция по умолчанию.

Давайте поработаем над функцией конструктора нашего виджета.

01
02
03
04
05
06
07
08
09
10
11
var BuzzReader = function(options){
    var url = «http://buzz.googleapis.com/feeds/{user}/public/posted»;
    jQuery.extend(this,options || {});
     
    if(this.user === «») throw «The ‘user’ property is required»;
    if(this.renderTo === «») throw «The ‘renderTo’ property is required»;
 
    if(this.url === «»)this.url = url.replace(/{user}/g,this.user);
     
    this.read();
};

На первом этапе мы определили URL службы Buzz, из которой мы собираемся получить данные. Мы заменим строку «{user}» пользовательской конфигурацией (см. Шаг 4).

На втором этапе мы переопределили свойства по умолчанию с данными параметрами; мы использовали jQuery.extend для этого.

На третьем шаге мы проверили необходимые конфигурации, одна из которых — «user» и «renderTo». Если один из них отсутствует, мы выдаем исключение. Это будет полезно для разработчика, который использует наш плагин.

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

Последний шаг очень важен. Здесь мы начинаем процесс чтения и отображения информации.


Мы настроили PHP-скрипт, который доставляет данные на наш сервер. Теперь нам нужно только сделать Ajax-запрос для получения данных с помощью jQuery; давайте посмотрим на следующий код:

01
02
03
04
05
06
07
08
09
10
read : function(){
    this.el = jQuery(this.renderTo);
    this.loader = this.el.append(«<div class=\»buzz-loading\»></div>»);
    jQuery.ajax({ //Step 2
        url : this.proxy,
        data : «url=»+this.url,
        context : this,
        success : this.parse
    });
},

На первом этапе мы добавили новый элемент к контейнеру, информируя зрителя о том, что в данный момент мы обрабатываем информацию.

На втором этапе мы сделали запрос Ajax. Самым важным является свойство «context»; эта конфигурация позволит вам изменить контекст функции, которая вызывается при ответе сервера. Наконец, мы устанавливаем контекст «this», который является объектом BuzzReader.

Помните, что скрипт PHP ожидает параметр «url». так что не забудьте отправить его; когда сервер отвечает, выполняется метод «разбора».


Служба Buzz доставляет данные в формате фида Atom, поэтому нам необходимо проанализировать и извлечь необходимую нам информацию.

Это пример документа XML, который возвращается из службы Buzz:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version=»1.0″ encoding=»utf-8″?>
  <feed xmlns=»http://www.w3.org/2005/Atom»
        xmlns:thr=»http://purl.org/syndication/thread/1.0″
        xmlns:media=»http://search.yahoo.com/mrss»
        xmlns:activity=»http://activitystrea.ms/spec/1.0/»>
    <link rel=»self»
          type=»application/atom+xml»
          href=»http://buzz.googleapis.com/feeds/117377434815709898403/public/posted»/>
    <link rel=»hub» href=»http://pubsubhubbub.appspot.com/»/>
    <title type=»text»>Google Buzz</title>
    <updated>2009-12-14T20:04:39.977Z</updated>
    <id>tag:google.com,2009:buzz-feed/public/posted/117377434815709898403</id>
    <generator>Google — Google Buzz</generator>
    <entry>
      <title type=»html»>Buzz by A. Googler from Mobile</title>
      <published>2009-12-14T20:04:39.000Z</published>
      <updated>2009-12-14T20:04:39.977Z</updated>
      <id>tag:google.com,2009:buzz/z12bx5v5hljywtfug23wtrrpklnhf3gd3</id>
      <link rel=»alternate»
            type=»text/html»
            href=»http://www.google.com/buzz/117377434815709898403/DmuNZHSfZ7t/buzz-buzz»/>
      <author>
        <name>A.
        <uri>http://www.google.com/profiles/a.googler</uri>
      </author>
      <content type=»html»>Bzz!
      <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
      <activity:object>
        <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
        <id>webupdates:[email protected]</id>
        <title>Buzz by A. Googler from Mobile</title>
        <content type=»html»>Bzz!
      </activity:object>
      <link rel=»replies»
            type=»application/atom+xml»
            href=»http://buzz.googleapis.com/feeds/117377434815709898403/comments/z12bx5v5hljywtfug23wtrrpklnhf3gd3″
            thr:count=»0″/>
      <thr:total>0</thr:total>
    </entry>
  </feed>

Как только мы узнаем ответ, мы можем легко проанализировать документ с помощью jQuery.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
parse : function(xml,status){
    var that = this;
    var nodes = jQuery(«entry»,xml);
    this.el.empty();
    var info = [];
    nodes.each(function(){ //Step 2
        var date = that.createDate(jQuery(«published»,this).text());
        info.push({
            title : jQuery(«title»,this).text(),
            author : jQuery(«author > name»,this).text(),
            uri : jQuery(«author > uri»,this).text(),
            summary : jQuery(«summary «).text(),
            content : jQuery(«content:first»,this).text(),
            published : that.format(date),
            updated : jQuery(«updated»,this).text(),
            date : date,
            reply : jQuery(«link[rel=replies]»,this).attr(«href»)
        });
    });
    this.data = info;
    this.onLoad.call(this,info);
    this.render(this.renderTo);
},

Мы получили два аргумента: первый — данные, в данном случае документ XML; Второй аргумент — это текстовый статус запроса.

На первом этапе мы получили все «входные» узлы; это место, где находятся обновления Buzz и вся необходимая информация. Затем мы освободили контейнер нашего виджета и создали пустой массив для хранения наших данных в виде объекта JavaScript для каждого узла.

На втором шаге мы перебрали узлы «entry» и извлекли «title», «author», «content» и так далее. Это действительно простой процесс; все, что нам нужно сделать, это написать селектор и установить корень для поиска, в этом случае корень — это узел «запись».

Я хотел бы указать на строку, где мы извлекаем атрибут «reply» — селектор выглядит примерно так:

1
link[rel=replies]

Мы указали, что мы хотим, чтобы узел «ссылка» имел атрибут «rel», равный «ответам». Это важно, потому что в каждой «записи» есть много узлов связи.

На третьем шаге мы создали ссылку «this.data» на массив, содержащий наши данные. После этого мы выполнили событие «onLoad» и передали извлеченную информацию.

На четвертом шаге мы выполнили метод рендеринга.

Прежде чем мы продолжим с методом «render», давайте рассмотрим методы «createData» и «format». Мы вызываем эти методы для каждой записи.

В методе «createDate» мы только собираемся создать новый объект Date с заданной строкой. Строка имеет формат «2009-12-14T20: 04: 39.977Z», поэтому мы можем создать объект Date следующим образом:

01
02
03
04
05
06
07
08
09
10
createDate : function(str){
    var date = new Date();
    date.setDate(str.substring(8,10));
    date.setMonth(str.substring(5,7) — 1);
    date.setFullYear(str.substring(0,4));
    date.setUTCHours(str.substring(11,13));
    date.setUTCMinutes(str.substring(14,16));
    date.setUTCSeconds(str.substring(17,19));
    return date;
}

Или мы можем использовать простое регулярное выражение для форматирования строки и передачи ее конструктору Date:

1
2
3
4
5
6
createDate : function(str){
    //str = ‘2009-12-14T20:04:39.977Z’
    str = str.substring(0,19).replace(/[ZT]/,» «).replace(/\-/g,»/»);
    //str = ‘2009/12/14 20:04:39’
    return new Date(str);
}

В методе форматирования мы собираемся использовать только что созданный объект даты и возвращать время между датой публикации и системным локальным временем — например, «11 минут назад» или «3 часа назад».

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
format : function(date){
    var diff = (((new Date()).getTime() — date.getTime()) / 1000),
        days = Math.floor(diff / 86400),
        months = Math.floor(days / 31);
 
    if (isNaN(days) || days < 0)return date.toString();
     
    if(days == 0){
        if(diff < 60)return «Just now»;
        if(diff < 120)return «1 minute ago»;
        if(diff < 3600)return Math.floor( diff / 60 ) + » minutes ago»;
        if(diff < 7200)return «1 hour ago»;
        if(diff < 86400)return Math.floor( diff / 3600 ) + » hours ago»;
    }else if(days < 31){
        if(days == 1)return «Yesterday»;
        if(days < 7)return days + » days ago»;
        if(days < 31)return Math.ceil( days / 7 ) + » weeks ago»;
    }else{
        if(months == 1)return «A month ago»;
        if(months < 12)return Math.ceil( days / 31 ) + » months ago»;
        if(months >=12)return Math.floor( days / 365 ) + » years ago»;
    }
},

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

Теперь давайте рассмотрим метод render.


До сих пор мы только извлекали данные с сервера Buzz и анализировали XML-документ. Это означает, что мы готовы вывести информацию на экран.

01
02
03
04
05
06
07
08
09
10
11
12
13
render : function(element){
    this.onRender.call(this,this);
     
    var html = [];
    html.push(«<ul>»);
     
    for(var i = 0; i < this.items || i < this.data.lenght;i++){
        html.push(«<li><strong><a href=\»»+this.data[i].uri+»\»>»+this.data[i].author+»</a></strong><span>»+this.data[i].published+»
    }
    html.push(«</ul>»);
     
    this.el.append(html.join(«»));
},

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

На втором этапе мы создали массив для хранения нашего динамического HTML. После этого мы создали список «ul», а затем перебрали наши данные, создав узел «li» для каждого элемента; вы, вероятно, заметили, что условие «for» имеет оператор «или»; это позволяет нам останавливать итерации, когда заканчивается массив данных или когда индекс «i» достиг свойства «items», определенного разработчиком, который собирается использовать плагин.

На последнем шаге мы вставили HTML-код в контейнер с помощью метода append.


Чтобы использовать наш виджет, нам нужно создать экземпляр нашего класса «BuzzReader», но перед этим давайте определим, где мы хотим его визуализировать. Создайте HTML-файл и в элементе body добавьте следующее:

1
2
3
4
5
<div id=»buzz»>
<div>
    <div class=»reader»></div>
</div>
</div>

Мы собираемся визуализировать наш виджет внутри div с помощью класса «reader», давайте создадим экземпляр нашего виджета следующим образом:

1
2
3
4
5
6
7
8
$(function(){
 
    new BuzzReader({
        renderTo : «#buzz .reader»,
        user : «nettutsblog»,
        items : 3
    });
});

Не забудьте импортировать библиотеку jQuery и «buzz-widget.js» в ваш HTML-файл. Если все было настроено и закодировано правильно, вы должны увидеть нечто похожее на следующее изображение:

Google Buzz виджет

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
/* step 1 */
body{font-family:»Trebuchet MS»,Arial,sans-serif;line-height:24px;font-size:14px;}
 
/*Step 2*/
#buzz{width:300px;margin:100px auto;border:1px solid #AFAFAF;}
#buzz > div{background-color:#E4E4E4;border:1px solid #F6F6F6;padding:10px;}
#buzz .reader{height:350px;overflow:auto;border:1px solid #F6F6F6;padding:80px 10px 10px 10px;background:#fff url(title.jpg) center 0 no-repeat;}
/* Step 3 */
#buzz ul{margin:0;padding:0;}
#buzz ul li{list-style-type:none;color:#A3A3A3;border-bottom:1px solid #E4E4E4;margin-bottom:5px;padding-bottom:5px;}
#buzz ul li div{color:#777;}
#buzz ul li a{color:#444;text-decoration:none;font-weight:normal;}
#buzz ul li a:hover{text-decoration:underline;}
#buzz ul li span{float:right;}
 
/* Step 4*/
#buzz .buzz-loading{position:absolute;margin-left:240px;width:16px;height:16px;background:transparent url(ajax-loader.gif) center center no-repeat;}

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

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

В результате мы получили гораздо более привлекательный продукт.

Google Buzz виджет

Последний шаг в этом уроке — создать плагин jQuery. Давайте изменим файл «buzz-widget.js», добавив следующий код в конец файла.

1
2
3
4
5
6
7
jQuery.fn.buzzReader = function(options){ //Step 1
    return this.each(function(){
        var opts = options ||
        opts.renderTo = this;
        new BuzzReader(opts);
    });
};

На первом этапе мы просто назвали наш плагин.

На втором шаге мы создали объект конфигурации, если аргумент «options» пуст. Далее мы определили свойство renderTo для фактического элемента.

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

Теперь мы можем использовать наш плагин в нашем HTML, например так:

1
2
3
4
5
6
$(function(){
    $(«#buzz .reader»).buzzReader({
        user : «nettutsblog»,
        items : 3
    });
});
Google Buzz виджет

Я надеюсь, что вы немного узнали о том, как извлекать данные из документов XML и отображать ваши последние обновления на любом веб-сайте. Любые вопросы? Спасибо за прочтение!