Final Flash Just Giving Parser

12 12 2007

Final Just Giving Example

Right so after several versions of this I finally have a nice class based AS2 version that’s optimised for performance and grabs the full data set. Thanks to all the team at Glue who worked on our Christmas card that inspired this research and also to Rich at Just Giving for his invaluable assistance and for amending their crossdomain.xml file to allow us Flash Devs access to their lovely RSS feeds:

FLA & com folder for download:

Download FLA

[code lang="actionscript"]

class com.glue.xmas.ui.JustGiving extends MovieClip {

// Class assets
private var serverStringPath:String = "http://www.justgiving.com/rss/getfundraisingpage.asp?eventgivinggroupid=";
private var jgGroupID:String;
private var xmlIn:XML;
private var xmlOut:XML;
private var updateJustGivingObj:Object;
private var updateJustGivingInterval;
private var pollSeconds:Number;
// On stage asset declarations
private var justGiving_mc:MovieClip;
private var target_txt:TextField;
private var total_txt:TextField;
private var online_txt:TextField;
private var offline_txt:TextField;
private var giftaid_txt:TextField;
// Temporary conversion assets
private var rcArr:Array;
private var rcStr:String;
private var t_arr:Array;
private var t_arr2:Array;
private var t_pounds:Number;
private var t_pence:Number;
private var t_total:Number;
private var dStr_init:String;
private var dStr_arr:Array;
private var dStr_arr2:Array;;
private var dStr_arr3:Array;
// Core Variable - with Public Getter/Setters
private var currentTarget:Number;
private var currentTotal:Number;
private var currentOnline:Number;
private var currentOffline:Number;
private var currentGiftAid:Number;

function JustGiving(){
// Poll secs & Just Giving Group ID
init(10, "963699");
}

private function init(secs:Number, groupID:String):Void{
pollSeconds = secs;
jgGroupID = groupID;
justGiving_mc = this;
setRepeat(pollSeconds, justGiving_mc, true);
hide();
}

//////////////////////////////////////////////////////////////////
// Hide & Show - Getters and Setters //
//////////////////////////////////////////////////////////////////

private function show():Void {
justGiving_mc._visible = true;
}
private function hide():Void {
justGiving_mc._visible = false;
}

public function set target(newTarget:Number):Void {
currentTarget = newTarget;
}
public function get target():Number {
return currentTarget;
}
public function set total(newTotal:Number):Void {
currentTotal = newTotal;
}
public function get total():Number {
return currentTotal;
}
public function set online(newOnline:Number):Void {
currentOnline = newOnline;
}
public function get online():Number {
return currentOnline;
}
public function set offline(newOffline:Number):Void {
currentOffline = newOffline;
}
public function get offline():Number {
return currentOffline;
}
public function set giftaid(newGiftAid:Number):Void {
currentGiftAid = newGiftAid;
}
public function get giftaid():Number {
return currentGiftAid;
}

//////////////////////////////////////////////////////////////////////////////////
// Setup Interval Set and Clear to control update period of live RSS data //
// //
// Seconds to leave between updates //
// Optional boolean - whether to execute instantly as well as on interval //
//////////////////////////////////////////////////////////////////////////////////

private function setRepeat(repeatTime:Number, mcScope:MovieClip, alsoCallOnInit:Boolean):Void {
updateJustGivingObj = new Object();
updateJustGivingObj.updateFromRSS = function():Void {
//On Interval - Parse RSS
trace("Requesting Fresh RSS Data...");
mcScope.parseJGRSS(mcScope.serverStringPath, mcScope);
}
updateJustGivingInterval = setInterval(updateJustGivingObj, "updateFromRSS", repeatTime*1000);
// Optional Instant Execute
if(alsoCallOnInit == true){
updateJustGivingObj.updateFromRSS();
}
}

private function clearRepeat():Void {
clearInterval(updateJustGivingInterval);
}

private function onJGFeedParse():Void {
target_txt.text = ""+target;
total_txt.text = ""+total;
online_txt.text = ""+online;
offline_txt.text = ""+offline;
giftaid_txt.text = ""+giftaid;
show();
}

//////////////////////////////////////////////////////////////////////////////////
// Main Parsing function and 2 String & Datatype Manipulation functions used by //
// removeCommas() //
// jgFeedStrToNum() //
// parseJGRSS() //
//////////////////////////////////////////////////////////////////////////////////

private function removeCommas(args:String):String {
trace("Removing Comma's from tridecimal string "+args);
// Split the string into tridecimal strings and reconcatenate without the commas
rcArr = args.split(',');
var rcStr:String = "";
for (var i=0; i rcStr += rcArr[i];
}
return rcStr;
}

private function jgFeedStrToNum(args:String):Number {

// Remove any commas as Just Giving add them at triddecimals e.g "£1,056,234"
if (args.indexOf(',') != -1) {
args = removeCommas(args);
}
// Split Donations string into Pounds/Pence - (or Dollars/Cents)
t_arr = args.split('.');
// Remove any trailing space from after the Pence/Cents string
t_arr2 = t_arr[1].split(' ');
var t_pounds:Number = new Number(t_arr[0]);
var t_pence:Number = new Number(t_arr2[0]);
//trace("Pounds "+t_pounds+" Pence "+t_pence+" Pence in Pounds "+(t_pence/100));
var t_total:Number = t_pounds+(t_pence/100);

return t_total;
}

private function parseJGRSS(jgRSSUrl:String, mcScope:MovieClip) {
var xmlIn:XML = new XML();
var xmlOut:XML = new XML();
xmlIn.ignoreWhite = true;

xmlIn.onLoad = function(success) {
if (success) {
//////////////////////////////////////////////////////////////////////////////////////////////
// PROCESS THE "Item Description" NODE TO GET ALL THE FINANCE TOTALS //
//////////////////////////////////////////////////////////////////////////////////////////////

trace("Loaded Feed & Parsing RSS...");

var dStr_init:String = this.firstChild.childNodes[0].childNodes[6].childNodes[2].childNodes[0].nodeValue;

// Split XML node string by html list end symbol
dStr_arr = dStr_init.split('

');

// Get Fundraising Page Target :
dStr_arr2 = dStr_arr[0].split(';');
currentTarget = mcScope.jgFeedStrToNum(dStr_arr2[1]);
//trace("currentTarget = "+currentTarget);
//mcScope.target_txt.text = currentTarget;
mcScope.target = currentTarget;

// Get Total donations to date :
dStr_arr2 = dStr_arr[1].split(';');
currentTotal = mcScope.jgFeedStrToNum(dStr_arr2[1]);
//trace("currentTotal = "+currentTotal);
//mcScope.total_txt.text = currentTotal;
mcScope.total = currentTotal;

// Get Online donations to date :
dStr_arr2 = dStr_arr[2].split(';');
currentOnline = mcScope.jgFeedStrToNum(dStr_arr2[1]);
//trace("currentOnline = "+currentOnline);
//mcScope.online_txt.text = currentOnline;
mcScope.online = currentOnline;

// Get Amount raised offline :
dStr_arr2 = dStr_arr[3].split(';');
currentOffline = mcScope.jgFeedStrToNum(dStr_arr2[1]);
//trace("currentOffline = "+currentOffline);
//mcScope.offline_txt.text = currentOffline;
mcScope.offline = currentOffline;

// Get The UK Gift Aid Reclaimed :
dStr_arr2 = dStr_arr[4].split(';');
dStr_arr3 = dStr_arr2[1].split('');
currentGiftAid = mcScope.jgFeedStrToNum(dStr_arr3[0]);
//trace("currentGiftAid = "+currentGiftAid);
//mcScope.giftaid_txt.text = currentGiftAid;
mcScope.giftaid = currentGiftAid;

mcScope.onJGFeedParse();

} else {
trace("RSS Load Failed");
}
};
xmlOut.sendAndLoad(jgRSSUrl+jgGroupID, xmlIn);
}
}

[/code]



Flash justgiving.com RSS Parse v2

10 12 2007

BananasUpdated the Flash Just Giving method to use XML.sendAndLoad instead of LoadVars and I’ve also included the Pence/Cents calculations if you need to do Maths on the returned value. You should be able to work out from this whatever properties you need from the RSSXML: all my source is below:

[code lang="actionscript"]

// Just Giving RSSXML Parsing V2
var xmlIn:XML = new XML();
var xmlOut:XML = new XML();
xmlIn.ignoreWhite = true;
xmlIn.onLoad = function(success) {
if (success) {

// HERES ALL THE PROPERTIES OF THE RSSXML
/*
trace("Title "+this.firstChild.childNodes[0].childNodes[0].childNodes[0]);
trace("Link "+this.firstChild.childNodes[0].childNodes[1].childNodes[0]);
trace("Description "+this.firstChild.childNodes[0].childNodes[2].childNodes[0]);
trace("Language "+this.firstChild.childNodes[0].childNodes[3].childNodes[0]);
trace("Last Build Date "+this.firstChild.childNodes[0].childNodes[4].childNodes[0]);
trace("TTL "+this.firstChild.childNodes[0].childNodes[5].childNodes[0]);
trace("Item Title "+this.firstChild.childNodes[0].childNodes[6].childNodes[0].childNodes[0]);
trace("Item Link "+this.firstChild.childNodes[0].childNodes[6].childNodes[1].childNodes[0]);
trace("Item Description "+this.firstChild.childNodes[0].childNodes[6].childNodes[2].childNodes[0]);
trace("Item Publish Date "+this.firstChild.childNodes[0].childNodes[6].childNodes[3].childNodes[0]);
*/
// HERES HOW TO PROCESS THE TO GET THE CURENT DONATIONS TOTAL

var donationStr:String = this.firstChild.childNodes[0].childNodes[6].childNodes[0].childNodes[0].nodeValue;
//testing only - donationStr = "So far this page has raised £980.07 "

// Split XML node string by pound sign (change to dollars $ if your currency is US)
arr = donationStr.split('£');

//At this point - if all you need is a string just use this..
trace("Donations as a String = "+"£"+arr[1]);
// However if you want a Number you can do Maths on you'll have to do a touch more...

// Split Donations string into Pounds/Pence - (or Dollars/Cents)
arr2 = arr[1].split('.');
// Remove any trailing space from after the Pence/Cents string
arr3 = arr2[1].split(' ');

var tdPounds:Number = new Number(arr2[0]);
var tdPence:Number = new Number(arr3[0]);
//trace("Pounds " + tdPounds + " Pence "+tdPence + " Pence in Pounds "+(tdPence/100));
var totalDonations:Number = tdPounds + (tdPence/100);

trace("Donations as a Number = " + totalDonations);

} else {
trace("RSS Load Failed");
}
};
// http://www.justgiving.com/gorillarob
//xmlOut.sendAndLoad("http://www.justgiving.com/rss/getfundraisingpage.asp?eventgivinggroupid=499910",xmlIn);
// http://www.justgiving.com/gluexmas
xmlOut.sendAndLoad("http://www.justgiving.com/rss/getfundraisingpage.asp?eventgivinggroupid=963699",xmlIn);

[/code]

Example FLA for download:
Download FLA



File Upload TypeFilter : AS2/AS3/PHP

5 12 2007

Here’s how to Filter which filetypes your user can upload in AS2, I’ve provided code for Image Files & All Files:

[code lang="actionscript"]

var reference:FileReference = new FileReference();
reference.browse([{description:"Image files", extension: "*.jpg;*.gif;*.png"}]);
// OR reference.browse([{description:'All Files (*.*)', extension:'*.*'}]);

[/code]

Here’s how to Filter which filetypes your user can upload in AS3:

[code lang="actionscript"]

imagesFilter = new FileFilter("Images", "*.jpg;*.gif;*.png");
// OR imagesFilter = new FileFilter("All Files", "*.*");
f = new FileReference();
f.addEventListener(Event.SELECT,onFileSelect);
f.addEventListener(IOErrorEvent.IO_ERROR,errorFile);
f.addEventListener(Event.COMPLETE, uploadComplete);
f.browse([imagesFilter]);

[/code]

With both languages – remember that this level of file filtering is great for usability but is not for security – you should check the filetype on the server side too (for .exe, .bat etc…) as there are are certain ways of uploading files not specified by these filters (That’s true of AS2 and AS3 apps I believe)

Here’s the PHP file that handles the upload:

[code lang="php"]

if (isset($_FILES['Filedata'])){
if ($_FILES['Filedata']['name']) {
$randappend = time();
move_uploaded_file($_FILES['Filedata']['tmp_name'], 'uploads/' .$randappend . "_" . basename($_FILES['Filedata']['name']));
}
}

?>

[/code]

If that doesnt work check that the PHPinfo() on the server you are uploading to -

