<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tutorialzine &#187; Search Results  &#187;  YQL</title>
	<atom:link href="http://tutorialzine.com/search/YQL/feed/rss2/" rel="self" type="application/rss+xml" />
	<link>http://tutorialzine.com</link>
	<description>Web Development Tutorials &#38; Resources</description>
	<lastBuildDate>Mon, 06 Feb 2012 08:49:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Making a Flickr-powered Slideshow</title>
		<link>http://tutorialzine.com/2011/02/flickr-api-slideshow-jquery/</link>
		<comments>http://tutorialzine.com/2011/02/flickr-api-slideshow-jquery/#comments</comments>
		<pubDate>Mon, 21 Feb 2011 13:28:24 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1377</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2011/02/flickr-api-slideshow-jquery/"><img src="http://cdn.tutorialzine.com/img/featured/1377.jpg" /></a></div> In this tutorial we will be developing a jQuery plugin that will make it possible to create slideshows, product guides or presentations from your Flickr photo sets.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2011/02/flickr-api-slideshow-jquery/"><img src="http://cdn.tutorialzine.com/img/featured/1377.jpg" /></a></div> <p>Today we will be developing a jQuery plugin that will make it easy to create slideshows, product guides or presentations from your Flickr photo sets. The plugin will be using Flickr&#8217;s APIs and YQL to fetch the photos in the sets, after which it will create the markup of the slideshow and listen for events.</p>
<blockquote class="note"><p><strong>Updated on Oct <strong>11th </strong>2011:</strong> Due to a change in Flickr&#8217;s API, you are now required to provide an API key when requesting the photos in a set. The script and this tutorial were updated to reflect this change. If you have downloaded this script before, replace jqFlick.js and script.js. You will also need to generate a Flickr API key (as explained in the tutorial) and paste it in script.js.</p></blockquote>
<h3>The HTML</h3>
<p>Before starting with <strong><em>jqFlick</em></strong> (the name of our plugin), lest first lay down the HTML structure of the underlying document. I am including the plugin&#8217;s CSS stylesheet &#8211; <em><strong>jqFlick.css</strong></em>, which we will be creating in the next step, and the plugin&#8217;s js file &#8211; <em><strong>jqFlick.js</strong></em>.</p>
<h4>index.html</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
&lt;title&gt;jqFlick - Flickr Micro Slider Plugin | Tutorialzine Demo&lt;/title&gt;

&lt;link rel="stylesheet" type="text/css" href="assets/css/styles.css" /&gt;
&lt;link rel="stylesheet" type="text/css" href="assets/jqFlick/jqFlick.css" /&gt;

&lt;/head&gt;
&lt;body&gt;

&lt;div id="page"&gt;

	&lt;h1&gt;Flickr Powered Micro Slider&lt;/h1&gt;

	&lt;div id="flickrSlider"&gt;&lt;/div&gt;

	&lt;p class="demos"&gt;More demos: &lt;select&gt;
    	&lt;option value="1" selected&gt;Presentation Example&lt;/option&gt;
        &lt;option value="2"&gt;Photo Slideshow&lt;/option&gt;
        &lt;option value="3"&gt;Product Shots (small)&lt;/option&gt;
    &lt;/select&gt;&lt;/p&gt;

&lt;/div&gt;

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="assets/jqFlick/jqFlick.js"&gt;&lt;/script&gt;
&lt;script src="assets/js/script.js"&gt;&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Additionally, we have <em>styles.css</em>, which styles the page itself, and script.js, which calls the plugin. Also, we have a select element with demos of three different configurations of the plugin. We will come back to this in a moment.</p>
<p>The other important element in the fragment above is the <em><strong>#flickrSlider</strong></em> div, which is going to be populated with the slider&#8217;s HTML by the <em>jqFlick</em> plugin:</p>
<h4>Generated Code</h4>
<pre class="brush:html">&lt;div id="flickrSlider" class="flickrSliderHolder" style="width: 500px; height: 345px;"&gt;
	&lt;span class="caption"&gt;&lt;/span&gt;
	&lt;ul style="width: 1000px; height: 320px; left: 0px;"&gt;
		&lt;li style="background-image: url('example.jpg'); width: 500px;"&gt;&lt;/li&gt;
		&lt;li style="background-image: url('example2.jpg'); width: 500px;"&gt;&lt;/li&gt;
	&lt;/ul&gt;
	&lt;div class="arrows"&gt;
		&lt;a class="previous" href="#"&gt;&lt;/a&gt;
		&lt;a class="next" href="#"&gt;&lt;/a&gt;
	&lt;/div&gt;
&lt;/div&gt;</pre>
<p>The <strong><em>#flickrSlider</em></strong> div is assigned a class name &#8211; <em>.flickrSliderHolder</em>, a width and a height. Inside it we have an unordered list with the slides, an arrow div holder with previous and next arrows, and a span for the captions. The unordered list is set to be wide enough to accommodate the LIs side by side. The slide animation is achieved by animating the left property of the UL.</p>
<div id="attachment_1381" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/02/flickr-api-slideshow-jquery/"><img class="size-full wp-image-1381" title="Flickr Slideshow jQuery Plugin" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/02/flickr-slideshow-gallery-jquery-plugin.jpg" alt="Flickr Slideshow jQuery Plugin" width="620" height="460" /></a><p class="wp-caption-text">Flickr Slideshow jQuery Plugin</p></div>
<h3>The CSS</h3>
<p>We need to provide the plugin with its own stylesheet, so it is easier to include into a website. This stylesheet must only affect the markup generated by the plugin, and we have to make sure it does not corrupt any other elements on the page. To achieve this, we are going to prefix the styles with the <em>.flickrSliderHolder</em> class name, assigned to the slideshow holder by the plugin.</p>
<h4>jqFlick.css</h4>
<pre class="brush:css">.flickrSliderHolder{
	position:relative;
	overflow:hidden;
}

.flickrSliderHolder ul{
	position:absolute;
	height:100%;
	list-style:none;
}

.flickrSliderHolder ul li{
	float:left;
	height:100%;
	background-repeat:no-repeat;
	background-position:center center;
}

.flickrSliderHolder .arrows{
	position:absolute;
	right:0;
	bottom:0;
}

.flickrSliderHolder .arrows a{
	width:22px;
	height:22px;
	float:left;
	background:url('arrows.png') no-repeat top left;
	text-decoration:none;
	outline:none;
	border:none;
}

.flickrSliderHolder a.previous:hover{
	background-position:left bottom;
}

.flickrSliderHolder a.next{
	margin-left:-1px;
	background-position:top right;
}

.flickrSliderHolder a.next:hover{
	background-position:bottom right;
}

