Tutorial: Twitter Updates in Flash Part 2

Our first tutorial, Pull Twitter Updates into Flash, got us a bit of attention. So rather than write an entirely new tutorial, we thought we’d beat a dead horse a little and re-hash some of the same material.

Fwitter

We’re even using the same Fwitter logo. Classy.

This tutorial builds on the last one, and helps us solve an important problem. Untold Entertainment member and friend of the site MichaelJW pointed out last time around that Twitter only allows you to make 100 calls per hour for a given user name. If you’re fabulously swamped with oodles of traffic, or you’re like me, suffering from delusions that you will one day be fabulously swamped with oodles of traffic, then this is a problem. Fortunately, MichaelJW has the solution: simply write to Twitter and ask to be whitelisted, so that you can make all the calls you want!

In short order, you’ll receive this letter from Twitter:

From: Twitter
Subject: Your Request for Twitter API whitelisting has been rejected

Hi Ryan Creighton,
Thanks for requesting to be on Twitter’s API whitelist. Unfortunately, we’ve rejected your request.
Here’s why:
Please investigate other strategies to stay within our rate limits: http://apiwiki.twitter.com/FAQ#HowdoInbspkeepfromrunningintotheratelimit
Please address the issues above and submit another request if appropriate.
The Twitter API Team

CrapDAMMIT. That means we’re actually going to have to do some work to overcome this problem. Aww … i hate things that are hard.

Cold Hard Cache

i don’t know what you’re up to,but i thought this Twitter module idea was pretty cool, so i stuck it at the top of my website in the global nav. That means that every time the page is refreshed, we hit Twitter for a new copy of the tweets. Also, God kills a kitten or whatever. So that’s not being a very good netizen. Why hammer Twitter with more requests than necessary when we can spend hours of our own time writing a caching script to solve the problem? Am i right?

So here’s what we’re gonna do, in pseudocode:

  1. When we load up the module, let’s check the user’s Flash cookie to see if we’ve saved any Twitter data
  2. If the cookie is empty, we’ll hit the Twitter servers and grab new data. Then we’ll save that data for next time.
  3. We’ll add a time stamp to the Flash cookie so we know how long it’s been since we grabbed fresh data from Twitter.
  4. If there IS Twitter data in the cookie, let’s look at how old it is
  5. If it’s still fresh, there’s no need to hit Twitter. We’ll just display that data.
  6. If it’s old data, let’s hit Twitter and get a new copy.

(note throughout the tutorial and the code, i use the vernacular “Flash cookie”. The proper term is “shared object”, but it’s a lot harder to remember what the thing does when you call it that.)

How do we know what constitutes “old” data? It’s right there in the code. You can set the number of hours, minutes and seconds it takes for the data to expire. i think setting the expiry to 1 hour is pretty reasonable, but feel free to be as unreasonable as you like with this value. It’s your Twitter funeral.

