<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" 
      xmlns:thr="http://purl.org/syndication/thread/1.0">
  <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/ch-18-consuming-twitter-apis.html" />
  <link rel="self" type="application/atom+xml" href="http://www.insideria.com/atom.xml" />
  <id>tag:www.insideria.com,2009://34/tag:www.insideria.com,2009://34.34955-</id>
  <updated>2009-11-16T15:10:03Z</updated>
  <title>Comments for Developing Mashup Air Apps: Consuming Twitter APIs (http://www.insideria.com/2009/03/ch-18-consuming-twitter-apis.html)</title>
  <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.21-en</generator>
  <entry>
    <id>tag:www.insideria.com,2009://34.34955</id>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/ch-18-consuming-twitter-apis.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://blogs.oreilly.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=34/entry_id=34955" title="Developing Mashup Air Apps: Consuming Twitter APIs" />
    <published>2009-03-24T14:00:19Z</published>
    <updated>2009-06-08T15:57:50Z</updated>
    <title>Developing Mashup Air Apps: Consuming Twitter APIs</title>
    <summary>Excerpted from Chapter 18 of the Adobe AIR 1.5 Cookbook. Mashup applications are based on the possibility of consuming remote data sources, and to create one, you need a good understanding of the APIs available. AIR offers even greater possibilities for creating mashup applications and widgets. With AIR, you can go beyond all the sandbox security of the browser and add advanced features to the application to interact with the file system or local storage with SQLite. This chapter demonstrates how to integrate the Flickr, Yahoo Maps, and Twitter web services to create desktop mashup applications with AIR.</summary>
    <author>
      <name>Marco Casario</name>
      
    </author>
    
    <category term="Features" />
    
    <content type="html" xml:lang="en" xml:base="http://www.insideria.com/">
      <![CDATA[<p><em>This is excerpted from Chapter 18 of the <a href="http://oreilly.com/catalog/9780596522506/" target="_blank">Adobe AIR 1.5 Cookbook</a> by <a href="http://www.oreillynet.com/pub/au/3416">David Tucker</a>, <a href="http://www.oreillynet.com/pub/au/3417">Marco Casario</a>, <a href="http://www.oreillynet.com/pub/au/3427">Koen De Weggheleire</a>, and <a href="http://www.oreillynet.com/pub/au/3426">Rich Tretola</a>. The book includes hands-on recipes to help you solve a variety of tasks and scenarios often encountered when using Adobe AIR to build Rich Internet Applications for the desktop.</em></p>

<div class="ap_r_front" style="width:180px;"><a href="http://oreilly.com/catalog/9780596522506/?CMP=ILC-dm_nav_related-books" target="_blank"><img border="0" src="http://www.oreilly.com/catalog/covers/9780596522506_cat.gif" width="180" height="233" /></a>
<div class="apcaption">Get the <a href="http://oreilly.com/catalog/9780596522506/?CMP=ILC-dm_nav_related-books" target="_blank">Adobe AIR 1.5 Cookbook</a> or download the <a href="http://cachefly.oreilly.com/digitalmedia/9780596522506/9780596522506_bonus_ch18.pdf" target="_blank">PDF</a> of this entire chapter.</div></div>

<h2 class="title" style="clear: both"><a name="consuming_twitter_apis"></a>Consuming Twitter APIs</h2>

<h3 class="title"><a name="id430805"></a>Problem</h3>

<p>You want to access the Twitter APIs web services.</p>

<h3 class="title"><a name="id430812"></a>Solution</h3>

<p>Twitter was born from the simple idea of communicating quickly with friends via brief text messages, but its success also contributed to its transformation, and today the service is also used for commercial purposes to communicate new initiatives, software releases, and much more.</p>

<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>According to Wikipedia, Twitter is a free social networking and microblogging service that allows users to send updates (otherwise known as <span class="emphasis"><em>tweets</em></span>), which are text-based posts of up to 140 characters. Updates are displayed on the user&#8217;s profile page and delivered to other users who have signed up to receive them. The sender can restrict delivery to those in their circle of friends (delivery to everyone being the default). Users can receive updates via the Twitter website, instant messaging, SMS, RSS, or email, as well as through an application such as Twitterrific or Facebook. For SMS, four gateway numbers are currently available: short codes for the United States, Canada, and India, and a United Kingdom number for international use. Several third parties offer the ability to post and receive updates via email.</p></div>

<p>This is a sampling of AIR applications that consume Twitter&#8217;s APIs:</p>

<ul type="disc"><li><p>Twhirl (<a href="http://www.twhirl.org" target="_top">http://www.twhirl.org</a>)</p></li><li><p>Spaz (<a href="http://funkatron.com/spaz" target="_top">http://funkatron.com/spaz</a>); developed using Ajax</p></li><li><p>Snitter (<a href="http://getsnitter.com" target="_top">http://getsnitter.com</a>)</p></li><li><p>Tweetr (<a href="http://www.tweet-r.com" target="_top">http://www.tweet-r.com</a>)</p></li></ul>

<p>This recipe uses Twitter&#8217;s APIs to create a simple AIR application with ActionScript and JavaScript that displays the most recent messages and account details.</p>

<h3 class="title"><a name="id430895"></a>Discussion</h3>

<p>Twitter provides its own set of APIs to consume its web services and create mashups that use its services. This solution will use the simplest approach to consume Twitter&#8217;s APIs, without carrying out the authentication procedure to retrieve information about protected users who aren&#8217;t friends.</p>

<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3>

<p>You can find more information to study Twitter&#8217;s APIs at the following addresses:</p>

<ul type="disc"><li><p><a href="http://apiwiki.twitter.com/Twitter" target="_top">http://apiwiki.twitter.com/Twitter</a>: The API home page</p></li><li><p><a href="http://apiwiki.twitter.com/REST+API+Documentation" target="_top">http://apiwiki.twitter.com/REST+API+Documentation</a>:  API documentation, which is a reference for developers building  tools that talk to Twitter</p></li><li><p><a href="http://groups.google.com/group/twitter-development-talk" target="_top">http://groups.google.com/group/twitter-development-talk</a>:  Twitter Development Talk, where you can talk about your Twitter applications with other developers</p></li><li><p><a href="http://code.google.com/p/twitterscript" target="_top">http://code.google.com/p/twitterscript</a>: <span class="keep-together">An ActionScript 3 library for accessing Twitter APIs. </span></p></li></ul></div>

<h4 class="title"><a name="id430962"></a>ActionScript/Flex</h4>

<p>An open source library that began as a Twitter project, the twitterscript <span class="keep-together">ActionScript 3</span> library (<a href="http://apiwiki.twitter.com" target="_top">http://apiwiki.twitter.com</a>) is a great help when using the Twitter APIs with ActionScript.</p>

<p>It&#8217;s quite easy to use this library. After you download <code>TwitterApi.swc</code> and import it into your Flash or Flex project, you can import and use its classes. For example, the <code>loadUserTimeline</code> method of the <code>Twitter</code> class allows you to load the timeline of a user by assigning it a nickname as a parameter:</p>
 
<a name="I_programlisting18_d1e23918"></a><div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>tw = <span class="category1">new</span> Twitter();
tw.addEventListener(TwitterEvent.ON_USER_TIMELINE_RESULT, loadedUserTimeline );
tw.loadUserTimeline( nick );</pre>
</code>
</div></div>

<p>The <code>nick</code> parameter contains the screen name of the Twitter user. The <code>ON_USER_TIMELINE_RESULT</code> event of the <code>TwitterEvent</code> class is triggered when the list of the timeline of messages is loaded. In the <code>loadedUserTimeline</code> event handler, you can load the messages in a variable, which will then be used as a data provider in the application:</p>
<a name="I_programlisting18_d1e23934"></a><div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre><span class="category1">private</span> <span class="category1">function</span> loadedUserTimeline( evt:TwitterEvent ):<span class="category1">void</span>
{
     <span class="category1">var</span> timeline:<span class="category2">Array</span> = evt.<span class="category2">data</span> as <span class="category2">Array</span>;
 
     <span class="linecomment">// populate messages list dataprovider</span>
     <span class="category1">var</span> twitStatus:TwitterStatus;
     <span class="category1">for</span> each( twitStatus <span class="category1">in</span> timeline )
     {
          _timelineDP.<span class="category2">addItem</span>( twitStatus );
      }
     _logedUserProfile = twitStatus.user;
}</pre>
</code>
</div></div>

<p>The <code>data</code> property of the <code>event</code> object contains an array of timeline messages. With a <code>for...each</code> loop, you can control all the <code>TwitterStatus</code> objects in the timeline messages.</p>

<p>The complete ActionScript class that pulls the latest messages from a Twitter user using a nickname is as follows:</p><a name="I_programlisting18_d1e23952"></a>
<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>package com.oreilly.aircookbook.bonus
{
 
     <span class="category1">import</span> mx.collections.ArrayCollection;
     <span class="category1">import</span> mx.controls.Alert;
 
     <span class="category1">import</span> twitter.api.Twitter;
     <span class="category1">import</span> twitter.api.<span class="category2">data</span>.TwitterStatus;
     <span class="category1">import</span> twitter.api.<span class="category2">data</span>.TwitterUser;
     <span class="category1">import</span> twitter.api.events.TwitterEvent;
 
     <span class="category1">public</span> <span class="category1">class</span> TwitterConn
     {
          <span class="category1">private</span> <span class="category1">var</span> tw:Twitter;
  
          <span class="category1">private</span> <span class="category1">var</span> _userDetails:TwitterUserVO;
          <span class="category1">public</span> <span class="category1">function</span> <span class="category2">get</span> userDetails():TwitterUserVO
          {
           <span class="category1">return</span> _userDetails;
           }
  
          <span class="category1">private</span> <span class="category1">var</span> _logedUserProfile:TwitterUser;
          <span class="category1">public</span> <span class="category1">function</span> <span class="category2">get</span> logedUserProfile():TwitterUser
          {
           <span class="category1">return</span> _logedUserProfile;
           }
          <span class="category1">private</span> <span class="category1">var</span> _timelineDP:ArrayCollection;
  
          <span class="category1">public</span> <span class="category1">function</span> <span class="category2">get</span> timelineDP():ArrayCollection
          {
           <span class="category1">return</span> _timelineDP;
           }
  
  
          <span class="category1">public</span> <span class="category1">function</span> TwitterConn()
          {
           tw = <span class="category1">new</span> Twitter();
           tw.addEventListener( TwitterEvent.ON_USER_TIMELINE_RESULT, loadedUserTimeline );
           _timelineDP = <span class="category1">new</span> ArrayCollection();
           }
  
          <span class="category1">public</span> <span class="category1">function</span> loadUserTimeline( nick:<span class="category2">String</span> ):<span class="category1">void</span>
          {
           <span class="category1">if</span>( nick == "<span class="quote"></span>" )
           <span class="category1">return</span>;
   
           tw.loadUserTimeline( nick );
           }
  
          <span class="linecomment">// called when user timeline is returned from webservices</span>
          <span class="category1">private</span> <span class="category1">function</span> loadedUserTimeline( evt:TwitterEvent ):<span class="category1">void</span>
          {
           <span class="linecomment">// access timeline messages array</span>
           <span class="category1">var</span> timeline:<span class="category2">Array</span> = evt.<span class="category2">data</span> as <span class="category2">Array</span>;
   
           <span class="linecomment">// clear previous messages list contents</span>
           _timelineDP.<span class="category2">removeAll</span>();
   
           <span class="linecomment">// if no timeline found for specified user</span>
           <span class="linecomment">// exit function execution</span>
           <span class="linecomment">// user probably doesn't exists</span>
           <span class="category1">if</span>(timeline == <span class="category1">null</span> || timeline.<span class="category2">length</span> == 0 )
           {
            <span class="category1">return</span>;
            }
   
           <span class="category1">var</span> twitStatus:TwitterStatus;
           <span class="category1">for</span> each( twitStatus <span class="category1">in</span> timeline )
           {
            _timelineDP.<span class="category2">addItem</span>( twitStatus );
            }
   
           _logedUserProfile = twitStatus.user;
   
           _userDetails = <span class="category1">new</span> TwitterUserVO();
   
           _userDetails.source = logedUserProfile.profileImageUrl;
           _userDetails.<span class="category2">name</span> = logedUserProfile.<span class="category2">name</span>;
           _userDetails.screenName = logedUserProfile.screenName;
           _userDetails.location = logedUserProfile.location;
           _userDetails.<span class="category2">url</span> = logedUserProfile.<span class="category2">url</span>;
           _userDetails.description = logedUserProfile.description;
   
           }
      }
}</pre>
</code>
</div></div>

<p>The class creates the instance of the <code>Twitter</code> class in the constructor and creates an event listener for the <code>TwitterEvent.ON_USER_TIMELINE_RESULT</code> event.</p>

<p>In the <code>loadedUserTimeline</code> event handler, called when a response user timeline is returned from web services, you check whether there is a timeline of messages for the specific screen name that was passed to the function; if a timeline doesn&#8217;t exist, the function will exit. This check is carried out by verifying whether the <code>timeline.length</code> property is different from zero.</p>

<p>In the <code>userDetails</code> property, an ActionScript <code>Value</code> object is instanced and saved as <code>TwitterUserVO.as</code>, a simple class that transports data, to which you assign the properties contained in the <code>TwitterStatus</code> class and in its <code>user: twitStatus.user</code> property. This information belongs to the user for which you loaded the message timeline. The <span class="keep-together">ActionScript</span> <code>Value</code> object <code>TwitterUserVO.as</code> simply contains a list of properties:</p>

<a name="I_programlisting18_d1e23998"></a><div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>package com.oreilly.aircookbook.ch16
{
     [Bindable]
     <span class="category1">public</span> <span class="category1">class</span> TwitterUserVO
     {
  
          <span class="category1">public</span> <span class="category1">var</span> source:<span class="category2">String</span>;
          <span class="category1">public</span> <span class="category1">var</span> <span class="category2">name</span>:<span class="category2">String</span>;
          <span class="category1">public</span> <span class="category1">var</span> location:<span class="category2">String</span>;
          <span class="category1">public</span> <span class="category1">var</span> <span class="category2">url</span>:<span class="category2">String</span>;
          <span class="category1">public</span> <span class="category1">var</span> description:<span class="category2">String</span>;
          <span class="category1">public</span> <span class="category1">var</span> screenName:<span class="category2">String</span>;
  
          <span class="category1">public</span> <span class="category1">function</span> TwitterUserVO()
          {
           }
          }
}</pre>
</code>
</div></div>

<p>For the sake of brevity, in this <code>Value</code> object the properties have been declared as public. To follow object programming best practices, you should encapsulate the properties of a class to make it more secure and declare the properties as private so they can be exposed and be get and set with the public getter/setter methods.</p>

<p>The AIR application that defines the user interface elements is as follows:</p>

<a name="I_programlisting18_d1e24007"></a><div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>&lt;?xml <span class="category2">version</span>="<span class="quote">1.0</span>" encoding="<span class="quote">utf-8</span>"?&gt;
&lt;mx:WindowedApplication
xmlns:mx="<span class="quote">http://www.adobe.com/2006/mxml</span>"
 <span class="category2">width</span>="<span class="quote">550</span>"&gt;

&lt;mx:Script&gt;
&lt;![CDATA[
    <span class="category1">import</span> mx.core.IFlexDisplayObject;
    <span class="category1">import</span> com.oreilly.aircookbook.bonus.TwitterConn;
    <span class="category1">import</span> com.oreilly.aircookbook.bonus.TwitterAuthor;
    <span class="category1">import</span> mx.managers.PopUpManager;

    [Bindable]
    <span class="category1">private</span> <span class="category1">var</span> twclass:TwitterConn = <span class="category1">new</span> TwitterConn();


    <span class="category1">private</span> <span class="category1">function</span> showDetails():<span class="category1">void</span>
    {
        <span class="category1">var</span> myPopUp:IFlexDisplayObject = PopUpManager.createPopUp (<span class="category1">this</span>,
     TwitterAuthor, <span class="category1">true</span>);
         TwitterAuthor( myPopUp ).twitterDetails = twclass.userDetails;
         PopUpManager.centerPopUp( myPopUp );
     }

]]&gt;
&lt;/mx:Script&gt;

&lt;mx:HBox&gt;
&lt;mx:Label <span class="category2">text</span>="<span class="quote">Insert your Twitter username: </span>" /&gt;
&lt;mx:TextInput id="<span class="quote">userTxt</span>" /&gt;

&lt;mx:<span class="category2">Button</span> id="<span class="quote">userBtn</span>"
<span class="category1">label</span>="<span class="quote">Read latest message</span>"
click="<span class="quote">twclass.loadUserTimeline(userTxt.text);authorBtn.visible = true</span>" /&gt;

&lt;/mx:HBox&gt;

&lt;mx:List dataProvider="<span class="quote">{twclass.timelineDP}</span>"
labelField="<span class="quote">text</span>"  <span class="category2">width</span>="<span class="quote">496</span>" <span class="category2">height</span>="<span class="quote">166</span>"/&gt;

&lt;mx:LinkButton id="<span class="quote">authorBtn</span>" <span class="category2">visible</span>="<span class="quote">false</span>" <span class="category1">label</span>="<span class="quote">See Twitter Account Details</span>" 
click="<span class="quote">showDetails()</span>" /&gt;

&lt;/mx:WindowedApplication&gt;</pre>
</code>
</div></div>


<p>The application has a <code>TextInput</code> control and a <code>Button</code> control that allow the users to insert their Twitter nicknames and download their timeline message lists. This list of messages is associated as a data provider to a <code>List</code> control through the <code>timelineDP</code> property of the ActionScript class that you created previously: <code>dataProvider="{twclass.timelineDP}"</code>.</p>

<p>Finally, a <code>LinkButton</code> control allows you to open a pop-up window, controlled by the <code>PopUpManager</code> class, to which you pass the ActionScript <code>Value</code> object in the <code>userDetails</code>
 property:</p>
 
 <a name="I_programlisting18_d1e24042"></a><div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre><span class="category1">private</span> <span class="category1">function</span> showDetails():<span class="category1">void</span>
{
     <span class="category1">var</span> myPopUp:IFlexDisplayObject = PopUpManager.createPopUp (<span class="category1">this</span>, TwitterAuthor, <span class="category1">true</span>);
     TwitterAuthor( myPopUp ).twitterDetails = twclass.userDetails;
     PopUpManager.centerPopUp( myPopUp );
}</pre>
</code>
</div></div>

<p>The second parameter that is passed to the <code>createPopUp</code> method of the <code>PopUpManager</code> class is an MXML component saved as <code>TwitterAuthor.mxml</code>. This component will be a <span class="keep-together">subclass</span> of the <code>TitleWindow</code> class, will take the <code>Value</code> object as a parameter, and will print its properties in the Flex controls:</p><a name="I_programlisting18_d1e24065"></a><div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>&lt;?xml <span class="category2">version</span>="<span class="quote">1.0</span>"  encoding="<span class="quote">utf-8</span>"?&gt;

&lt;mx:TitleWindow  xmlns:mx="<span class="quote">http://www.adobe.com/2006/mxml</span>"
layout="<span class="quote">absolute</span>"  title="<span class="quote">Twitter Account Details</span>"
<span class="category2">width</span>="<span class="quote">320</span>" <span class="category2">height</span>="<span class="quote">240</span>"
showCloseButton="<span class="quote">true</span>"
borderAlpha="<span class="quote">1.0</span>"
creationComplete="<span class="quote">addEventListener( CloseEvent.CLOSE, closeMe );</span>"&gt;

&lt;mx:Script&gt;
&lt;![CDATA[
    <span class="category1">import</span> mx.managers.PopUpManager;
    <span class="category1">import</span> mx.events.CloseEvent;
    <span class="category1">import</span> com.oreilly.aircookbook.bonus.TwitterUserVO;

    [Bindable]
    <span class="category1">public</span> <span class="category1">var</span> twitterDetails:TwitterUserVO;
    <span class="category1">private</span> <span class="category1">function</span> closeMe( event:CloseEvent ):<span class="category1">void</span>
    {
         PopUpManager.removePopUp( <span class="category1">this</span> );
     }
]]&gt;
&lt;/mx:Script&gt;
&lt;mx:Image source="<span class="quote">{twitterDetails.source}</span>"  <span class="category2">x</span>="<span class="quote">10</span>" <span class="category2">y</span>="<span class="quote">12</span>"/&gt;
&lt;mx:Label <span class="category2">x</span>="<span class="quote">91</span>" <span class="category2">y</span>="<span class="quote">10</span>" <span class="category2">text</span>="<span class="quote">{twitterDetails.name}</span>" /&gt;
&lt;mx:Label <span class="category2">x</span>="<span class="quote">89</span>" <span class="category2">y</span>="<span class="quote">36</span>" <span class="category2">text</span>="<span class="quote">{twitterDetails.screenName}</span>" /&gt;
&lt;mx:Label <span class="category2">x</span>="<span class="quote">89</span>" <span class="category2">y</span>="<span class="quote">62</span>" <span class="category2">text</span>="<span class="quote">{twitterDetails.url}</span>" /&gt;

&lt;mx:Label <span class="category2">x</span>="<span class="quote">89</span>" <span class="category2">y</span>="<span class="quote">88</span>" <span class="category2">text</span>="<span class="quote">{twitterDetails.location}</span>" /&gt;
&lt;mx:TextArea <span class="category2">x</span>="<span class="quote">90</span>" <span class="category2">y</span>="<span class="quote">114</span>" <span class="category2">text</span>="<span class="quote">{twitterDetails.description}</span>" /&gt;
&lt;/mx:TitleWindow&gt;</pre>
</code>
</div></div>

<h4 class="title"><a name="id431573"></a>JavaScript/HTML</h4>

<p>For JavaScript, the TwitterJs library allows you to obtain a list of messages in your own web page. Created by remy sharp (<a href="http://remysharp.com" target="_top">http://remysharp.com</a>), the TwitterJs library is available at <a href="http://code.google.com/p/twitterjs/downloads/list" target="_top">http://code.google.com/p/twitterjs/downloads/list</a>.</p>

<p>Download the zip file, extract it directly in the project folder, and import the file <code class="filename">twitterjs/src/twitter.js</code>.</p>

<p>The <code>getTwitters</code> method returns a list of messages. The parameters you can pass are as follows:</p>

<ul type="disc"><li><p><code>id</code> (String): This is the username.</p></li><li><p><code>count</code> (Int): This can be 1&#8211;20, and it defaults to 1. The maximum limit is 20.</p></li><li><p><code>prefix</code> (String): This is in the format <code>'%name% said'</code>. It defaults to blank.</p></li><li><p><code>clearContents</code> (Boolean): This removes the contents of the element specified in <code>cssIdOfContainer</code>; it defaults to <code>true</code>.</p></li><li><p><code>ignoreReplies</code> (Boolean): This skips over tweets starting with <code>@</code>, and it defaults to <code>false</code>.</p></li><li><p><code>template</code> (String): This is the HTML template to use for <code>li</code> elements. This defaults to a predefined template.</p></li><li><p><code>enableLinks</code> (Boolean): This &#8220;linkifies&#8221; the text, and it defaults to <code>true</code>.</p></li><li><p><code>timeout</code> (Int): This is how long before triggering <code>onTimeout</code>. It defaults to 10 seconds if <code>onTimeout</code> is set.</p></li>
<li><p><code>onTimeoutCancel</code> (Boolean): This completely cancels the Twitter call if it times out. It defaults to <code>false</code>.</p></li><li><p><code>onTimeout</code> (Function): This is the function to run when the timeout occurs. This function is bound to the element specified with it.</p></li></ul>


<p>The example in AIR uses the same approach as the previous solution. One web page incorporates a second web page through an <code>iframe</code> container, which carries out the JavaScript call to the Twitter APIs.</p>

<p>This is the code of the parent web page:</p><a name="I_programlisting18_d1e24174"></a><div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>&lt;!DOCTYPE <span class="category2">html</span> PUBLIC "<span class="quote">-//W3C//DTD XHTML 1.0 Transitional//EN</span>" 
"<span class="quote">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</span>"&gt;

&lt;<span class="category2">html</span> xmlns="<span class="quote">http://www.w3.org/1999/xhtml</span>"&gt;
&lt;head&gt;

&lt;script <span class="category2">type</span>="<span class="quote">text/javascript</span>" src="<span class="quote">frameworks/AIRAliases.js</span>" /&gt;
&lt;script <span class="category2">type</span>="<span class="quote">text/javascript</span>" src="<span class="quote">frameworks/AIRIntrospector.js</span>" /&gt;


&lt;meta http-equiv="<span class="quote">Content-Type</span>" content="<span class="quote">text/html; charset=utf-8</span>" /&gt;

&lt;title&gt;AIR Cookbook: 18.3 Consuming Twitter APIs (JavaScript)&lt;/title&gt;

&lt;/head&gt;

&lt;body&gt;
&lt;h1&gt;AIR Cookbook: 18.3 Consuming Twitter APIs (JavaScript)&lt;/h1&gt;


&lt;iframe
id="<span class="quote">twitter</span>"
src="<span class="quote">tweetrIframe.html</span>"
sandboxRoot="<span class="quote">http://SomeRemoteDomain.com/</span>"
documentRoot="<span class="quote">app:/</span>" <span class="category2">width</span>="<span class="quote">500</span>" <span class="category2">height</span>="<span class="quote">500</span>"
/&gt;

&lt;/body&gt;
&lt;/<span class="category2">html</span>&gt;</pre>
</code>
</div></div>

<p>The core of the application is in the <code class="filename">tweetrIframe.html</code> page that is loaded in the <code>iframe</code>. In this web page, after importing the TwitterJs library, call the <code>getTwitters</code> method, which will return the message timeline.</p>

<p>This is the complete code:</p><a name="I_programlisting18_d1e24189"></a><div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;">
<code language="perl">
<pre>&lt;!DOCTYPE <span class="category2">html</span> PUBLIC "<span class="quote">-//W3C//DTD XHTML 1.0 Strict//EN</span>"
  "<span class="quote">http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd</span>"&gt;

&lt;<span class="category2">html</span> lang="<span class="quote">en</span>"&gt;
&lt;head&gt;
&lt;meta http-equiv="<span class="quote">Content-type</span>" content="<span class="quote">text/html; charset=utf-8</span>" /&gt;
 &lt;title&gt;Twitter Plugin&lt;/title&gt;
&lt;link rel="<span class="quote">stylesheet</span>" href="<span class="quote">twitterjs/test/twitter.css</span>" <span class="category2">type</span>="<span class="quote">text/css</span>" media="<span class="quote">screen</span>" 
charset="<span class="quote">utf-8</span>" /&gt;

&lt;script src="<span class="quote">twitterjs/src/twitter.js</span>" <span class="category2">type</span>="<span class="quote">text/javascript</span>" charset="<span class="quote">utf-8</span>"&gt;&lt;/script&gt;

&lt;script <span class="category2">type</span>="<span class="quote">text/javascript</span>" charset="<span class="quote">utf-8</span>"&gt;

<span class="category1">var</span> twitter_id = '<span class="quote">765942</span>';

<span class="category1">function</span> loadMsg()
{
 
 <span class="category1">var</span> nick = document.getElementById( '<span class="quote">location</span>' ).value;
 
 <span class="category1">if</span> (nick == '<span class="quote">Insert your Twitter nickname</span>' || nick == '<span class="quote"></span>') { nick = '<span class="quote">marcocasario</span>'}
 
 getTwitters('<span class="quote">msg</span>', {
  id: nick,
  prefix: '<span class="quote">&lt;img height="16" width="16" src="%profile_image_url%" /&gt;
  &lt;a href="http://twitter.com/%screen_name%"&gt;%name%&lt;/a&gt; said: </span>',
  clearContents: <span class="category1">false</span>, <span class="linecomment">// leave the original message in place</span>
  count: 10,
  withFriends: <span class="category1">true</span>,
  ignoreReplies: <span class="category1">false</span>,
  template: '<span class="quote">&lt;span class="twitterPrefix"&gt;&lt;img height="16" width="16" 
  src="%user_profile_image_url%" /&gt; 
  &lt;span class="twitterStatus"&gt;"%text%"&lt;/span&gt; &lt;em class="twitterTime"&gt;
  
  &lt;a href="http://twitter.com/%user_screen_name%/statuses/%id%"&gt;%time%&lt;/a&gt;&lt;/em&gt;</span>'
      });
}
&lt;/script&gt;
  &lt;/head&gt;
  &lt;body id="<span class="quote">page</span>"&gt;

 &lt;<span class="category2">input</span> id="<span class="quote">location</span>" <span class="category2">type</span>="<span class="quote">text</span>" value="<span class="quote">Insert your Twitter nickname</span>" /&gt;

&lt;<span class="category2">input</span> <span class="category2">type</span>="<span class="quote">submit</span>" <span class="category2">name</span>="<span class="quote">go</span>" id="<span class="quote">go</span>" value="<span class="quote">Show Tweets</span>" onclick="<span class="quote">loadMsg()</span>" /&gt;

&lt;div <span class="category1">class</span>="<span class="quote">twitters</span>" id="<span class="quote">msg</span>"&gt;
&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;/<span class="category2">html</span>&gt;</pre>
</code>
</div></div>

<p>The page displays a text input where users can insert their screen names used in Twitter and a button that, once it is clicked, invokes the <code>loadMsg</code> function. This function takes the value in the text input and, in turn, launches the <code>getTwitters</code> method from the TwitterJs library. This method, according to the parameters that are specified for it, returns the message timeline for the Twitter user who is specified in the text input. If the text input is left empty, the default nickname is marcocasario (my personal <span class="keep-together">nickname</span>).</p>

<div style="width:520px; overflow: auto; padding: 10px 15px; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; margin-bottom: 15px;"><a href="http://oreilly.com/catalog/9780596522506/?CMP=ILC-dm_nav_related-books" target="_blank"><img border="0" style="float: right;" src="http://www.oreilly.com/catalog/covers/9780596522506_thumb.gif" /></a>
<p><strong>Skip to another section of the Adobe AIR 1.5 Cookbook, Chapter 18, Developing Mashup AIR Applications:</strong><br /><a href="http://insideria.com/2009/03/ch-18-yahoo-maps-web-services.html">Consuming Yahoo Maps Web Services</a> | <a href="http://insideria.com/2009/03/ch-18-ch-18-consuming-flickr-web-services.html">Consuming Flickr Web Services</a></p>

<p><strong>Go to the <a href="http://oreilly.com/catalog/9780596522506/?CMP=ILC-dm_nav_related-books" target="_blank">catalog page</a> for the Adobe AIR 1.5 Cookbook. Download the <a href="http://cachefly.oreilly.com/digitalmedia/9780596522506/9780596522506_bonus_ch18.pdf" target="_blank">PDF</a> of this entire chapter. <a href="http://oreilly.com/catalog/9780596522506/toc.html" target="_blank">View</a> the book's table of contents.</strong></p></div>

<p><a href="http://www.insideria.com/david-tucker/">Read more from 
David Tucker</a>.
<span class="stay-connected" style="padding: 0px; float: none;">
<a href="http://www.insideria.com/david-tucker/atom.xml" onmouseover="showIconLabel(this);" onmouseout="hideIconLabel();">
<img src="http://www.insideria.com/riaimages/rss_icon.png" alt="David Tucker's Atom feed" title=""/></a></span></p>

<p><a href="http://www.insideria.com/rich-tretola/">Read more from 
Rich Tretola</a>.
<span class="stay-connected" style="padding: 0px; float: none;">
<a href="http://www.insideria.com/rich-tretola/atom.xml" onmouseover="showIconLabel(this);" onmouseout="hideIconLabel();">
<img src="http://www.insideria.com/riaimages/rss_icon.png" alt="Rich Tretola's Atom feed" title=""/></a> 
<a href="http://twitter.com/richtretola" onmouseover="showIconLabel(this);"  onmouseout="hideIconLabel();">
<img src="http://www.insideria.com/riaimages/icon_twitter.gif" alt="richtretola on Twitter" title=""/></a>					
</span></p>
]]>
      
    </content>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34955-comment:2066414</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34955" type="text/html" href="http://www.insideria.com/2009/03/ch-18-consuming-twitter-apis.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/ch-18-consuming-twitter-apis.html#comment-2066414" />
    <title>Comment from Daniel Phillips on 2009-06-18</title>
    <author>
        <name>Daniel Phillips</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>this is the worst article I ahve come across, I just hope and pray that this does not represent a real excerpt from the book, first of all the proposed html and script for HTML / Javascript AIR application doesn't work, and to even get to a point to realize it doesn't work you have to clean up the terrible html,  tags invalid,  tag not closed it's a joke...</p>

<p>gravely disappointing </p>]]>
    </content>
    <published>2009-06-18T11:23:32Z</published>
  </entry>

</feed