.flickrSliderHolder .caption{
	font-size:13px;
	line-height: 22px;
	position:absolute;
	bottom:0;
	left:0;
}</pre>
<p>Once called, <em>jqFlick</em> assigns the <em>.flickrSliderHolder</em> class to the slider holder div, and generates the markup that we saw in the previous step. The code above styles the arrows, caption, unordered list and the container.</p>
<div id="attachment_1382" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2011/02/flickr-api-slideshow-jquery/"><img class="size-full wp-image-1382" title="Perfect for Slideshows, Product Guides and Presentations" src="http://cdn.tutorialzine.com/wp-content/uploads/2011/02/perfect-slideshows-product-guides-presentations.jpg" alt="Perfect for Slideshows, Product Guides and Presentations" width="620" height="260" /></a><p class="wp-caption-text">Perfect for Slideshows, Product Guides and Presentations</p></div>
<h3>The jQuery Code</h3>
<p>Starting with the jQuery section, lets first see what a response from the Flickr API looks like:</p>
<h4>Sample YQL Response</h4>
<pre class="brush:js">{
    "query": {
        "count": 3,
        "created": "2011-02-19T20:11:18Z",
        "lang": "en-US",
        "results": {
            "photo": [{
                "farm": "6",
                "id": "5456788328",
                "isprimary": "1",
                "secret": "e9eddccf8e",
                "server": "5213",
                "title": "The title of the image becomes an optional caption."
            }, {
                "farm": "6",
                "id": "5456179165",
                "isprimary": "0",
                "secret": "28bae85307",
                "server": "5216",
                "title": "There are no limits really."
            }, {
                "farm": "6",
                "id": "5456179233",
                "isprimary": "0",
                "secret": "e05287691f",
                "server": "5018",
                "title": "What more do you need.."
            }]
        }
    }
}</pre>
<p>Here I&#8217;ve selected the photos that are contained in <a href="http://www.flickr.com/photos/59645888@N08/sets/72157625956932639/" target="_blank">this photoset</a>. The response contains useful information about the images. We are going to use the farm, id, secret, and server properties of these objects to put together the URL at which the photos are located, while the title properties are going to be used as captions.</p>
<p>You can find your photos at the following address, by replacing the keywords with the objects&#8217; values:</p>
<pre class="brush:plain">http://farm{FARM}.static.flickr.com/{SERVER}/{ID}_{SECRET}.jpg</pre>
<p>In our plugin, we will be using Flickr&#8217;s API method for <a href="http://www.flickr.com/services/api/flickr.photosets.getPhotos.htm" target="_blank">listing photos in a photoset</a>. However, to communicate with Flickr&#8217;s APIs, we will need to register for an API key.</p>
<h4>API key registration</h4>
<p>This step is actually quite simple. You need to have a valid Flickr registration and visit <a href="http://www.flickr.com/services/apps/create/" target="_blank">this page</a>. After you choose the type of the registration (non commercial in our case), you fill in the application details. You now get your API key, which you will need in a second.</p>
<blockquote class="note"><p>For more info on the various Flickr APIs you can go to their <a href="http://www.flickr.com/services/api/" target="_blank">documentation page</a>. If you would like to know more about the URL addresses of their photos (including info on how to fetch different image sizes) see <a href="http://www.flickr.com/services/api/misc.urls.html" target="_blank">here</a>. You can also read more about YQL in our previous <a href="../?s=YQL">YQL tutorials.</a></p></blockquote>
<p>Now we are ready to write the jQuery code. As you know, encapsulating jQuery functionality in a plugin has many benefits, as you can read from our <a href="http://tutorialzine.com/2011/02/converting-jquery-code-plugin/">jQuery plugin tutorial</a>. Lets see what jqFlick.js, the main plugin file, looks like:</p>
<h4>jqFlick.js</h4>
<pre class="brush:js">(function($){

	$.fn.jqFlick = function(options){

		// Default options:

		options = $.extend({
			width:500,
			height:500,
			maxFetch:50,
			captions:false,
			autoAdvance:false,
			advancePeriod:5000,
			apiKey:''
		},options);

		// Using YQL and the flickr.photosets.photos table to query the Flickr API.

		var YQL = 'http://query.yahooapis.com/v1/public/yql?q={QUERY}&amp;format=json&amp;callback=?',
			query = "SELECT * FROM flickr.photosets.photos({MAX}) WHERE photoset_id='{PHOTOSET}'"+
				" AND api_key='{KEY}'";

		// Replacing the "{EXAMPLE}" keywords from the strings:

		YQL = templateReplace(YQL,{
			"query": encodeURIComponent(
				templateReplace(query,{
					photoset : options.photosetID,
					max	: options.maxFetch,
					key	: options.apiKey
				}
			))
		});

		// Template for building Flickr's image URLs:

		var flickrSRC = 'http://farm{FARM}.static.flickr.com/{SERVER}/{ID}_{SECRET}.jpg',
			flickrSlider = this;

		flickrSlider.trigger('jqFlickRemove');

		// Fetching the images using Flickr's API:

		$.getJSON(YQL,function(r){
			if(!r || !r.query || !r.query.count){
				throw "There is no such photoset!";
			}

			var currentPos = 1,
				cnt = r.query.count;

			var caption = $('&lt;span&gt;',{
				className: 'caption'
			}).appendTo(flickrSlider);

			var ul = $('&lt;ul&gt;',{
				css:{
					width: options.width*r.query.count,
					height:options.height
				}
			});

			// Looping through the photo results:

			$.each(r.query.results.photo,function(){
				data = this;

				// Creating a new LI element with the photo as its
				// centered background image:

				$('&lt;li&gt;',{
					css : {
						backgroundImage: 'url('+templateReplace(flickrSRC,data)+')',
						width: options.width
					}
				}).appendTo(ul);
			});

			flickrSlider.addClass('flickrSliderHolder')
						.width(options.width)
						.height(options.height+25)
						.append(ul);

			// Binding a custom "slide" event.
			// You can then flickrSlider.trigger("slide",2)
			// to go to the second slide:

			flickrSlider.bind('slide',function(e,slide){
				if(slide &lt; 1 || slide &gt; cnt || ul.is(':animated')){
					return false;
				}

				ul.animate({
					left:-(slide-1)*options.width
				},{
					easing: 'easeInOutCirc',
					duration: 300
				});

				if(options.captions){

					// Animating the transition between
					// the captions (if enabled):

					caption.fadeOut(150,function(){
						caption.html(r.query.results.photo[slide-1].title);
					}).fadeIn(150);
				}

				currentPos = slide;
			});

			var arrows = $('&lt;div&gt;',{
				className: 'arrows'
			});

			// Creating the previous / next arrows, and
			// binding event listeners for the click events:

			var arrowPrev = $('&lt;a&gt;',{
				className: 'previous',
				href: '#',
				click : function(){
					var toShow = currentPos - 1;
					if(toShow &lt; 1){
						toShow = cnt;
					}

					flickrSlider.trigger('slide',[toShow]);
					return false;
				}
			}).appendTo(arrows);

			var arrowNext = $('&lt;a&gt;',{
				className: 'next',
				href: '#',
				click : function(){
					var toShow = currentPos + 1;
					if(toShow &gt; cnt){
						toShow = 1;
					}

					flickrSlider.trigger('slide',[toShow]);
					return false;
				}
			}).appendTo(arrows);

			arrows.appendTo(flickrSlider);

			// Showing the first slide by default:

			flickrSlider.trigger('slide',[1]);

			if(options.autoAdvance){

				// If auto advance is enabled, listen for
				// the load event and schedule a periodic slide change.
				//
				// Read more here:
				// http://tutorialzine.com/2011/01/how-to-make-auto-advancing-slideshows/

				$(window).load(function(){

					$.fn.jqFlick.timeOut = null;

					arrowPrev.add(arrowNext).click(function(e,simulated){
						if(!simulated){
							clearTimeout($.fn.jqFlick.timeOut);
						}
					});

					(function autoAdvance(){
						if($.fn.jqFlick.timeOut){
							arrowNext.trigger('click',[true]);
						}
						$.fn.jqFlick.timeOut = setTimeout(autoAdvance,options.advancePeriod);
					})();
				});
			}
		});

		// This custom event removes all event listeners,
		// and empties the slider holder:

		flickrSlider.bind('jqFlickRemove',function(){
			if($.fn.jqFlick.timeOut){
				clearTimeout($.fn.jqFlick.timeOut);
			}

			flickrSlider.empty().unbind('jqFlickRemove slide');

		});

		return flickrSlider;

	};

	// Helper function for replacing "{KEYWORD}" with
	// the respectful values of an object:

	function templateReplace(template,data){
		return template.replace(/{([^}]+)}/g,function(match,group){
			return data[group.toLowerCase()];
		});
	}

	// A custom easing functon. For more info visit:
	// http://gsgd.co.uk/sandbox/jquery/easing/

	$.easing.easeInOutCirc = function (x, t, b, c, d) {
		if ((t/=d/2) &lt; 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	};

})(jQuery);</pre>
<p><em>jqFlick</em> takes an options object as its only parameter. You are required to specify the id of the photoset (the <em>photosetID </em>property), which you can easily copy from the address bar of your web browser while viewing the photoset. Only public photosets can be shown by the <em>jqFlick</em>.</p>
<p>Now lets see how the plugin is called. At the top of this file, you will need to paste your Flickr API key that we generated above:</p>
<h4>js/script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	// Paste your Flickr API key here
	var apiKey = '';

	// Creating a flickr slider. This is
	// how you would probably use the plugin.

	$('#flickrSlider').jqFlick({
		photosetID: '72157625956932639',
		width:500,
		height:320,
		autoAdvance:true,
		apiKey:apiKey
	});

	// Creating different flickr sliders,
	// depending on the select element value.

	$('select').change(function(){

		var options = {};

		switch(this.value){
			case '1':
				options = {
					photosetID: '72157625956932639',
					width:500,
					height:320,
					captions:true,
					autoAdvance:true,
					apiKey:apiKey
				};
				break;
			case '2':
				options = {
					photosetID:'42296',
					width:500,
					height:500,
					captions:true,
					autoAdvance:true,
					apiKey:apiKey
				};
				break;
			case '3':
				options = {
					photosetID:'72157625961099915',
					width:200,
					height:150,
					apiKey:apiKey
				}
		}

		$('#flickrSlider').jqFlick(options);
	});

});</pre>
<p>In the switch statement above, I am listening for the change event of the select dropdown. There, depending on the value of the select, I assign different options objects, which are then passed to the plugin. This demonstrates the different options that are available without taking much screen space.</p>
<p><strong>With this our Flickr-powered Slideshow is complete!</strong></p>
<h3>Conclusion</h3>
<p>You can use this plugin to build slideshows, product guides or presentations. To use the plugin you just need to drop the jqFlickr folder to your website root and include jqFlick.css and jqFlick.js in your HTML documents.</p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2011/02/flickr-api-slideshow-jquery/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Dynamic FAQ Section w/ jQuery, YQL &amp; Google Docs</title>
		<link>http://tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/</link>
		<comments>http://tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 15:22:49 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=1061</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/"><img src="http://cdn.tutorialzine.com/img/featured/1061.jpg" /></a></div> In this tutorial, we are making a dynamic FAQ section. The script, with the help of jQuery &#038; YQL, will pull the contents of a shared spreadsheet in your Google Docs account, and use the data to populate the FAQ section with content.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/"><img src="http://cdn.tutorialzine.com/img/featured/1061.jpg" /></a></div> <p>In this tutorial, we are making a dynamic FAQ section. The script, with the help of jQuery &amp; <a href="http://developer.yahoo.com/yql/" target="_blank">YQL</a>, will pull the contents of a shared spreadsheet in your Google Docs account, and use the data to populate the FAQ section with questions and answers.</p>