Here comes the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package
{
	/**********************************************
	 * 
	 *  This fun Twitter widget is brough to you
	 *  by Untold Entertainment Inc, and 
	 *  peanut butter!  Peanut butter: a gooey,
	 *  yummy snack that might kill you.
	 * 
	 *  http://www.untoldentertainment.com
	 * 
	 **********************************************/
 
	// Here are all the goodies you're going to need 
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.events.Event;
	import flash.events.NetStatusEvent;
	import flash.net.SharedObject;
 	import flash.net.SharedObjectFlushStatus;	
 
	public class Main extends MovieClip
	{
		private var twitterXML:XML; // This holds the xml data
		private var cachedTwitterData:SharedObject; // This stores the data loaded from the Flash cookie
		private var twitterPHPScriptPath:String;
		private var myTwitterID:String;
		private var wereAllowedToWriteToTheFlashCookie:Boolean; // You can use this value to decide whether or not to make repeated save attempts
 
		public function Main()
		{
			// Put your Twitter username here.  For example, ours is "untoldEnt" :
			myTwitterID = "myTwitterID"; 
 
			// Put the path to your php script here:
			twitterPHPScriptPath = "http://www.yourdomain.com/thePathToYourPHPScript";
 
			wereAllowedToWriteToTheFlashCookie = true; // (let's be optimistic until we discover otherwise) 
 
			// Check to see if the user has already retrieved the Twitter updates and stored them in a Flash cookie:
			loadTwitterDataFromFlashCookie();
		}
 
		private function loadTwitterDataFromFlashCookie():void
		{
			// Call up the Twitter data from the Flash cookie on the user's machine:
			cachedTwitterData = SharedObject.getLocal("twitter");
 
			var timeStamp:Date = cachedTwitterData.data.timeStamp;
 
			if (timeStamp != null)
			{
				// The timeStamp variable is in there, which means we've retrieved Twitter info for this user at some point.
 
				// Now let's check the timeStamp. If the last time we grabbed Twitter data was too long ago, let's grab fresh info:
				if (hasExpired(timeStamp))
				{
					// The most recent copy of the Twitter data in the Flash cookie is old!  Let's get some fresh data:
					trace("cookie has expired!  let's get some fresh data");
					loadTwitterXML();		
				} else {
					// It hasn't been very long since we grabbed a fresh copy of the Twitter data. Let's just use what we've got in the Flash cookie:
					trace("cookie is fresh. display the data.");
					twitterXML = cachedTwitterData.data.twitterXML;
					showTwitterStatus();
				}
			} else {
				// If there's no timeStamp variable in there, then the cookie's empty.  We need to hit Twitter to grab our data for the first time.
				loadTwitterXML();				
			}			
		}
 
		private function saveTwitterDataToFlashCookie():void
		{
 
			// This bit tries to write something to the user's Flash cookie. Depending on the user's Flash cookie
			// settings, we may need to ask the user permission before we write to the cookie.  We'll test
			// the water by trying to write something to the cookie:
            var flushStatus:String = null;
            try
			{
                flushStatus = cachedTwitterData.flush(10000);
            } catch (error:Error) {
                trace("Error...Could not write SharedObject to disk\n");
            }
			// If we were able to write to the Flash cookie, let's see if the user was prompted to allow us or not:
            if (flushStatus != null)
			{
                switch (flushStatus)
				{
					// The user is only allowing us to write a very small amount of data to the Flash cookie, and has asked
					// Flash to prompt him so that he can give permission to write something larger.  Let's wait until the
					// user clicks to give that permission:
                    case SharedObjectFlushStatus.PENDING:
                        trace("Requesting permission to save object...\n");
                        cachedTwitterData.addEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
                        break;
					// We're home-free: we can write to the cookie, and the amount of data is small enough to fly under the
					// user's Flash cookie permission radar.  Let's write some data!
                    case SharedObjectFlushStatus.FLUSHED:
                        //trace("Value flushed to disk.\n");
						trace("********* save complete. ***********\n");
						finishedHandlingTwitterData();
                        break;
                }
            }				
		}
 
		private function onFlushStatus(e:NetStatusEvent):void
		{
            trace("User closed permission dialog...\n");
            switch (e.info.code)
			{
                case "SharedObject.Flush.Success":
                    trace("User granted permission -- value saved.\n");
					finishedHandlingTwitterData();
                    break;
				// Dammit!  In this case, the user freaked out and won't let us write anything to his Flash cookie.
				// We'll have to hit Twitter every single time solely for this user's benefit.
                case "SharedObject.Flush.Failed":
                    trace("User denied permission -- value not saved.\n");
					wereAllowedToWriteToTheFlashCookie = false;
                    break;
            }
 
            cachedTwitterData.removeEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
        }	
 
		private function finishedHandlingTwitterData(e:Event = null):void
		{
			trace("Twitter data saved.");
		}
 
		private function hasExpired(timeStamp:Date):Boolean
		{
			// Store the date RIGHT NOW, to compare against the Flash cookie timeStamp:
			var now:Date = new Date();
 
			// Let's say that the cookie expires after 1 hour, 0 minutes and zero seconds:
			var expiryHours:Number = 1;
			var expiryMinutes:Number = 0;
			var expirySeconds:Number = 0;
 
			// Store some handy conversion values:
			var msPerHour:Number = 3600000;
			var msPerMinute:Number = 60000;
			var msPerSecond:Number = 1000;
 
			// Multiply those values to get the expiry time in milliseconds:
			var expiryTime:Number = (expiryHours * msPerHour) + (expiryMinutes * msPerMinute) + (expirySeconds * msPerSecond);
 
			// Return whether or not the timeStamp is past the expiry date:
			return (now.getTime() - timeStamp.getTime() > expiryTime)
		}
 
		private function loadTwitterXML():void
		{
			var urlLoader:URLLoader = new URLLoader();
			// When all the junk has been pulled in from the url, we'll fire finishedLoadingXML:
			urlLoader.addEventListener(Event.COMPLETE, finishLoadingXML);
			urlLoader.load(new URLRequest(twitterPHPScriptPath + "?twitterId=" + myTwitterID));			
		}
 
		private function finishLoadingXML(e:Event = null):void
		{
			// All the junk has been pulled in from the xml!  Hooray!
			// Remove the eventListener as a bit of housecleaning:
			e.target.removeEventListener(Event.COMPLETE, finishLoadingXML);
 
			// Populate the xml object with the xml data:
			twitterXML = new XML(e.target.data);
 
 
			cachedTwitterData = SharedObject.getLocal("twitter");
 
			// Set the date/time RIGHT NOW:
			cachedTwitterData.data.timeStamp = new Date();
			// Store the twitterXML data:
			cachedTwitterData.data.twitterXML = twitterXML;	
			// (Try to) save the whole shebang the user's Flash cookie: 
			saveTwitterDataToFlashCookie();
 
			showTwitterStatus();
		}
 
		private function showTwitterStatus():void
		{
			trace("showTwitterStatus");
			// Uncomment these lines if you want to see all the fun stuff Twitter sends you:
			//trace(twitterXML);
			//trace(twitterXML.head);
 
			// Prep the text field to hold our latest Twitter update:
			twitter_txt.wordWrap = true;
			twitter_txt.autoSize = TextFieldAutoSize.LEFT;
 
			// Populate the text field with the first element in the status.text nodes:
			twitter_txt.htmlText = twitterXML.status.text[0];
		}
	}
}