  • Is file_uploads true?
  • Is upload_max_filesize big enough?

Bookmark me if that’s useful :)



Flash AS2 Justgiving.com RSS Parsing

5 12 2007

Here’s a quick method of parsing your justgiving.com RSS feed in AS2

As a little background – here is my Just Giving Gorilla Run 2007 page and here’s the corresponding RSS feed

Bananas

This AS2 Actionscript function returns the total online donations as a Number, it’s a bit quick and dirty but will do a job ;)

[code lang="actionscript"]

function parseRSSForTotalOnlineDonations(justGivingURL:String, justGivinGroupID:String) {

var jgGrID = justGivinGroupID;
var jgStr = justGivingURL+jgGrID;
var rssSend_lv:LoadVars = new LoadVars();
var rssReply_lv:LoadVars = new LoadVars();

rssReply_lv.onLoad = function(success:Boolean) {
if (success) {

var rssXML:XML = new XML(this);
var st:String = new String(rssXML.childNodes[0]);
arr = st.split('Total');
st2 = unescape(arr[1]);
arr2 = st2.split('');
st3 = unescape(arr2[0]);
arr3 = st3.split('#');
st4 = arr3[1];
arr4 = st4.split(';');
st5 = unescape(arr4[1]);
arr5 = st5.split('.');
st6 = unescape(arr5[0]);
var totalDonations:Number = new Number(st6);

trace(totalDonations);

} else {
trace("Connection Failed!");

}
};

rssSend_lv.sendAndLoad(jgStr, rssReply_lv, GET);

}