<p>The best aspect of this solution, is that you can change the contents of  the FAQ section from within Google Docs &#8211; just edit the spreadsheet.  You can even leverage the rest of Google Docs&#8217; features, such as  collaborative editing. This way, a small team can support the FAQ  section without the need of a dedicated CMS solution.</p>
<p><em>Thanks to <a href="http://csi.nfshost.com/goodies/" target="_blank">Chris Ivarson</a> for designing the Google Docs icon, used in the featured illustration of this tutorial.</em></p>
<h3>Google Docs</h3>
<p>Before starting work on the FAQ section, we first need to create a new Google Docs Spreadsheet. As you probably already have an account with Google (if not, <a href="https://docs.google.com/">create one</a>), we&#8217;ll move straight to the interesting part.</p>
<p>In a blank spreadsheet, start filling in two columns of data. The first column should contain the questions, and the second one the answers, that are going to become entries in your FAQ section. Each FAQ goes on a separate line. You can see the one that I created <a href="https://spreadsheets.google.com/ccc?key=0Ahe1-YRnPKQ_dEI0STVPX05NVTJuNENhVlhKZklNUlE&amp;hl=en&amp;authkey=CJiB3agC" target="_blank">here</a>.</p>
<p>After this, click <strong>Share &gt; Publish as webpage</strong> and choose CSV from the dropdown list. This will generate a link to your spreadsheet in the form of a regular CSV file, which we will use later.</p>
<h3>The HTML</h3>
<p>The first step in developing the script is the markup. The <strong>#page</strong> div is the main container element. It is the only div with an explicit width. It is also centered in the middle of the page with a <a href="http://tutorialzine.com/2010/03/centering-div-vertically-and-horizontally/">margin:auto</a>, as you will see in the CSS part of the tut.</p>
<h4>faq.html</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;

&lt;link rel="stylesheet" type="text/css" href="styles.css" /&gt;

&lt;/head&gt;

&lt;body&gt;

&lt;div id="page"&gt;

    &lt;div id="headingSection"&gt;
    	&lt;h1&gt;Frequently Asked Questions&lt;/h1&gt;
        &lt;a class="button expand" href="#"&gt;Expand&lt;/a&gt;
    &lt;/div&gt;

    &lt;div id="faqSection"&gt;
    	&lt;!-- The FAQs are inserted here --&gt;
    &lt;/div&gt;

&lt;/div&gt;

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script src="script.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>The stylesheet is included in the head of the document, and the jQuery library and our <strong>script.js</strong> are included at the bottom. All of these are discussed in detail in the next sections of this tutorial.</p>
<p>The <strong>#headingSection</strong> contains the h1 heading, and the expand/collapse button. After it comes the <strong>#faqSection</strong> div, where the FAQ entries are inserted after jQuery fetched the contents of your Google Docs Spreadsheet.</p>
<p>The FAQ entries are organized as a definition list structure (<strong>dl</strong>). This is one of the least used HTML elements, but is perfect for our task. Here is how it looks once jQuery adds it to the page.</p>
<h4>faq.html</h4>
<pre class="brush:html">&lt;dl&gt;
    &lt;dt&gt;&lt;span class="icon"&gt;&lt;/span&gt;How does this FAQ section work?&lt;/dt&gt;
    &lt;dd&gt;With the help of jQuery and YQL, this script pulls the latest data ..&lt;/dd&gt;

    &lt;dt&gt;&lt;span class="icon"&gt;&lt;/span&gt;Can you modify it?&lt;/dt&gt;
    &lt;dd&gt;This is the best part of it - you can change the contents ..&lt;/dd&gt;
&lt;/dl&gt;</pre>
<p>The <strong>dl</strong> element holds a <strong>dt</strong> for each question and a <strong>dd</strong> for each answer. The dd elements are hidden with display:none, and are only shown with a <strong>slideDown</strong> animation once the respective <strong>dt</strong> is clicked.</p>
<div id="attachment_1066" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/faq.html"><img class="size-full wp-image-1066" title="Dynamic FAQ Section" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/21.jpg" alt="Dynamic FAQ Section" width="620" height="460" /></a><p class="wp-caption-text">Dynamic FAQ Section</p></div>
<h3>The CSS</h3>
<p>The styles, (held in styles.css) are pretty straightforward and self-explanatory. As mentioned above, only the <strong>#page</strong> div, which acts as the main container, is explicitly assigned a width. It is also centered in the middle of the page with an auto value for the left/right margins.</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">#page{
	width:753px;
	margin:50px auto;
}

#headingSection{
	background-color:#7b8b98;
	padding:40px;
	padding-left:60px;
	position:relative;
	border:1px solid #8b9ba7;
	border-bottom:none;
}

#faqSection{
	background:url('img/faq_bg.jpg') repeat-y #fff;
	padding:20px 90px 60px 60px;
	border:1px solid white;
	text-shadow:1px 1px 0 white;
}

h1{
	color:#fff;
	font-size:36px;
	font-weight:normal;
}

/* The expand / collapse button */

a.button{
	background:url('img/buttons.png') no-repeat;
	width:80px;
	height:38px;
	position:absolute;
	right:50px;
	top:45px;
	text-indent:-9999px;
	overflow:hidden;
	border:none !important;
}

a.button.expand:hover{ background-position:0 -38px;}
a.button.collapse{ background-position:0 -76px;}
a.button.collapse:hover{ background-position:0 bottom;}
</pre>
<p>We are using a single anchor tag for both the expand and the collapse button, by assigning it either the <strong>expand</strong> or the <strong>collapse</strong> CSS class. These classes determine which parts of the background image are offset into view. The background image itself is four times the height of the button, and contains a normal and a hover state for both the expand and collapse button versions.</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">/* Definition Lists */

dt{
	color:#8F9AA3;
	font-size:25px;
	margin-top:30px;
	padding-left:25px;
	position:relative;
	cursor:pointer;
	border:1px solid transparent;
}

