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.
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 rejectedHi 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:
- When we load up the module, let’s check the user’s Flash cookie to see if we’ve saved any Twitter data
- If the cookie is empty, we’ll hit the Twitter servers and grab new data. Then we’ll save that data for next time.
- 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.
- If there IS Twitter data in the cookie, let’s look at how old it is
- If it’s still fresh, there’s no need to hit Twitter. We’ll just display that data.
- 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
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.
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.
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.
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!
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.
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?
No suggestions! But it’s a good thing we’re on the Internatz. Anyone else?
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.
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
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/
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
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.
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.
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.
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.
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.
Maaan….. damn nice … its courtesy people like you that this world of internet is surviving .. damn damn guud .. both the technology and the motive heh ..
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
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.
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
Christian – do a quick check to make sure everything’s rigged up properly by putting a trace() command in Main, for starters.
If you are still having trouble with this one. Clean out your shared object folders eg:
information found here http://addiator.blogspot.com/2008/03/flash-cookies-finding-and-deleting.html
Was working fine and then not … Cleared out my shared objects all is well. Going to look into Joe B’s method.
Hey, thanks a lot man! After a few hours of pulling my hair out between the first tut and this one i got it with this cache version! This is the site: http://www.caitlincwilliams.com/
Thanks for making the twitter happen! :)
I have a question for you:
When I have the url in as http://caitlincwilliams.com the twitter feed doesn’t pull in, but when I have it with the “www” in the url it does. Any thoughts on this?
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.
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?
Ryan – Thanks, found helpful info here: http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html and fixed the issue!
How did you guys get the url links from the tweet to actually be working links on the untold entertainment site?
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!
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?
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!
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
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.
Sean – “untoldent” is set as the Twitter id in the php file. Did you forget to change that to your own username?
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.
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.
Ryan, Thanks for the details… I will see what I can do with it :) Thanks again!
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
Mitch – by popular demand, here’s your tutorial:
Tutorial: Clickify Your Twitter Feed in Flash
Pingback: untoldentertainment.com » Tutorial: Clickify Your Twitter Feed in Flash
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!
Justin – why are you stuck on AS2? Are you deploying to some ancient device?
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. :)
Justin – you (mostly) won’t regret it.
Try starting here, and reading the Understanding Classes tutorials:
http://www.untoldentertainment.com/blog/flash-and-actionscript-911/
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.
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
you are hilarious and helpful! p.s. your website says copyright 2008, are you from the past?
Steve – yeeeees, i’m from the paaaaast! (floating around) Wooooo!! Everyone here is thiiiiiiiner and has more haaaAAAaaaairrr!
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()
well… i just realized the hosting account I’m testing on may not even support PHP… d’oh! tyring to find out for sure
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]
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
Is there a way to make a link in a tweet clickable and a different color?
There sure is! Look up the TextFormat class.
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,
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?
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 :)
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!
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)
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.
Tom – it may be an addedToStage problem … you might be trying to put text into a TextField on your stage before it’s available.
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.
Hey,
When I go to the homepage of my website then I can see my tweets, but when I go to another page and press again on home then it is saying “loading…” how to automatically refresh this script?
Thanks!
See: http://www.zangpraktijk.nl/twitter
It’s throwing an error in my debug player …
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.