Создание виджета для чтения RSS каналов

Вы будете очень удивлены, узнав какое количество информации доступно в Интернете через RSS и ATOM каналы - поиск в твиттере, напоминания гугл, собственные и другие блоги и многое другое. Вам просто необходимо найти оранжевую иконку и Вы точно найдете массу полезной информации, которая так и ждет, чтобы быть задействованной.

Сегодня мы займемся созданием красивого виджета для чтения подобных лент. Он будет извлекать любую ленту и отображать ее в любом месте сайта. Вы можете настроить его таким образом, чтобы он отображал последние сообщения с разных категорий блога, или упоминания о Вас в твиттере, или все что угодно :).

Решение проблем

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

Проблема 1 - чтение лент

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

И тут нам поможет YQL. Этот сервис читает ленту и делает ее доступной нашему скрипту в качестве JSON объекта, который мы можем вывести на странице.

YQL - бесплатный API сервис от Yahoo, с помощью которого Вы можете делать намного больше, чем просто читать ленты. Он служит шлюзом между Вашим и любым другим АПИ и позволяет Вам манипулировать ими с помощью легкого синтаксиса по типу SQL. Больше информации можно найти тут.

Настройка YQL требует небольших усилий, однако (нам необходимо динамически включить тег <script> в шапку сайта). К счастью, jQuery способен на это - есть метод под названием getJSON.

Проблема 2 - Разные форматы лент

Существуют разные форматы лент - RSS1, RSS2 и ATOM. Они отличаются друг от друга. Наш код должен уметь считывать результаты, которые выдает YQL и выводить их на страницу.

Эту проблему мы решим с помощью отдельной функции с несколькими логическими или\или ( || ) в нашем коде.

Проблема 3 - Недостаточно места

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


Приступим к созданию...

Шаг 1 - XHTML

Первая часть урока содержит базовую разметку.

demo.html
<div id="feedWidget">
<div id="activeTab">
<!-- Название -->
</div>
<div class="line"></div>
<div id="tabContent">
<!-- Содержимое -->
</div>
</div>

Поскольку все в нашем виджете зависит от JavaScript его нет смысла показывать, при отключенном в браузере JS. И поэтому feedWidget спрятан с помощью display:none в стилях. А показывается он с помощью метода jQuery show().

Шаг 2 - CSS

styles.css - часть 1
#feedWidget{
	background:url(img/bg.png) repeat-x #47525c;
	border:2px solid #48535e;
	margin:0 auto;
	width:200px;
	padding:5px;
	position:relative;

	/* при выключенном JS ничего не отображается: */
	display:none;
	z-index:20;
}

#activeTab.hover,.dropDownList{
	background:url(img/drop_arrow.png) no-repeat 95% 50% #47525c;
	border:1px solid #38434d;

	margin:-1px;

	cursor:pointer;

	/* CSS3 скругленные углы: */
	-moz-border-radius:5px;
	-webkit-border-radius:5px;
	border-radius:5px;

}

#activeTab,.dropDownList div{
	color:white;
	cursor:pointer;
	font-size:20px;
	margin:0 2px 0 0;
	padding:5px;

	text-shadow:0 1px 1px black;
}

.line{
	height:1px;
	overflow:hidden;
	background-color:#2b353d;
	border-bottom:1px solid #687581;
	margin:10px 0;
}

Обратите внимание на то, что мы определяем специальный класс при наведении на слой #activeTab, вместо обычного :hover псевдокласса. Это сделано потому, что стиль при наведении должен быть применен только в случае наличия нескольких источников лент, что невозможно определить используя CSS. Это будет сделано с помощью JS.

styles.css - часть 2
.dropDownList{
	background-image:none;
	position:absolute;

	border-top:none;
	padding:5px;

	-moz-border-radius-topleft: 0;
	-moz-border-radius-topright: 0;
	-webkit-border-top-left-radius: 0;
	-webkit-border-top-right-radius: 0;
	border-top-left-radius: 0;
	border-top-right-radius: 0;
}

.dropDownList div:hover{
	background-color:#505e6b;
}

#tabContent div{
	/* тут будут сообщения с ленты */

	background-color:#EEEEEE;
	color:#555555;
	font-size:10px;
	margin-bottom:10px;
	padding:5px;
	position:relative;

	-moz-border-radius:5px;
	-webkit-border-radius:5px;
	border-radius:5px;

	/* CSS3 тень ячейки: */
	-moz-box-shadow:0 1px 1px black;
	-webkit-box-shadow:0 1px 1px black;
	box-shadow:0 1px 1px black;
}

Тут мы оформляем внешний вид зоны, в которой будут выводиться сообщения.

Шаг 3- jQuery

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

script.js - часть 1
/* Настройки: */