dt:hover{ color:#5f6a73;}

dt .icon{
	background:url('img/bullets.png') no-repeat;
	height:12px;
	left:0;
	position:absolute;
	top:11px;
	width:12px;
}

dt.opened .icon{ background-position:left bottom;}

dd{
	font-size:14px;
	color:#717f89;
	line-height:1.5;
	padding:20px 0 0 25px;
	width:580px;
	display:none;
}
</pre>
<p>When a definition title (dt) is clicked, its respective dd is expanded into view (as you will see in the next section). With this, the dt is also assigned an <strong>opened</strong> class. This class helps jQuery determine which FAQ&#8217;s are opened, and in the same time affects the styling of the small bullet on the left of the title.</p>
<div id="attachment_1067" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/faq.html"><img class="size-full wp-image-1067" title="FAQ expanded" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/3.png" alt="FAQ expanded" width="620" height="260" /></a><p class="wp-caption-text">FAQ expanded</p></div>
<h3>The jQuery</h3>
<p>Moving to probably the most interesting part of the tutorial. If you&#8217;ve been following the tutorials on this site, you&#8217;ve probably noticed that <a href="http://developer.yahoo.com/yql/" target="_blank">YQL</a> finds its way into <a href="http://tutorialzine.com/?s=YQL">a lot of the tutorials here</a>. The main reason behind this, is that YQL makes possible for developers to use it as a proxy for a wide range of APIs, and implement a diverse functionality entirely in JavaScript.</p>
<p>Today we are using YQL to fetch our Google Spreadsheet as CSV and parse it, so that it is available as a regular JSON object. This way, we end up with a free and easy to update data storage for our simple app.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	// The published URL of your Google Docs spreadsheet as CSV:
	var csvURL = 'https://spreadsheets.google.com/pub?key='+
			'0Ahe1-YRnPKQ_dEI0STVPX05NVTJuNENhVlhKZklNUlE&amp;hl=en&amp;output=csv';

	// The YQL address:
	var yqlURL =	"http://query.yahooapis.com/v1/public/yql?q="+
			"select%20*%20from%20csv%20where%20url%3D'"+encodeURIComponent(csvURL)+
			"'%20and%20columns%3D'question%2Canswer'&amp;format=json&amp;callback=?";

	$.getJSON(yqlURL,function(msg){

		var dl = $('&lt;dl&gt;');

		// Looping through all the entries in the CSV file:
		$.each(msg.query.results.row,function(){

			// Sometimes the entries are surrounded by double quotes. This is why
			// we strip them first with the replace method:

			var answer = this.answer.replace(/""/g,'"').replace(/^"|"$/g,'');
			var question = this.question.replace(/""/g,'"').replace(/^"|"$/g,'');

			// Formatting the FAQ as a definition list: dt for the question
			// and a dd for the answer.

			dl.append('&lt;dt&gt;&lt;span class="icon"&gt;&lt;/span&gt;'+
			question+'&lt;/dt&gt;&lt;dd&gt;'+answer+'&lt;/dd&gt;');
		});

		// Appending the definition list:
		$('#faqSection').append(dl);

		$('dt').live('click',function(){
			var dd = $(this).next();

			// If the title is clicked and the dd is not currently animated,
			// start an animation with the slideToggle() method.

			if(!dd.is(':animated')){
				dd.slideToggle();
				$(this).toggleClass('opened');
			}

		});

		$('a.button').click(function(){

			// To expand/collapse all of the FAQs simultaneously,
			// just trigger the click event on the DTs

			if($(this).hasClass('collapse')){
				$('dt.opened').click();
			}
			else $('dt:not(.opened)').click();

			$(this).toggleClass('expand collapse');

			return false;
		});

	});
});</pre>
<p>It may not be clear from the code above, but jQuery sends a JSONP request to YQL&#8217;s servers with the following YQL query:</p>
<pre class="brush:sql">SELECT * FROM csv
WHERE url='https://spreadsheets.google.com/...'
AND columns='question,answer'</pre>
<p><strong><em>CSV</em></strong> is a YQL table, which takes the URL of a csv file and a list of column names. It returns a JSON object with the column names as its properties. The script then filters them (stripping off unnecessary double quotes) and inserts them as a definition list (DL)  into the page.</p>
<p><strong>With this our dynamic FAQ section is complete!</strong></p>
<h3>Customization</h3>
<p>To use this script with your own spreadsheet, you only need to edit the csvURL variable in <strong>script.js</strong>, and replace it with the CSV  URL of your spreadsheet. You can obtain this address from <strong>Share &gt; Publish as webpage &gt; CSV dropdown</strong>. Also, be aware that when you make changes to the spreadsheet, it could take a few minutes for the changes to take effect. You can speed this up by clicking the <em><strong>Republish now</strong></em> button, found in the same overlay window.</p>
<div id="attachment_1065" class="wp-caption alignnone" style="width: 630px"><img class="size-full wp-image-1065" title="Obtaining the CSV URL" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/08/1.png" alt="Obtaining the CSV URL" width="620" height="460" /><p class="wp-caption-text">Obtaining the CSV URL</p></div>
<h3>Final Words</h3>
<p>You can use the same technique to power different kinds of dynamic pages. However, this implementation does have its shortcomings. All the content is generated with JavaScript, which means that it will not be visible to search engines.</p>
<p>To guarantee that your data will be crawled, you can take a different route. You could use PHP, or other back-end language, to fetch and display the data from YQL in a fixed interval of time &#8211; say 30 minutes (or even less frequently, if you don&#8217;t plan to update the data often).</p>
<p><strong>Be sure to share your suggestions in the comment section below.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/08/dynamic-faq-jquery-yql-google-docs/feed/</wfw:commentRss>
		<slash:comments>57</slash:comments>
		</item>
		<item>
		<title>Making Your First Google Chrome Extension</title>
		<link>http://tutorialzine.com/2010/06/making-first-chrome-extension/</link>
		<comments>http://tutorialzine.com/2010/06/making-first-chrome-extension/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 12:53:55 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=940</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2010/06/making-first-chrome-extension/"><img src="http://cdn.tutorialzine.com/img/featured/940.jpg" /></a></div> In this tutorial, we are going to create a simple extension, which puts a small icon next to Chrome's address bar, and, when clicked, will fetch Tutorialzine's RSS feed and display a fancy preview of our latest tutorials.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2010/06/making-first-chrome-extension/"><img src="http://cdn.tutorialzine.com/img/featured/940.jpg" /></a></div> <p>The Google Chrome web browser is slowly growing in popularity. This is no surprise, as it is a great browser, and is backed by no other than Google. It also provides great tools for web developers and I find myself using it more and more (actually Firebug is the only thing keeping me from crossing to the other side).</p>
<p>With the introduction of <a href="https://chrome.google.com/extensions" target="_blank">extensions</a>, Google Chrome became even more agile and powerful.</p>
<p>In this tutorial, we are going to create a simple extension, which puts a small icon next to Chrome&#8217;s address bar, and, when clicked, will fetch Tutorialzine&#8217;s RSS feed and display a fancy preview of our latest tutorials.</p>
<p>[By the way, we just launched <a href="http://www.zinescripts.com/" target="_blank">ZineScripts</a>! Use this Promo Code for a <strong>10% discount</strong>: <em>google-chrome-tut-93a2</em>]</p>
<p>First a few words about extensions.</p>
<h3>How Extensions Work</h3>
<p>Extensions in Google Chrome are basically webpages. You have javascript files, stylesheets and images. You can even use JavaScript libraries like  jQuery.</p>
<p>The extensions are, however, treated a bit differently than your regular webpage, which is displayed in the browser. You can have access to all the opened tabs, to the user&#8217;s browsing history, you can manipulate all the pages that are opened, send AJAX requests to any website and much more.</p>
<p>You also have the benefit (or the limitation) that your extension runs only on one browser. You can forget all compatibility issues and embrace Google Chrome&#8217;s hot new HTML5 features.</p>
<div id="attachment_945" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/06/making-first-chrome-extension/demo.html"><img class="size-full wp-image-945" title="Tutorialzine's Google Chrome Extension" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/06/i11.png" alt="Tutorialzine's Google Chrome Extension" width="620" height="460" /></a><p class="wp-caption-text">Tutorialzine&#39;s Google Chrome Extension</p></div>
<h3>Developing extensions</h3>
<p>Extension  are packed in a <strong>.crx</strong> file (arenamed zip file) but during development, you can map your working folder as an extension. This way you can quickly change and deploy code without the need of repackaging.</p>
<p>This is done by opening the extension page (type <em><a href="chrome://extensions/">chrome://extensions/</a></em> in the address bar, or click <em>Wrench icon &gt; Extensions</em>), and clicking <strong>Developer mode &gt; Load unpacked extension..</strong> on the page. After you make a change to the extension, just hit the Reload link below it.</p>
<p>After you&#8217;re done developing, click <strong>Pack extension..</strong> and a crx file will be created for you. You can serve this file from your site and enable your site&#8217;s visitors to install it.</p>
<p>Google Chrome is by far the easiest browser to make extensions for, as you will see from the steps below.</p>
<p><strong>A note about debugging</strong>: To debug your extension, right-click on your extension&#8217;s icon, next to the address bar, and choose <em>Inspect popup</em>. You can also check out <a href="http://code.google.com/chrome/extensions/tut_debugging.html" target="_blank">this tutorial</a>.</p>
<h3>Step 1 &#8211; Manifest.json</h3>
<p>The first step in creating an extension, is mapping a folder on your hard drive as an extension (as explained the above). You are going to put all your files in this folder.</p>
<p>The only thing required from your extension by Chrome, is the <strong>manifest.json</strong> file. This is a text file, which holds configuration settings in the form of a json object.</p>
<p>Here is the one we are going to use:</p>
<h4>manifest.json</h4>
<pre class="brush:js">{
	"name": "Tutorialzine Extension",
	"version": "1.0",
	"description": "Making your first Google Chrome extension.",
	"browser_action":	{
		"default_icon": "icon.png",
		"popup": "tutorialzine.html"
	},

	"icons":{
		"128":"icon_128.png"
	}
}</pre>
<p>In this file we are specifying the name of the extension and a number of other options, such as browser actions and permissions.</p>
<p>In <strong>browser_actions</strong>, we put settings that are in relation with the browser window. The <strong>popup</strong> property tells Chrome, that we are going to show <em>tutorialzine.html</em> as a popup. There are a number of settings you can put in browser_actions. You can read more on <a href="http://code.google.com/chrome/extensions/browserAction.html" target="_blank">Google Chrome&#8217;s Extension documentation</a>.</p>
<p>For this extension we do not need access to currently opened pages, nor manipulating tabs and windows. If we needed those, however, we would need to include a permissions property, with the addresses of the pages.</p>
<p>For more information about the manifest file, refer to <a href="http://code.google.com/chrome/extensions/manifest.html" target="_blank">Google Chrome&#8217;s documentation</a>.</p>
<h3>Step 2 &#8211; HTML 5</h3>
<p>As mentioned above, we told Chrome that <em>tutorialzine.html</em> is going to be opened as a popup. This is a regular html file, complete with stylesheets and js files.</p>
<p>And as Google Chrome has a really good support for HTML5, we can code tutorialzine.html in it. You could, however, use any HTML version you normally code your sites with.</p>
<h4>tutorialzine.html</h4>
<pre class="brush:html">&lt;!DOCTYPE html&gt; &lt;!-- The new doctype --&gt;
&lt;html&gt;
&lt;head&gt; &lt;!-- No title and meta tags are necessary for the extension --&gt;

&lt;link rel="stylesheet" type="text/css" href="style.css" /&gt;
&lt;script src="jquery.min.js"&gt;&lt;/script&gt; &lt;!-- Including jQuery --&gt;
&lt;script src="script.js"&gt;&lt;/script&gt; &lt;!-- Our script file --&gt;

&lt;/head&gt;

&lt;body&gt;

&lt;h1&gt;Latest Tutorials on Tutorialzine&lt;/h1&gt;

&lt;div id="content"&gt;
&lt;!-- The latest tutorials are going to be inserted here --&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>As you can see, we are addressing the css and js files directly. Chrome will include them for us. Just as if we are working on a regular webpage.</p>
<h3>Step 3 &#8211; CSS3</h3>
<p>As the extension is rendered Google Chrome, we do not need to limit ourselves with the least common denominator when it comes to CSS3 support. This is why we can afford to use fancy rules like <strong>-webkit-box-reflection</strong> and <strong>-webkit-gradient</strong>.</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">*{
	margin:0;
	padding:0;
}