parseRSSForTotalOnlineDonations("http://www.justgiving.com/rss/getfundraisingpage.asp?eventgivinggroupid=","499910");

[/code]

As ever if this helps you please distribute this link via any of the provided Bookmarking tools. Cheers.



JS String replace chars function

5 12 2007

handy way to replace chars in strings with JS

[code lang="javascript"]
function replace (origStr, searchStr, replaceStr) {
var tempStr = "";
var startIndex = 0;
if (searchStr == "") {
return origStr;
}
if (origStr.indexOf(searchStr) != -1) {
while ((searchIndex = origStr.indexOf(searchStr, startIndex)) != -1) {
tempStr += origStr.substring(startIndex, searchIndex);
tempStr += replaceStr;
startIndex = searchIndex + searchStr.length;
}
return tempStr + origStr.substring(startIndex);
} else {
return origStr;
}
}

[/code]



JS Get query string variables

5 12 2007

Easy way to grab Variables from the query string using JS
[code lang="javascript"]

function getQueryStringVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;
var pair = vars[i].split("=");
if (pair[0] == variable) {
// Var value or just true if exists - your call
//return pair[1];
return true;
}
}
return false;
}
[/code]



Copy Embed Tag to Clipboard from Flash

3 12 2007

Just finished an AS2 Flash cross browser “Copy to clipboard from Flash” solution (copies a MySpace pastable tag). You can see the final widget clicking through on my MySpace page. Here’s the tag generator site featuring said copy to clipboard functionality that lets you copy the code for this widget:

Respect to Jeffothy for the DHTML solution of using encodeURIComponent() I updated this somewhat and made it write the MySpace tag to a hidden div. To get a clearer view of what’s going on please feel free to have a nose at my test version:

http://www.londonfloramarathonwidget.com/?test=true

Here’s the (mega simple) AS2 :

[code lang="actionscript"]

copyToClip_btn.onRelease = function() {
getURL("javascript:copyToClip('"+_root.copyURL+"');");
};

[/code]

Where _root.copyURL is a variable appended via a query string (as MySpace doesn’t allow FlashVars) e.g.

http://www.myhost.com/myswf.swf?copyURL=http://www.theclickthrough.com

I’m sure those of you savvy enough to do a view source will benefit enormously from my JS/CSS code ;) If this helps you in any way please distribute this link via any of the provided Bookmarking tools; thanks!

Enjoy ;)



Flash getURL clickthrough workaround for MySpace

3 12 2007

Found a way to get around the fact that you can’t use getURL to do clickthroughs from Flash embedded in MySpace. (They banned using getURL due to last years Flash injected XSS “Samy is my friend” worm crippling many a benign Flash app)

The way round it is to position images in the places where you want the clickthroughs. Now this sounds easy but there’s no documentation, you can’t use DHTML layers or JS or full CSS layouts (have to use tables), theres a million CSS bits you have to override and the editor does a search and replace on certain strings when you save the tag in MySpace and sometimes treats whitespace as line breaks – very frustrating!