var tabs = {
	"@tutorialzine" : {
		"feed"		: "http://twitter.com/statuses/user_timeline/67315866.rss",
		"function"	: twitter
	},

	"Latest Tutorials": {
		"feed"		: "http://feeds.feedburner.com/Tutorialzine",
		"function"	: rss
	},

	"Smashing Mag": {
		"feed"		: "http://rss1.smashingmagazine.com/feed/",
		"function"	: rss
	},

	"Script & Style" : {
		"feed"		: "http://feeds2.feedburner.com/ScriptAndStyle",
		"function"	: rss
	}
}

$(document).ready(function(){

	/* Считаем количество источников: */
	var totalTabs=0;
	$.each(tabs,function(){totalTabs++;})

	$('#feedWidget').show().mouseleave(function(){

		/* Если курсор покинул виджет, спрятать выпадающий список: */
		$('.dropDownList').remove();
		$('#activeTab').removeClass('hover');

	}).mouseenter(function(){

		if(totalTabs>1) $('#activeTab').addClass('hover');

	});

	$('#activeTab').click(showDropDown);

	/* используем метод LIVe */

	$('.dropDownList div').live('click',function(){

 		/* Calling the showDropDown function, when the drop down is already shown, will hide it: */
		showDropDown();
		showTab($(this).text());
	});

	/* показываем один из источников после загрузки страницы: */

	showTab('@tutorialzine');
});

Объект tabs содержит записи о разных источниках, которые мы будем использовать вместе с функцией, которая будет выводить ленты на страницу. В конце мы выводим один источник (в скобках функции showTab) для отображения сразу после загрузки страницы.

script.js - часть 2
function showTab(key)
{
	var obj = tabs[key];
	if(!obj) return false;

	var stage = $('#tabContent');

	/* формируем query: */
	var query = "select * from feed where url='"+obj.feed+"' LIMIT 5";

	/* Формируем URL lkz YQL: */
	var url = "http://query.yahooapis.com/v1/public/yql?q="+encodeURIComponent(query)+"&format=json&callback=?";

	$.getJSON(url,function(data){

		stage.empty();

		/* элемент существует в RSS и ATOM лентах: */

		$.each(data.query.results.item || data.query.results.entry,function(){

			try{
				/* Пробуем вызвать функцию юзера, "this" остаток информации ленты: */
				stage.append(obj['function'](this));

			}
			catch(e){
				/* Информируем о возможных ошибках: */
				var f_name =obj['function'].toString().match(/function\s+(\w+)\(/i);
				if(f_name) f_name = f_name[1];

				stage.append('<div>There is a problem with your '+f_name+ ' function</div>');
				return false;
			}
		})

	});

	$('#activeTab').text(key);
}

function showDropDown()
{
	if(totalTabs<2) return false;

	if($('#feedWidget .dropDownList').length)
	{
	/* Если выпадающий список уже показан, спрятать его: */

	$('.dropDownList').slideUp('fast',function(){ $(this).remove(); })

	return false;

	}

	var activeTab = $('#activeTab');

	var offsetTop = (activeTab.offset().top - $('#feedWidget').offset().top )+activeTab.outerHeight() - 5;

	/* Создание выпадающего слоя на лету: */

	var dropDown = $('<div>').addClass('dropDownList').css({

		'top'	: offsetTop,
		'width'	: activeTab.width()

	}).hide().appendTo('#feedWidget')

	$.each(tabs,function(j){

		if(j==activeTab.text()) return true;

		$('<div>').text(j).appendTo(dropDown);
	})

	dropDown.slideDown('fast');

}

Функция showTab берет название вкладки в качестве параметра и показывает ее в виджете, после формирования YQL URL, и чтения его с помощью метода getJSON. После этого, ответ проходит цикл с помощью $.each и вызывается функция.

script.js - часть 3
function twitter(item)
{
	/* Форматируем твиты, превращая хештеги, упоминания в ссылках URLS в правильные гиперлинки: */

	return $('<div>').html(
		formatString(item.description || item.title)+
		' <a href="'+(item.link || item.origLink)+'" target="_blank">[tweet]</a>'
	);
}

function rss(item)
{
	return $('<div>').html(
		formatString(item.title.content || item.title)+
		' <a href="'+(item.origLink || item.link[0].href || item.link)+'" target="_blank">[read]</a>'
	);
}

function formatString(str)
{

	str = str.replace(/<[^>]+>/ig,'');
	str=' '+str;
	str = str.replace(/((ftp|https?):\/\/([-\w\.]+)+(:\d+)?(\/([\w/_\.]*(\?\S+)?)?)?)/gm,'<a href="$1" target="_blank">$1</a>');
	str = str.replace(/([^\w])\@([\w\-]+)/gm,'$1@<a href="http://twitter.com/$2" target="_blank">$2</a>');
	str = str.replace(/([^\w])\#([\w\-]+)/gm,'$1<a href="http://twitter.com/search?q=%23$2" target="_blank">#$2</a>');
	return str;
}

В последней части у нас 2 функции - twitter и rss. Они берут объект (переданный из $.each d showTab()) и находят путь к ссылке и названию элемента ленты.

Вот и все готово! Пользуйтесь! :)
Добавлено: 22 Августа 2013 01:33:45 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...