body{
	/* Setting default text color, background and a font stack */
	font-size:12px;
	color:#666;

	/* A webkit gradient: */
	background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#EEE), to(#DDD));

	text-shadow:1px 1px 0 white;
	font-family:Arial, Helvetica, sans-serif;
	overflow-x:hidden;
}

.tutorial{
	width:500px;
	padding:10px 20px;
	margin-bottom:10px;
}

img{
	width:100px;
	height:100px;
	float:left;

	/* Webkit CSS3 Reflection */
	-webkit-box-reflect: below 0 -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.75, transparent), to(rgba(255, 255, 255, 0.3))) 0 0 0 0 stretch stretch;
}</pre>
<p><strong>-webkit-box-reflect</strong> creates a pure CSS reflection under the thumbnail images. It takes a number of parameters to generate the reflection &#8211; position of the reflection, offset from the bottom of the image, and a mask (which is defined with a gradient).</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">p,a{
	padding:10px 0 0 120px;
	display:block;
}

a,a:visited{
	color:#09F;
	text-decoration:none;
}

a:hover{
	text-decoration:underline;
}

h1{
	/* Webkit gradient: */
	background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#EEE), to(#DDD));

	border-bottom: 1px solid #F0F0F0;
	font-size: 24px;
	font-weight: normal;
	margin-bottom: 30px;
	padding: 30px 0px;
	text-align: center;
	text-shadow: white 0px 1px 1px;
}

h2{
	font-size:24px;
	font-weight:normal;
	right:40px;
	padding-left:120px;
}

h1,h2{
	font-family:"Myriad Pro",Arial,Helvetica,sans-serif;
}</pre>
<p>In the second part of the code we are also using a gradient, but this time as a background for the h1 element.</p>
<div id="attachment_946" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/06/making-first-chrome-extension/demo.html"><img class="size-full wp-image-946" title="CSS3 Reflections &amp; Text Shadows" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/06/i21.png" alt="CSS3 Reflections &amp; Text Shadows" width="620" height="260" /></a><p class="wp-caption-text">CSS3 Reflections &amp; Text Shadows</p></div>
<h3>Step 4 &#8211; jQuery</h3>
<p>The JavaScript is executed as if it was part of a regular web page. This means that we can include the jQuery library and define a <strong>$(document).ready()</strong> function as we would normally do in a web project.</p>
<p>Clicking the extension icon has the same effect for the scripts on the page, as opening the page in a browser.</p>
<p>Inside $(document).ready(), we fetch the latest results from Tutorialzine&#8217;s RSS feed, with the help of <strong>Yahoo&#8217;s YQL API</strong>. We&#8217;ve used this API a <a href="http://tutorialzine.com/?s=YQL" target="_blank">couple of times before</a>, here on Tz. It allows us to use an SQL-like syntax to fetch data in a JSON format.</p>
<p>After fetching the data, we generate the HTML markup and include it in <em>tutorialzine.html</em>. We also save it to <strong>localStorage</strong> as a simple caching solution. localStorage is a simple way to save persistent data (it survives between page loads). This makes the experience of using the extension a lot faster.</p>
<h4>script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	var query = "SELECT * FROM feed WHERE url='http://feeds.feedburner.com/Tutorialzine' LIMIT 2";

	// Storing the seconds since the epoch in now:
	var now = (new Date()).getTime()/1000;

	// If there is no cache set in localStorage, or the cache is older than 1 hour:
	if(!localStorage.cache || now - parseInt(localStorage.time) &gt; 1*60*60)
	{
		$.get("http://query.yahooapis.com/v1/public/yql?q="+encodeURIComponent(query)+"&amp;format=json&amp;callback=?",function(msg){

			// msg.query.results.item is an array:
			var items = msg.query.results.item;
			var htmlString = "";

			for(var i=0;i&lt;items.length;i++)
			{
				var tut = items[i];

				// Extracting the post ID from the permalink:
				var id = tut.guid.content.match(/(\d+)$/)[0];

				// Looping and generating the markup of the tutorials:

				htmlString += '&lt;div class="tutorial"&gt;\
								&lt;img src="http://cdn.tutorialzine.com/img/posts/'+id+'.jpg" /&gt;\
								&lt;h2&gt;'+tut.title+'&lt;/h2&gt;\
								&lt;p&gt;'+tut.description+'&lt;/p&gt;\
								&lt;a href="'+tut.link+'" target="_blank"&gt;Read more&lt;/a&gt;\
								&lt;/div&gt;';
			}

			// Setting the cache
			localStorage.cache	= htmlString;
			localStorage.time	= now;

			// Updating the content div:
			$('#content').html(htmlString);
		},'json');
	}
	else{
		// The cache is fresh, use it:
		$('#content').html(localStorage.cache);
	}
});</pre>
<p>In localStorage we also store a timestamp. We use it to determine how old the cache in localStorage is. If it is older than an hour, we ignore it and fetch the data again.</p>
<p>Here is a sample of the data that is returned from YQL.</p>
<pre class="brush:js">{
	"query": {
		"count": "1",
		"created": "2010-06-09T12:02:33Z",
		"lang": "en-US",
		"results": {

			"item": {
				"title": "Neon Text Effect With jQuery &amp; CSS",
				"link": "http://feedproxy.google.com/..",

				"comments": [
					"http://tutorialzine.com/2010/06/neon-text-effect..",
					"11"
				],

				"pubDate": "Tue, 01 Jun 2010 20:11:54 +0000",
				"creator": "Martin Angelov",

				"category": [
					"CSS",
					"jQuery"
				],

				"guid": {
					"isPermaLink": "false",
					"content": "http://tutorialzine.com/?p=925"
				},

				"description": "In this combined design and coding tutorial..",
				"commentRss": "http://tutorialzine.com/2010/06/neon-text-e..",
				"origLink": "http://tutorialzine.com/2010/06/neon-text-eff.."

			}
		}
	}
}
</pre>
<p>This structure is made available to us in the <strong>msg</strong> variable on line 11 of script.js.</p>
<p><strong>With this your first Google Chrome extension is complete!</strong></p>
<h3>Conclusion</h3>
<p>You can read more about extensions (including advanced features not covered in this tutorial) on <a href="http://code.google.com/chrome/extensions/overview.html" target="_blank">Google Chrome&#8217;s Extension documentation page</a>. I hope that this tutorial has given you a great start in extending the browser&#8217;s functionality.</p>
<p><strong>What do you think? Would you make a Chrome extension for your website?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/06/making-first-chrome-extension/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Combined Facebook, Twitter &amp; RSS Social Stats with jQuery, PHP &amp; YQL</title>
		<link>http://tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/</link>
		<comments>http://tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/#comments</comments>
		<pubDate>Wed, 19 May 2010 21:50:43 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=909</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/"><img src="http://cdn.tutorialzine.com/img/featured/909.jpg" /></a></div> This week we are going to create a simple widget, which combines the number of your RSS readers, twitter followers, and fans of your facebook fan page, to give a rough estimate of your social popularity.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/"><img src="http://cdn.tutorialzine.com/img/featured/909.jpg" /></a></div> <p>As we increasingly depend on more and more social services, there rises the need to provide a simple way to let our website visitors take part of our diverse social presence.</p>