This is just a modified version of the code we used last time, with the caching stuff added in. It’s very well commented. If you’re new to the concept of Flash cookies, take a careful read-through and make yourself smart.

I Did it All for the Cookie

Cookie Monster

Now DAT a lot of code.

i added one flag to the code called wereAllowedToWriteToTheFlashCookie. Time was, no one knew about Flash cookies, and you could get away with murder. Nowadays, some folks are wise to the fact that Flash can store stuff to their computers, and they’re blocking access, or cranking the permission slider down so that barely any data can be stored to their computers. If this is the case, and you try to store a Flash cookie, a dialogue box will pop up and ask the user to authorize the cookie-writing procedure. If the player says “no”, we’re flagging the wereAllowedToWriteToTheFlashCookie to false.

This tutorial doesn’t really make any further use of that value. But if you check out our super-deluxe version of this module at the top of the Untold Entertainment site, you’ll notice we added paging controls so that users can flip through the last twenty Twitter messages, and an auto-refresh countdown that displays the next tweet automatically. One of the things i noticed was that if you move around the site quickly, the bird keeps tweeting the most recent post. That’s kind of boring.

What i’d like to do (which i may have already done, depending on when you read this), is to save the currentTweet number every time it changes. That way, when the page refreshes, i can retrieve the currentTweet number from the Flash cookie and pick up where i left off. BUT if the user isn’t allowing Flash cookies, he’s gonna see that “Allow?” dialogue pop up every time i try to save the currentTweet number. And that stinks. That guy’s not likely to pay a repeat visit.

So i’ll check the wereAllowedToWriteToTheFlashCookie flag before i try to save anything else to the Flash cookie.

And by then, the Twitter module on our site will be just about as awesomazing as possible.

Making it Work

If this is your first time with these Twitter tutorials, you might make some mistakes. And then you might blame those mistakes on us. Rest assured, the code works. You’re probably doing something silly. Make sure you test this on a web server, because the Flash IDE lies to you, and generally won’t tell you when there’s a securty sandbox issue. Please check the comments at the bottom of these posts to make sure you’re not making the same mistake that someone else has made before you. We’re not that great at troubleshooting this stuff, because we’re usually too busy chasing after the next shiny object to pay proper attention to you. When in doubt, use the boards to discuss. By signing up on our boards, you get the added benefit of being awesome.

You can download the source code for this tutorial here:

cachedTwitterUpdatesInFlash.zip

For more Flash AS3 Tutorials and a pile of other useful stuff, check out our Flash and Actionscript 911 feature.