Finally nailed it – the London Marathon Countdown Widget app I built is hosted on my MySpace http://www.myspace.com/lordrobertmc, clicks through ok and is tested in IE7, Firefox & Safari. Here’s the code if you’d like to benefit from my painful experience ;)

N.B I also discovered that you can’t use FlashVars to embed variables only ? querystring. Bah

Here’s what your widget will look like:

Here’s the code:

<style type=”text/css”> table.adiflmw { width: 396px; height: 250px; border-width: 0px 0px 0px 0px; border-spacing: 0px; border-style: none none none none; border-color: white white white white; background-color: white; } table.adiflmw td { border-width: 0px 0px 0px 0px; padding: 0px 0px 0px 0px; border-style: none none none none; border-color: white white white white; background-color: white; -moz-border-radius: 0px 0px 0px 0px; } a:link, a:active, a:visited { color:#ffffff; } </style> <table class=”adiflmw”> <tr> <td valign=”top” align=”left”> <span> <a href=”http://adidaswidgets.glueserv.co.uk/v9/” id=”adiCt1″><img src=”http://adidaswidgets.glueserv.co.uk/v9/adiflm396x38.jpg” border = “none” /></a><br><object type=”application/x-shockwave-flash” allowScriptAccess=”never” allowNetworking=”internal” height=”130 name=” width=”396″ align=”middle” data=”http://adidaswidgets.glueserv.co.uk/v9/Clock02.swf?spURL=http://www.justgiving.com/gorillarob&getCountDownLink=http://adidaswidgets.glueserv.co.uk/v9/”> <param name=”allowScriptAccess” value=”never” /> <param name=”allowNetworking” value=”internal” /> <param name=”movie” value=”http://adidaswidgets.glueserv.co.uk/v9/Clock02.swf?spURL=http://www.justgiving.com/gorillarob&getCountDownLink=http://adidaswidgets.glueserv.co.uk/v9/” /> <param name=”quality” value=”high” /> <param name=”wmode” value=”opaque” /> <param name=”bgcolor” value=”#ffffff” /> </object> <br> <a href=”http://www.justgiving.com/gorillarob” id=”adiCt2″><img src=”http://adidaswidgets.glueserv.co.uk/v9/adiflm396x82.jpg” border = “none” /></a> </span> </td> </tr> </table>

N.B You’ll have to manually swap those curly brackets for standard double quotes as Code Snippet doesn’t like this block for some reason :(

If this helps you in any way please distribute this link via any of the provided Bookmarking tools; thanks!

Enjoy ;)



Hello world!

3 12 2007

Just hooked up WordPress & a lovely plug in from addthis.com. Expect some useful Flash/DHTML/PHP Dev items soon ;)