<p>In this tutorial we are going to create a simple widget, which combines the number of your RSS readers, twitter followers, and fans of your facebook fan page, to give a rough estimate of your social popularity.</p>
<p>We are using jQuery and the <a href="http://code.drewwilson.com/entry/tiptip-jquery-plugin" target="_blank">tipTip plugin</a>, object-oriented PHP, and <a href="http://developer.yahoo.com/yql/" target="_blank">Yahoo&#8217;s YQL</a>, while demonstrating a number of interesting web development techniques.</p>
<blockquote class="note"><p><strong>Update</strong>: Facebook has made a minor change in their API which prevented this script from fetching the page fan count. This is now fixed and you can download the script again.</p></blockquote>
<h3>Step 1 &#8211; PHP</h3>
<p>YQL is a free Yahoo web service, which enables us to communicate  with numerous third-party APIs through a consistent SQL-like language (and hence the name). It is basically a gateway that sits between you and the other APIs.</p>
<p>This is especially important here, as we are using Yahoo&#8217;s YQL for  three very different tasks:</p>
<ul>
<li>Fetch your RSS subscriber count with FeedBurner&#8217;s <a href="http://code.google.com/apis/feedburner/awareness_api.html" target="_blank"> awareness API</a> (which comes in the form of an XML file that has to be parsed).<strong><br />
Note: </strong><em>You have to enable the awareness API to use this widget with your own feed. This is done from the Publicize Tab on your feed settings page</em>;</li>
<li>Use twitter&#8217;s API to get your number of followers;</li>
<li>Use Facebook&#8217;s new <strong>Graph API</strong> (<a href="http://developers.facebook.com/docs/api" target="_blank">link</a>) to get  information about the number of fans of your facebook fanpage.</li>
</ul>
<p>If it weren&#8217;t for YQL, we&#8217;d have to research and implement three very different solutions, which would slow us down significantly.</p>
<h4>includes/subscriber_stats.class.php</h4>
<pre class="brush:php">class SubscriberStats{

	public	$twitter,$rss,$facebook;
	public	$services = array();

	public function __construct($arr){

		$this-&gt;services = $arr;

		$yqlQueries = array();

		// Forming the Feedburner Awaraness API URL from the passed feed URL:
		$feedBurnerAwarenessAPI = 'http://feedburner.google.com/api/awareness'.
		'/1.0/GetFeedData?uri='.end(split('/',trim($arr['feedBurnerURL'],'/')));

		// Building an array with queries:

		if($arr['feedBurnerURL'])
			$yqlQueries[] = '
				SELECT * FROM xml
				WHERE url=\''.$feedBurnerAwarenessAPI.'\'
			';

		if($arr['twitterName'])
			$yqlQueries[] = '
				SELECT * FROM twitter.user.profile
				WHERE id=\''.$arr['twitterName'].'\'
			';

		if($arr['facebookFanPageURL'])
			$yqlQueries[] = '
			SELECT likes FROM facebook.graph
			WHERE id=\''.end(split('/',trim($arr['facebookFanPageURL'],'/'))).'\'
			';

		// Combing them into a YQL multiquery:
		$multiQuery =
		'SELECT * FROM query.multi WHERE queries = "'.join(';',$yqlQueries).'"';

		// Executing the query:
		$result = json_decode(
			file_get_contents('http://query.yahooapis.com/v1/public/yql?q='.
			urlencode($multiQuery).'&amp;format=json&amp;diagnostics=false&amp;'
			'amp;env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys')
		)-&gt;query-&gt;results-&gt;results;

		// The results from the queries are accessible in the $results array:

		$this-&gt;rss = $result[0]-&gt;rsp-&gt;feed-&gt;entry-&gt;circulation;
		$this-&gt;twitter = $result[1]-&gt;item-&gt;meta[5]-&gt;content;
		$this-&gt;facebook = $result[2]-&gt;json-&gt;fan_count;
	}

	public function generate(){

		$total = number_format($this-&gt;rss+$this-&gt;twitter+$this-&gt;facebook);

		echo '
			&lt;div class="subscriberStats"&gt;
				&lt;div class="subscriberCount"
				title="'.$total.'+ Total Social Media Followers"&gt;'.$total.'&lt;/div&gt;

				&lt;div class="socialIcon"
				title="'.number_format($this-&gt;rss).' RSS Subscribers"&gt;
					&lt;a href="'.$this-&gt;services['feedBurnerURL'].'"&gt;
					&lt;img src="img/rss.png" alt="RSS" /&gt;&lt;/a&gt;
				&lt;/div&gt;

				&lt;div class="socialIcon"
				title="'.number_format($this-&gt;facebook).' Fans on Facebook"&gt;
					&lt;a href="'.$this-&gt;services['facebookFanPageURL'].'"&gt;
					&lt;img src="img/facebook.png" alt="Facebook" /&gt;&lt;/a&gt;
				&lt;/div&gt;

				&lt;div class="socialIcon"
				title="'.number_format($this-&gt;twitter).' Twitter Followers"&gt;
				&lt;a href="http://twitter.com/'.$this-&gt;services['twitterName'].'"&gt;
					&lt;img src="img/twitter.png" alt="Twitter" /&gt;&lt;/a&gt;
				&lt;/div&gt;
			&lt;/div&gt;
		';
	}
}</pre>
<p>When we create an object of this class, the construct method is called, and a YQL query is created and executed.</p>
<p>To request the data from YQL&#8217;s servers, we just use <strong>file_get_contents()</strong> with the query passed as a parameter of the URL address. This returns a JSON object (basically a JavaScript object) which we can decode into a native PHP array with the in-build <strong>json_decode()</strong> function.</p>
<p>The results of these queries are saved locally and are made available for use in the <strong>generate()</strong> method which renders all the needed markup.</p>
<p>And now lets see how this class is used:</p>
<h4>subscriber_count.php</h4>
<pre class="brush:php">require "includes/subscriber_stats.class.php";

$cacheFileName = "cache.txt";

// IMPORTANT: after making changes to this file (or the SubscriberStats class)
// remeber to delete cache.txt from your server, otherwise you wont see your changes.

// If a cache file exists and it is less than 6*60*60 seconds (6 hours) old, use it:

if(file_exists($cacheFileName) &amp;&amp; time() - filemtime($cacheFileName) &gt; 6*60*60)
{
	$stats = unserialize(file_get_contents($cacheFileName));
}

if(!$stats)
{
	// If no cache was found, fetch the subscriber stats and create a new cache:

	$stats = new SubscriberStats(array(
		'facebookFanPageURL'	=&gt; 'http://www.facebook.com/smashmag',
		'feedBurnerURL'			=&gt; 'http://feeds.feedburner.com/Tutorialzine',
		'twitterName'			=&gt; 'Tutorialzine'
	));

	// Serialize turns the object into a string,
	// which can later be restored with unserialize():

	file_put_contents($cacheFileName,serialize($stats));
}

//	You can access the individual stats like this:
//	$stats-&gt;twitter;
//	$stats-&gt;facebook;
//	$stats-&gt;rss;

//	Output the markup for the stats:

$stats-&gt;generate();</pre>
<p>Sending a query to YQL&#8217;s servers and receiving a response is a relatively slow process and would be unwise to request the same information on every page load (not to mention that we could get banned from the API for abuse).</p>
<p>This is why we implement a simple caching system. The idea is simple: if a cache file does not exist (or is older than 6 hours), connect to YQL, create a new cache file and output the XHTML markup. Otherwise, just read the cache and output directly. This way we send a request to the API only once every six hours which is perfect for any practical purposes.</p>
<div id="attachment_913" class="wp-caption alignnone" style="width: 630px"><a href="http://demo.tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/demo.html"><img class="size-full wp-image-913 " title="Combined Social Media Followers Count" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/05/i11.png" alt="Combined Social Media Followers Count" width="620" height="260" /></a><p class="wp-caption-text">Combined Social Media Followers Count</p></div>
<h3>Step 2 &#8211; XHTML</h3>
<p>As mentioned in the PHP section above, the generate() method renders all the XHTML markup used to display the stats. Here is what the generated code looks like:</p>
<h4>sample code</h4>
<pre class="brush:html">&lt;div class="subscriberStats"&gt;
    &lt;div class="subscriberCount"  title="25,382+ Total Social Media Followers&gt;25,382&lt;/div&gt;

    &lt;div class="socialIcon" title="5,921 RSS Subscribers"&gt;
        &lt;a href="http://feeds.feedburner.com/Tutorialzine"&gt;
        &lt;img alt="RSS" src="img/rss.png" /&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div class="socialIcon" title="16,813 Fans on Facebook"&gt;
        &lt;a href="http://www.facebook.com/smashmag"&gt;
        &lt;img alt="Facebook" src="img/facebook.png" /&gt;&lt;/a&gt;
    &lt;/div&gt;

    &lt;div class="socialIcon" title="2,648 Twitter Followers"&gt;
        &lt;a href="http://twitter.com/Tutorialzine"&gt;
        &lt;img alt="Twitter" src="img/twitter.png" /&gt;&lt;/a&gt;
    &lt;/div&gt;