64 thoughts on “Tutorial: Twitter Updates in Flash Part 2

  1. Michael

    Thanks for the namedrop! That’s harsh of Twitter to just leave a blank space for the reason (or did you just cut that out?)

    Anyway, brilliant tutorial. I love your idea of storing all that info in the sha–Flash cookie, and all the benefits that come with it. I’d never thought of that.

    Reply
  2. Ryan

    Thanks Michael! You’re right – no explanation from Twitter. Just a link to optimization suggestions. i honestly can’t say i blame them, though. But in ten years, we’ll be on a Trivial Pursuit card: “Which monolithic entertainment company did Twitter once reject for whitelisting?”

    Hahahaha. Delusions of grandeur.

    Reply
  3. dan

    i can’t for the life of me link the php up to the flash. i’m learning as3 but have never done anything with flash and php. i’m sure i’m just missing something really easy with how to create the php file or the file path in flash, but either way i’m stuck. is it possible to see yours was set up with the php before you put in the place holders? thanks in advance!

    Reply
    1. Ryan

      The trick there is that if i tell you the path to my php file, anyone can hit my script with their info, and that’s no fun for us.

      It’s not too tough. In your ftp program, create a new folder. Let’s say “scripts”. So the path to that folder is http://www.yourdomain.com/scripts. Then, create your php file and drop it into that folder. Now the path to the php file is http://www.yourdomain.com/scripts/myPHPfile.php. That’s not too tricky, is it?

      Just make sure that the swf file that calls the php is also within the directory structure at http://www.yourdomain.com, or you’ll get security sandbox errors like the other folks here.

      Reply
  4. dan

    that is no fun for you, no fun indeed. well, apparently i did have the located in the right place and with the right path in flash, but i get this dandy message:

    TypeError: Error #1088: The markup in the document following the root element must be well-formed.

    apparently me and flash disagree on our definition of ‘well-formed’ and i pulled it from the first tutorial.
    any suggestions?

    Reply
  5. PB

    thats great that you are talking about the twitter api,a good example of searching with the twitter api is on twiogle.com because you can search on twitter and google at the same time.

    Reply
  6. Travis

    Ryan, I have been messing with this for sometime now and am still stumped!

    My Flash file just sits at “Loading…”

    I have tested that the PHP file is working by directing my web browser to: http://www.parisisrestaurant.com/tscriptphp/parisitwitter.php?twitterId=TrattoriaParisi

    This returns a twitter feed, so it must not be my PHP file.

    I have edited the code to include my ID: var myTwitterID:String = “TrattoriaParisi”;
    And edited to include the PHP location: var twitterPHPScriptPath:String = “http://www.parisisrestaurant.com/tscriptphp/parisitwitter.php”;

    I save the file and upload them to the directory and it just sits there…. what am I doing wrong?!?! Please help!

    -Travis

    Reply
    1. Ryan

      The problem is likely a) little and b) dumb. Is your Flash Player updated to the latest version? Consider using DeMonster Debugger to fire out trace actions that’ll tell you what’s going on with swfs playing in the browser:

      http://demonsterdebugger.com/

      Reply
  7. Travis

    You are right, it must be something small and stupid. And I think it is with the PHP call in the AS script.

    I tryed using that application but with no avail. The funny thing is that when I use the code from tutorial 1 (from the website not the source file (the code is different between these two)) it populates twitter in the flash file on my local computer but not on my web server. I am pretty sure this is because the code listed on tutorial 1 makes no call to a PHP file. When I use the code in tutorial 1 from the source file (the one that makes a call to the PHP file) it no longer works.

    Since I was able to make a call to my PHP file and get a return through the web browser, then this tells me that there must be a problem with the call from the AS file to the PHP file. However, I literally copied and pasted the same PHP link that works in my browser to the AS file but with no avail, either.

    I realize you are probably busy with other things, but if you get a second to take a look i have uploaded the files to: http://www.parisisrestaurant.com/files/tparisi.zip

    -Travis

    Reply
    1. Ryan

      Travis – thanks for pointing out that the code was different between the blog post and the zip file. The post has the correct version. Hitting Twitter directly from Flash isn’t going to work.

      Did you read the comments from the others in both tutorials? The problem you have is likely a security sandbox issue. Make sure that the swf is sitting in the same domain as the php. Even a missing “www” will cause an error.

      Reply
  8. Travis

    Ryan, I was able to get it all working…mostly. Your code works perfect however when I add this code into my site, i then recieve an error:

    1120: Access of undefined property twitter_txt.

    my twitter_txt box is in scene 1, Frame 66, and within a movie clip symbol. Am I not calling it correctly from the Main.as file? Any help would be appreciated, once again.

    Reply
    1. Ryan

      Two problems here: 1. If your text field is on frame 66, and the code is being executed on frame 1, the code won’t find the text field. 2. If your text field is nested inside another clip, you need to use dot syntax to refer to it. So if it’s in a clip called textBoxHolder on the main timeline, to access it you need to say textBoxHolder.twitter_txt.

      There’s a third possible problem – AS3 is junk for dealing with timeline stuff, and especially nested clips on the timeline. Most often, the code executes before the screen is drawn and the clips become accessible. So watch out.

      Reply
  9. Travis

    That was the easy fix, using specials.twitter_txt. Now I am down to what seems to be the last issue. Like you said, my twitter_txt box sits with the loading text because the call to the Main.as file is at the beginning of the movie. Is there a way to call it again, at say, frame 66 in order to populate that text field?

    If not, I was thinking that i could make the ‘specials’ movie clips visibility equal to false at the beginning in order to populate the text box, but once it switches scenes I lose the text. Is there a way to maybe set the contents of the textbox to a global variable of a sort and then repopulate the textbox with those contents once i get to frame 66 (scene 2)?

    Sorry for all the questions, I am getting very close and I really appreciate the help.

    Reply
    1. Ryan

      1. Never use scenes
      2. The Main.as file is nearly exactly the same thing as having code in the first frame of your movie. So if you write a method (function) in there that populates the text field, you can just call that method when you hit frame 66. So if the method is called populateTextField, and inside you say twitter_txt.text = “whatever”, put a frame script on frame 66 and call the method – populateTextField()
      3. That all being said, there are some best practices you should learn going forward. Never use frame scripts. You wind up with what’s called “spaghetti code”, where you have little snippets buried all around your movie. And, unfortunately, stop using the timeline. AS3 has rendered the timeline useless to the point where if you try to use it and harmonize it with your AS3 code, you’re in for a world of hurt. This is a bitter pill to swallow, since i’m a big fan of timelines and nested clips, but the eggheads who have held Flash hostage for the past few years have locked us out.

      Reply
  10. joe B

    nice!

    Thanks much for this tutorial – i found it usefull and was able to get the first round working no problem – good work!

    But a few questions regarding this post … after read it seems like this method wouldn’t really work if you were getting a LOt of hits from ‘different’ users – is there any reason not to save the xml file out from the php and call to that? (then maybe add some logic to decide which xml file to read)

    im doing something like this for my solution:

    echo $file;

    $filename = $twitterId.’output.xml’;
    $h = fopen($filename, ‘w’);
    fwrite($h, $file);
    fclose($h);

    do get me wrong… I do like the shared object approach as well

    Reply
    1. Ryan

      NP, Joe B. Truth be told, we’re actually using a method similar to the one you’ve described here. We’ve set a cron job so that every x minutes, our server grabs the Twitter data and stores it. Visitors to our site actaully hit a php page that returns the cached data. This way, you get around the server call limit because it’s only our server that constantly checks the feed. Technology ftw! Thanks for sharing your solution.

      Reply
  11. Christian

    I have tried to set up the script really quickly and changed the required files but am not getting the twitter to load on my page.

    http://www.christianpompa.com/index2.html . the php & .as file is on there named twiter.php & Main.as in no directory, just right after domain for u quick testing. Can you check this out and give me a quick rundown of whats wrong with that. I checked throughout all the comments and couldn’t find anything. I also set the AS3 setting on the flash to link to Main.as but still no go on it. Thanks

    Reply
    1. Ryan

      Christian – do a quick check to make sure everything’s rigged up properly by putting a trace() command in Main, for starters.

      Reply
    1. Ryan

      Brandon – i’m not a pro at this, but my understanding is that Flash treats the www address and the non-www address as two different domains, and refuses to pull data from one domain into another. Just Google Flash cross-domain policy.

      Reply
  12. West

    Great tutorial. Haven’t found anything else like this on the web yet.

    Only had two problems getting it to work: 1) getting my server to cooperate (fopen stuff) and 2) figuring out that the php code is the ONLY thing that should be in the php file.

    I am, however, having problems implementing a stylesheet for the text. I want to pull in multiple tweets with the timestamps below each one (which I can do without a hitch) and have the timestamp be a smaller font and different color. I tried to use a css file loaded to a styleSheet and applied to the textbox, then use html code in between each node of the xml to create this effect… like this:

    twitter_txt.htmlText = “” + twitterXML.status.text[0] + “” + twitterXML.status.created_at[0] + “”;

    It just isn’t working. works though.
    Any ideas anyone?

    Reply
  13. Mike Maurer

    How did you guys get the url links from the tweet to actually be working links on the untold entertainment site?

    Reply
  14. Steve Axworthy

    Hey Ryan.. awesome work and great tutorial… I have gone through the comments and have seen the questions and replies on making the tweet links actual links.. and I understand that you seach for the http:// and then make that a link until you get to the next space in the AS3 code… but I am not at ll familliar on how to code that… If you could provide code or a link to a VERY beginner tutorial or samples that a ‘dummy’ may be able to get.. I would greatly appreciate it! Everything is working great in my test.. just need the links ;)
    Thanks!

    Reply
    1. Ryan

      Steve – are you asking for a tutorial on how to pick through the information you get from the Twitter RSS feed and do stuff with it?

      Reply
  15. Steve Axworthy

    Ryan, I am asking for details on making the tweet links actual links… I assume that would mean picking through the info from the tweeter rss feed to create the links.. hope I am explaining that right.

    Thanks!

    Reply
    1. Ryan

      Sorry, Steve – i misread your question.

      Short of writing a tutorial on it, here are the concepts and method calls you need:

      1. Take the Tweet string and store each word in a separate index in an array. You can do this with the Array.split() method

      2. Loop through each word, and look for “http://” using the String.indexOf() method. That method returns the position of the thing you’re looking for in the string. It returns -1 if the thing doesn’t exist in the string.

      3. If a word contains “http://”, replace it with “” + theWord + “‘‘”;, which resolves to someURL – your standard html hyperlink

      4. As you’re looping through each word and checking it for hyperlinks, concatenate it into a new string

      5. myTextField.htmlText = brandNewStringWithHyperlinksInIt;
      Yeah?

      – Ryan

      Reply
  16. Sean

    Alright, I think I’m almost there because my SWF file is pulling info from twitter. Only problem is it’s YOUR FEED!

    In the Main.as file I have changed the “myTwitterID = “XXXXXXX” to my XXXXXXX and pointed it to the correct PHP on my domain in the “twitterPHPScriptPath = “http://www.mydomain.com/phpfile.php” line, but it keeps showing your feed. I must be overlooking something small. Let me know if there is someplace else I need to change a parameter. Hope I’m just missing something small. I’m really just learning this as I go.

    Reply
  17. Sean

    I looked into the PHP and Main.as files, and it seems like the only place to put MY twitter user name is in the Main.as file.
    ______
    Isn’t the twitter ID in the PHP file set by that line in your Main.as file?

    The PHP file’s:
    “$twitterId = isset($_REQUEST[“twitterId”]) ? $_REQUEST[“twitterId”] : ”;
    if( $twitterId == “” ){”

    Is set by the Twitter id in the Main.as (as seen here?):

    // Put your Twitter username here. For example, ours is “Untoldent” :
    myTwitterID = “MyUsername”;

    // Put the path to your php script here:
    twitterPHPScriptPath = “http://www.mydomain.com/Scripts/twitter.php”;

    Am I missing something? I can DM you through twitter the URLs I’m using to test this from if it will help. I just don’t want to post them for all to see (grin).

    Thanks in advance for the help. Great tutorial so far, just trying to figure out where my stupid mistake is.

    Reply
  18. Sean

    Okay, I had everything right! That PHP file is effected by the Main.as script, and that’s the only place you need to update the TwitterID. It’s all working for me now.

    Your cashing script was just a little too strong and my browser too dumb. It was working off an old cashed Main.as file, one that had your info in it. After a few resetting the browsers, and clearing my cashed files, it seems to be working. Excellent tutorial sir! Thanks for having this available to us.

    Reply
  19. Mitch Rawrockin

    Hello there!

    First of all, supertutorial, I got mine up and running in no time and I’m an AS Newbie!

    Steve, I was wondering if you managed to get the links working, and if so, would you mind to share that part of code with me, that would be great..

    thanks,

    Mitch

    Reply
  20. Pingback: untoldentertainment.com » Tutorial: Clickify Your Twitter Feed in Flash

  21. Justin

    Ryan, can’t thank you enough for posting both these tutorials. It’s bonus enough to have these so I probably shouldn’t even ask, but any chance of Fwitter Part 2 for AS2?

    I stumbled my way through translating the AS3 from your first tutorial to AS2, but now visitors are exceding the 100 calls limit!

    Reply
  22. Justin

    Ryan, you’re totally right. It sounds like I’m building a site for a Commodore 64 or something.

    I… guess I can… learn AS3. :)

    Reply
  23. Curran

    Ryan: Sweet tutorial, and I love your website.
    Just one question: do you or anyone in internet land know what gets returned by twitter after 100 calls are exceeded? is it still xml? Wondering so I can account for it so that my app fails gracefully should that happen. I dont feel like reloading my app 100 times to find out! Thanks.

    Reply
    1. Ryan

      Curran – thanks! i *think* Twitter returns nothing once you break the limit, but i’m not sure how that gets read into Flash? Null? Dunno. It’s not very hard to poll Twitter 100 times … why don’t you be a pioneer? Break it, and let us all know!

      – Ryan

      Reply
    1. Ryan

      Steve – yeeeees, i’m from the paaaaast! (floating around) Wooooo!! Everyone here is thiiiiiiiner and has more haaaAAAaaaairrr!

      Reply
  24. steve p

    hm…. not sure what i’m doing wrong here. i noticed in the comments that there were some discrepancies between the .zip file posted and the code posted on this actual page, is there one I should or shouldn’t use? When I post your original files online and test them out your feed comes in fine, but when I change the Main.as file’s myTwitterID and the twitterPHPScriptPath to an absolute path to my php file all I get is the “loading” text.

    I read all the comments about the possible sandbox issues, but I am keeping all my files in the same folder and testing online so I don’t think thats the issue.

    In flash I get the error below, which I noticed someone else mentioned in the first fwitter tutorial. The only solution I saw was to set the text box to render text as HTML, but that didnt’ seem to make a difference.

    Any suggestions?

    cookie is fresh. display the data.
    showTwitterStatus
    TypeError: Error #2007: Parameter text must be non-null.
    at flash.text::TextField/set htmlText()
    at Main/showTwitterStatus()
    at Main/loadTwitterDataFromFlashCookie()
    at Main()

    Reply
  25. steve p

    well… i just realized the hosting account I’m testing on may not even support PHP… d’oh! tyring to find out for sure

    Reply
  26. Javier

    Hi Ryan Great class!! Thank You Very Much for sharing it too!!

    @Justin: here is the as2 code, it is working i`d downgraded Ryan`s great class, to use on a project that does not supported as3 (it was on a projector embedded into office `07), also here is a very handy tool to convert you as2 code into as3 while you`re learning it, http://www.5etdemi.com/blog/archives/2006/11/as2-to-as3-converter-createtextfield-geturl-handling/ , hope anyone with the same issue find it usefull, again Ryan you`re the man thank you very much!.
    [code]
    …import Proxy;

    class Twitter extends MovieClip
    {
    private var twitterXML : XML;
    private var twitterPHPScriptPath : String;
    private var myTwitterID : String;
    private var twitterText : TextField;
    private var statusInterval : Number;
    private var cicle : Number = 0;
    private var cookie : SharedObject;
    private var writeCookie : Boolean;
    private var currDate : Date;

    public function Twitter()
    {
    this.myTwitterID = “jzhouVIP”;
    this.twitterPHPScriptPath = “http://localhost/twitter.php”;
    this.writeCookie = true;
    this.loadDataFromCookie();
    }

    private function loadDataFromCookie() : Void
    {
    this.cookie = SharedObject.getLocal(“twitter”);
    var timeStamp : Date = this.cookie.data.timeStamp;

    if (timeStamp != null)
    {
    if (hasExpired(timeStamp))
    {
    trace(“cookie has expired! let’s get some fresh data”);
    this.loadTwitterXML();
    }
    else
    {
    trace(“cookie is fresh. display the data.”);
    this.twitterXML = this.cookie.data.twitterXML;
    this.showTwitterStatus();
    this.statusInterval = setInterval (this, “showTwitterStatus”, 10000);
    }
    }
    else
    {
    this.loadTwitterXML();
    }
    }

    private function saveToCookie() : Void
    {
    var flushStatus = null;
    try
    {
    flushStatus = this.cookie.flush(10000);
    }
    catch (error:Error)
    {
    trace(“Error…Could not write Cookie to disk\n”);
    }

    if (flushStatus != null)
    {
    switch (flushStatus)
    {
    case SharedObject.Flush.Failed:
    trace(“Requesting permission to save object…\n”);
    this.cookie.addEventListener(this, onFlushStatus);
    break;
    case SharedObject.Flush.Success:
    trace(“********* save complete. ***********\n”);
    finishedHandlingTwitterData();
    break;
    }
    }
    }

    private function onFlushStatus() : Void
    {
    trace(“User closed permission dialog…\n”);
    switch (this.cookie.onStatus)
    {
    case “SharedObject.Flush.Success”:
    trace(“User granted permission — value saved.\n”);
    finishedHandlingTwitterData();
    break;
    case “SharedObject.Flush.Failed”:
    trace(“User denied permission — value not saved.\n”);
    this.writeCookie = false;
    break;
    }
    this.cookie.removeEventListener(this, onFlushStatus);
    }

    private function finishedHandlingTwitterData() : Void
    {
    trace(“Twitter data saved.”);
    }

    private function hasExpired(timeStamp : Date) : Boolean
    {
    var now:Date = new Date();
    var expiryHours:Number = 2;
    var expiryMinutes:Number = 30;
    var expirySeconds:Number = 0;
    var msPerHour:Number = 3600000;
    var msPerMinute:Number = 60000;
    var msPerSecond:Number = 1000;
    var expiryTime:Number = (expiryHours * msPerHour) + (expiryMinutes * msPerMinute) + (expirySeconds * msPerSecond);

    return (now.getTime() – timeStamp.getTime() > expiryTime);
    }

    private function loadTwitterXML():Void
    {
    this.twitterXML = new XML();
    this.twitterXML.ignoreWhite = true;
    this.twitterXML.onLoad = Proxy.create(this, finishLoadingXML);
    this.twitterXML.load(this.twitterPHPScriptPath + “?twitterId=” + this.myTwitterID);
    trace(“xml loaded…init”);
    }

    private function finishLoadingXML():Void
    {
    this.cookie = SharedObject.getLocal(“twitter”);
    this.cookie.data.timeStamp = new Date();
    this.cookie.data.twitterXML = this.twitterXML;
    this.saveToCookie();
    this.showTwitterStatus();
    this.statusInterval = setInterval (this, “showTwitterStatus”, 10000);
    }

    private function showTwitterStatus():Void
    {
    if(cicle < this.twitterXML.firstChild.childNodes.length || cicle < this.cookie.data.twitterXML.length)
    {
    trace("cicle "+cicle);
    this.twitterText.autoSize = true;
    this.twitterText.embedFonts = true;
    this.twitterText.htmlText += this.twitterXML.firstChild.childNodes[cicle].childNodes[2] + "\n";
    cicle++;
    }
    else
    {
    clearInterval(this.statusInterval);
    trace("no more entries to display…aborting");
    }
    }
    }//end of class

    [/code]
    [code]
    …class Proxy
    {
    public static function create(oTarget : Object, fFunction : Function) : Function
    {
    var aParameters : Array = new Array();
    for(var i : Number = 2;i < arguments.length; i++)
    {
    aParameters[i – 2] = arguments[i];
    }
    var fProxy : Function = function():Void
    {
    var aActualParameters : Array = arguments.concat(aParameters);
    fFunction.apply(oTarget, aActualParameters);
    };
    return fProxy;
    }
    }

    [/code]

    Reply
  27. Larry

    Javier, thanks so much for posting AS 2 code for us dinosaurs.
    I’m a bit confused how to actually implement it– how do i actually get the class to interact with the text field? Also, I’m not seeing anything in the output.
    Thanks for your help!
    Larry

    Reply
  28. Corey Sayers

    timg,

    Here is a function that looks for a link inside of your tweet, then makes it a hyperlink and changes the color.

    public function createURLInsideofString(twitterPost:String):String
    {

    var doesHaveURLText:String = twitterPost;//;
    var urlstart = 0;
    var urlend = 0;
    var url_prefix:String = “”;

    if (doesHaveURLText.indexOf(“http://” || “www.”) != -1) {

    urlstart = doesHaveURLText.indexOf(“http://” || “www”);

    if (doesHaveURLText.indexOf(” “, urlstart) != -1) {
    urlend = doesHaveURLText.indexOf(” “, urlstart);

    } else {
    urlend=doesHaveURLText.length;
    }

    if (doesHaveURLText.indexOf(“http://”,urlstart) == -1) {
    url_prefix = “http://”;
    } else {
    url_prefix = “”;
    }

    return doesHaveURLText.substring( 0,urlstart)+”“+doesHaveURLText.substring(urlstart,urlend)+”“+doesHaveURLText.substring(urlend,doesHaveURLText.length);

    } else {
    return twitterPost;
    }

    }

    Just call that function like so,

    textFeild.htmlText = createURLInsideofString(twitterXML.status.text[i]);

    then your link will be highlighted, underlined and clickable.

    Hope that helps,

    Reply
  29. Corey Sayers

    Also, to get around the rate limiting, couldn’t you just write a PHP file that pulls all of the XML from twitter and saves it to your server, then you just have parse that XML? You could call that web service every minute with a CRON scheduler, which would only be 60 calls per hour and be an unlimited number on your server?

    Thoughts?

    Reply
    1. Ryan

      Corey- that’s exactly what we’re doing. But with the number of people telling me “i don’t know how to program – can you help me re-write this in Actionscript 1?”, i thought it best to just leave it at this :)

      Reply
  30. Corey Sayers

    Thanks Ryan, that was just a thought. But thanks so much for this. This is an AWESOME introduction shared objects, something that I have not worked with yet. Keep the killer tutorials coming!

    Reply
  31. Stefan Janssen

    Hi Ryan,

    You can call me a newbie, but i got some little flash experience. This is the first time i work with AS3.
    For mounts i’m trying to get this code working, but still the same result: Loading twitter status…
    I checked so many options out of these comments of other users, but i really get stucked.

    Like someone said before; on my local machine i can get the first tutorial-attachment working, only with your feeds. If i change just my twitter ID, it’s working but only on my local machine.

    I tried several times the code on the page of the first part of this tutorial, which is different, and i fill out the right php path.
    That also failed to work.
    The code above looks great, and i quite understand everything, but i’m confused that i can’t get it working.
    It all shows” Loading twitter status….”

    I did a lot of research in the code.
    And I think the php-file causes the failure.
    I checked the paths, and I also tested with www and without, relative paths etc. (the Main.as and the twitter.php are in the same directory on the server as my twitter.swf file)
    My webserver is of course compatible with php.

    I’m checking the swf file with Firefox, Safari and Chrome browsers.
    Firefox said in its status bar that when i’m opening the swf, it starts reading the twitterpage, and finish succesfully. But then again no result on my twitter_txt field.

    Some questions to make it a bit clear for me:
    1) I’m using the PHP file of the first part of this tutorial and named it “twitter.php” is that oke?
    2) To pretent www-mistakes, can i use a relative path for the php-file definition, like: twitterPHPScriptPath = “twitter.php”;
    3) Which of those 3 Main.as scripts do you advise me to use? Do they all work on a webserver?
    4) Does it make sence if i use my twitter ID or my twitter ID number? Do I have to provide the ” ” signs?
    5) How does the Main.as file hit the php-file? Can I check this?
    6) Any idea why it isn’t working if i just adjust the twitter ID, the php-file path and twitter.swf, twitter.php and Main.as upload to my webserver?

    If you are able to get some answers for me, i would be really really glad!
    And I hope you could help me to get this cool thing done.
    Thanx in advance!

    Stefan (from NL)

    Reply
  32. Tom

    Hi Ryan, awesome website and tutorials, I believe I may be having the same problem as steve p, but noone posted a solution….

    I’m copying the code here, and changing everything that is required. But am getting these errors:

    TypeError: Error #2007: Parameter text must be non-null.
    at flash.text::TextField/set htmlText()
    at Main/showTwitterStatus()
    at Main/loadTwitterDataFromFlashCookie()
    at Main()

    Any thoughts?

    Coincidentally if I comment all references of twitter_txt in the showTwitterStatus function and uncomment the trace(twitterXML); the error goes away but it does not trace the stuff twitter sends you.

    If you’ve got any thoughts it would be good to hear them. Thanks in advance.

    Reply
    1. Ryan Henson Creighton

      Tom – it may be an addedToStage problem … you might be trying to put text into a TextField on your stage before it’s available.

      Reply
  33. matt

    quick question:

    is there any way to display the relative time that the last tweet was made? like “43 minutes ago” or “two days ago”, etc.

    Reply
  34. James

    Hmm, I use your Tutorial 2 action script, only I have 3 dynamic texts.
    The problem is only if you go to another page and go back then it’s still loading…
    And when you type: http://www.zangpraktijk.nl/twitter it’s working.. Very strange.
    I hope you can find a solution.

    Reply

Leave a Reply to Tom Cancel reply

Your email address will not be published. Required fields are marked *