&lt;/div&gt;</pre>
<p>This code is fetched via AJAX and displayed on the page. Notice the title attributes. They are used as the contents of the fancy tooltips which are created by jQuery and the tipTip plugin, which we will discuss in a moment.</p>
<h3>Step 3 &#8211; CSS</h3>
<p>The CSS code is also quite simple and straightforward. The <strong>subscriberStats</strong> is the main outer div, inside it we have a number of <strong>.socialIcon</strong> divs and the <strong>subscrberCount</strong>.</p>
<h4>css/styles.css</h4>
<pre class="brush:css">.subscriberStats{
	height:35px;
	padding:5px;
	width:220px;
}

.socialIcon{
	float:left;
	height:32px;
	width:32px;
}

a img{
	border:none;
}

.subscriberCount{
	border-bottom:1px dotted #CCCCCC;
	color:#999999;
	float:left;
	font-size:28px;
	line-height:32px;
	margin-right:10px;
}

#main{
	height:100px;
	margin:140px auto 50px;
	position:relative;
	width:200px;
}</pre>
<p>All of these are floated to the left. Also notice that we disable the borders on the icon images on line 14, which are displayed by default and ruin your design.</p>
<h3>Step 4 &#8211; jQuery</h3>
<p>After including the jQuery library to the page, we just need to listen to the $(document).ready event, which is executed when all the markup of the page is accessible (this happens before things like images are loaded and comes earlier than the onload event).</p>
<h4>js/script.js</h4>
<pre class="brush:js">$(document).ready(function(){

	// Using the load AJAX method to fetch the subscriber markup
	// from subscriber_count.php:

	$('#main').load('subscriber_count.php',function(){

		// Once loaded, convert the title attributes to tooltips
		// with the tipTip jQuery plugin:

		$('.subscriberStats div').tipTip({defaultPosition:'top'});
	})

});</pre>
<p><strong>#main</strong> is the div where we want to insert the stats. This could be your sidebar or website header. The load method fetches the markup from <strong>suscriber_count.php</strong> and displays it on the page.  The callback function is called after this and all the div titles are replaced with fancy tooltips by the <em>tipTip plugin</em>.</p>
<p><strong>With this our combined social stats widget is complete!</strong></p>
<h3>Conclusion</h3>
<p>With services like YQL working with third party APIs is a charm. Not only it provides a common interface to a sea of technologies, but it also guarantees that you will be able to access to the services you want even as the underlying APIs change overtime.</p>
<p><strong>What do you think? How would you improve this code?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/05/showing-facebook-twitter-rss-stats-jquery-yql/feed/</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
		<item>
		<title>Making a Sleek Feed Widget With YQL, jQuery &amp; CSS3</title>
		<link>http://tutorialzine.com/2010/02/feed-widget-jquery-css-yql/</link>
		<comments>http://tutorialzine.com/2010/02/feed-widget-jquery-css-yql/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 16:08:21 +0000</pubDate>
		<dc:creator>Martin Angelov</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://tutorialzine.com/?p=661</guid>
		<description><![CDATA[<div><a href="http://tutorialzine.com/2010/02/feed-widget-jquery-css-yql/"><img src="http://cdn.tutorialzine.com/img/featured/661.jpg" /></a></div> We are making a sleek feed widget, that will fetch any feed and display it in your blog sidebar. You can set it up to show the latest posts from the different categories of your blog, your latest stumbles, or even people mentioning you on twitter.]]></description>
			<content:encoded><![CDATA[<div><a href="http://tutorialzine.com/2010/02/feed-widget-jquery-css-yql/"><img src="http://cdn.tutorialzine.com/img/featured/661.jpg" /></a></div> <p>You will be surprised at how much data is made available on the web through RSS or ATOM feeds &#8211; twitter searches, your latest diggs, Google Search alerts, your own blog categories and so much more. You just have to look for that orange icon and you&#8217;ll surely find a lot more precious data, just waiting to be put into use.</p>
<p>Today we are making a <strong>sleek feed widget</strong>, that will fetch any feed and display it in your blog sidebar. You can set it up to show the latest posts from the different categories of your blog, your latest stumbles, or even people mentioning you on twitter.</p>
<p><em>So go ahead, <strong>download the demo archive from the button above</strong>, and keep on reading..</em></p>
<h3>Problem Solving</h3>
<p>Before stepping into development, we have to clarify for ourselves what we are aiming for, discuss some potential problems, and their solutions.</p>
<h4>Problem 1 &#8211; Fetching Feeds</h4>
<p>The widget is entirely front-end based, so we have to find a way to fetch the feeds directly with JavaScript. AJAX is a great technology, but there are security restrictions that limit it to fetching data only from the current domain. This means we cannot access feeds directly and display them.</p>
<p>This is where <strong>YQL</strong> comes along. It fetches the feed we want, and makes it available to our script as a regular <strong>JSON</strong> object that we can later loop and print to the page.</p>
<blockquote><p>YQL is a free <strong>API</strong> service from Yahoo, with which you can do much more than just download feeds. It acts as a gateway between you and other API&#8217;s and lets you manipulate them with a quick to learn SQL-like syntax (hence the name).</p>
<p><span class="small">You can reed more about it in <a href="http://net.tutsplus.com/tutorials/other/an-api-for-the-web-learning-yql/" target="_blank">this tutorial on nettuts</a>, or go to the official <a href="http://developer.yahoo.com/yql/" target="_blank">YQL page</a>.</span></p></blockquote>
<p>Setting up YQL to work is tricky though (we have to dynamically include a <strong>&lt;script&gt;</strong> tag to the head section of the page, like we did in the <a href="http://tutorialzine.com/2009/10/jquery-twitter-ticker/">Twitter Ticker tutorial</a> few months back). Luckily, jQuery provides a method for just this purpose &#8211; <strong>getJSON</strong>. It does everything behind the scenes, so we don&#8217;t have to worry about the implementation.</p>
<h4>Problem 2 &#8211; Different Feed Formats</h4>
<p>As with everything else, feeds are available in a number of formats &#8211;  <strong>RSS1, RSS2</strong> and <strong>ATOM</strong>. They all have their differences and present a  challenge, because our code has to be able to loop through the results returned by <strong>YQL</strong> and successfully display the entries.</p>
<p>The solution to this is to move the functionality that displays the feeds in a separate function and use a number of logical <strong>OR</strong>-s ( || ) throughout the code. It works with all the feeds that I tested it with, but you could easily make your own version of the function for special cases (for example displaying Flickr streams with a thumbnail).</p>
<h4>Problem 3 &#8211; Insufficient Space</h4>
<p>This is more of a layout problem actually, but is quite an important one. Given the limited width of the blog sidebar area, it becomes evident that it is impossible to display more than a couple of tabs simultaneously, if we go with the regular horizontal placement. So the best option is to have them show in a sleek drop down, which can store all the feeds one could possibly want.</p>
<p><em>With those issues addressed, we can now move on to development.</em></p>
<h3>Step 1 &#8211; XHTML</h3>
<p>The first part of the tutorial consists of laying down the XHTML structure for the feed widget. The snippet below (extracted from <strong>demo.html</strong> in the download archive) is everything you need to show the widget on your page (apart from the CSS and jQuery files, covered in the later steps).</p>
<h4>demo.html</h4>
<pre class="brush:html">&lt;div id="feedWidget"&gt;

	&lt;div id="activeTab"&gt;
		&lt;!-- The name of the current tab is inserted here --&gt;
	&lt;/div&gt;

	&lt;div class="line"&gt;&lt;/div&gt;

	&lt;div id="tabContent"&gt;
		&lt;!-- The feed items are inserted here --&gt;
	&lt;/div&gt;

&lt;/div&gt;
</pre>
<p>As the widget is entirely dependent on JavaScript to function, there is little point in providing a fallback solution. The best we can do is to entirely hide it from view if JS is disabled. This is why the <strong>feedWidget</strong> div is hidden with <strong>display:non</strong>e in the stylesheet file, and shown with jQuery&#8217;s <strong>show()</strong> method in <strong>script.js</strong> (which will be run only if JS is available).</p>
<p>Now lets move to the next step.</p>
<div id="attachment_664" class="wp-caption alignnone" style="width: 630px"><a href="http://cdn.tutorialzine.com/wp-content/uploads/2010/02/i11.jpg"><img class="size-full wp-image-664" title="Feed Widget With jQuery, CSS3 &amp; YQL" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/02/i11.jpg" alt="Feed Widget With jQuery, CSS3 &amp; YQL" width="620" height="460" /></a><p class="wp-caption-text">Feed Widget With jQuery, CSS3 &amp; YQL</p></div>
<h3>Step 2 &#8211; CSS</h3>
<p>The styling of the widget is defined in <strong>styles.css</strong>. Only the styles that are directly used by the widget are included here. You can view the rest of the CSS declarations that define the looks of the page itself in that file.</p>
<h4>styles.css &#8211; Part 1</h4>
<pre class="brush:css">#feedWidget{
	background:url(img/bg.png) repeat-x #47525c;
	border:2px solid #48535e;
	margin:0 auto;
	width:200px;
	padding:5px;
	position:relative;

	/* Remains hidden if JS is not enabled: */
	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 round corners: */
	-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;
}</pre>
<p>Notice that we define a special hover class for the <strong>#activeTab</strong> div, instead of the regular <strong>:hover</strong> pseudo-class. This is because the hover style should only be applied if there is more than one tab to be shown, which is impossible to determine with CSS alone. This is why we apply it with JS.</p>
<p>The <strong>dropDownList</strong> shares a number of properties with the <strong>hover</strong> class of the <strong>#activeTab</strong> div. The most effective way to write the CSS is to group those two together, and later individually apply only those rules that differ, as you can see in the snippet below:</p>
<h4>styles.css &#8211; Part 2</h4>
<pre class="brush:css">.dropDownList{
	background-image:none;
	position:absolute;

	border-top:none;
	padding:5px;

	/* We reset the roundness of the top corners, inherited by a previous rule: */

	-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{
	/* The feed entry divs */

	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 box shadow: */
	-moz-box-shadow:0 1px 1px black;
	-webkit-box-shadow:0 1px 1px black;
	box-shadow:0 1px 1px black;
}
</pre>
<p>We apply a number of CSS3 rules here: <strong>border-radius</strong> for pure CSS rounded corners and <strong>box-shadow</strong> for adding a drop shadow below the feed items. They are provided with the -<strong>moz</strong>- and -<strong>webkit</strong>- vendor prefixes, because the regular version is not yet supported in any browser (but we supply it as well for future-proofing).</p>
<div id="attachment_665" class="wp-caption alignnone" style="width: 630px"><a href="http://cdn.tutorialzine.com/wp-content/uploads/2010/02/i31.jpg"><img class="size-full wp-image-665" title="The Dropdown" src="http://cdn.tutorialzine.com/wp-content/uploads/2010/02/i31.jpg" alt="The Dropdown" width="620" height="260" /></a><p class="wp-caption-text">The Dropdown</p></div>
<h3>Step 3 &#8211; jQuery</h3>
<p>After including the jQuery library into the page, it is now possible to leverage the methods it provides and build some complex interactions that would otherwise be impossible (or at least would take too much development resources).  The JavaScript code is located in <strong>scripts.js</strong> in the demo files.</p>
<h4>script.js &#8211; Part 1</h4>
<pre class="brush:js">/* Configuration: */

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 &amp; Style" : {
		"feed"		: "http://feeds2.feedburner.com/ScriptAndStyle",
		"function"	: rss
	}
}

$(document).ready(function(){
	/* This code is executed after the DOM has been completely loaded */

	/* Counting the tabs: */
	var totalTabs=0;
	$.each(tabs,function(){totalTabs++;})

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

		/* If the cursor left the widet, hide the drop down list: */
		$('.dropDownList').remove();
		$('#activeTab').removeClass('hover');

	}).mouseenter(function(){

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

	});

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

	/* Using the live method to bind an event, because the .dropDownList does not exist yet: */

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

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

	/* Showing one of the tabs on load: */

	showTab('@tutorialzine');
});
</pre>
<p>Notice the <strong>tabs</strong> object. It contains the declarations of the different feeds we want to use, along with a function that handles the output of those feeds to the page. The name of the property (before the colon) is inserted as a tab name, and when passed to the <strong>showTab()</strong> function, shows the contents of this feed inside the widget. This is how we load the &#8216;<strong>@tutorialzine</strong>&#8216; tweets on page load.</p>
<h4>script.js &#8211; Part 2</h4>
<pre class="brush:js">function showTab(key)
{
	var obj = tabs[key];
	if(!obj) return false;

	var stage = $('#tabContent');

	/* Forming the query: */
	var query = "select * from feed where url='"+obj.feed+"' LIMIT 5";

	/* Forming the URL to YQL: */
	var url = "http://query.yahooapis.com/v1/public/yql?q="+encodeURIComponent(query)+"&amp;format=json&amp;callback=?";

	$.getJSON(url,function(data){

		stage.empty();

		/* item exists in RSS and entry in ATOM feeds: */

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

			try{
				/* Trying to call the user provided function, "this" the rest of the feed data: */
				stage.append(obj['function'](this));

			}
			catch(e){
				/* Notifying users if there are any problems with their handler functions: */
				var f_name =obj['function'].toString().match(/function\s+(\w+)\(/i);
				if(f_name) f_name = f_name[1];

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

	});

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

function showDropDown()
{
	if(totalTabs&lt;2) return false;

	if($('#feedWidget .dropDownList').length)
	{
	/* If the drop down is already shown, hide it: */

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

	return false;

	}

	var activeTab = $('#activeTab');

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

	/* Creating the drop down div on the fly: */

	var dropDown = $('&lt;div&gt;').addClass('dropDownList').css({

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

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

	$.each(tabs,function(j){

		/* Populating the div with the tabs that are not currently shown: */
		if(j==activeTab.text()) return true;

		$('&lt;div&gt;').text(j).appendTo(dropDown);
	})

	dropDown.slideDown('fast');

}
</pre>
<p>The <strong>showTab</strong> function takes a tab name as a parameter and displays it in the widget, after forming the corresponding <strong>YQL</strong> URL, and fetching it with the <strong>getJSON()</strong> method. After this, the response is looped with <strong>$.each</strong> and the function that was provided in the tab definition is called.</p>
<p>You can additionally switch the active tab from outside the widget code, by calling <strong>showTab()</strong> with a different tab name (and thus creating custom controls for the widget).</p>
<h4>script.js &#8211; Part 3</h4>
<pre class="brush:js">function twitter(item)
{
	/* Formats the tweets, by turning hashtags, mentions an URLS into proper hyperlinks: */

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

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

function formatString(str)
{
	/* This function was taken from our Twitter Ticker tutorial - http://tutorialzine.com/2009/10/jquery-twitter-ticker/ */

	str = str.replace(/&lt;[^&gt;]+&gt;/ig,'');
	str=' '+str;
	str = str.replace(/((ftp|https?):\/\/([-\w\.]+)+(:\d+)?(\/([\w/_\.]*(\?\S+)?)?)?)/gm,'&lt;a href="$1" target="_blank"&gt;$1&lt;/a&gt;');
	str = str.replace(/([^\w])\@([\w\-]+)/gm,'$1@&lt;a href="http://twitter.com/$2" target="_blank"&gt;$2&lt;/a&gt;');
	str = str.replace(/([^\w])\#([\w\-]+)/gm,'$1&lt;a href="http://twitter.com/search?q=%23$2" target="_blank"&gt;#$2&lt;/a&gt;');
	return str;
}
</pre>
<p>In the last part of the code, we have the two functions &#8211; <strong>twitter</strong> and <strong>rss</strong>. These take an object passed from the <strong>$.each</strong> loop in <strong>showTab()</strong> and find their way to the link and title of the feed item, depending on whether it is RSS or ATOM.</p>
<p>You can create your own functions and include them in the <strong>tabs</strong> object. This way you can expand the functionality for feeds that are not limited to text. It is only important that you return the results as a <strong>&#8216;&lt;div&gt;&#8230;.&lt;/div&gt;&#8217;</strong> string.</p>
<p><strong>With this our Sleek Feed Widget is complete!</strong></p>
<h3>To Wrap It Up</h3>
<p>You are free to use and build upon the widget any way you see fit. The code is easy to modify and you can quickly implement all sorts of functionality.</p>
<p>If you liked this tutorial, be sure to <a href="http://twitter.com/Tutorialzine" target="_blank">follow us on twitter</a> for the latest and greatest web dev resources on the web.</p>
<p><strong>What do you think? How would you modify this code?</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://tutorialzine.com/2010/02/feed-widget-jquery-css-yql/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using apc
Page Caching using apc
Object Caching 460/492 objects using apc
Content Delivery Network via cdn.tutorialzine.com

Served from: tutorialzine.com @ 2012-02-08 13:40:50 -->
