// jquery.namespace
// A smarter way to create namespaces for jQuery calls and utility methods.
// (c)2009 Edmond Leung/Fox Sports
//
// Usage:
// 
// Single level namespacing:
// code: $.namespace('fs');
// result: $.fs is now available
// 
// ... multi-level namespacing:
// code: $.namespace('fs.ad');
// result: $.fs.ad is now available
//
// You can also pass in a hash as an extra parameter to have it automatically
// added into the namespace. Works for both util and jQuery object call namespaces:
// code: $.namespace('fs.ad', { methodname: function() {} });
// result: $.fs.ad.methodname() can now be called
//
// The above are for namespacing util functions, to namespace jQuery
// object calls start with 'fn.', note that methods in the created namespace
// MUST be created with this namespace util function:
// code: $.namespace('fn.fs', { methodname: function() {} })
// result: $(selector).fs.methodname() is now available
//
// Limitations:
// Need to create a new jQuery object everytime a namespaced plugin is used.
// That is, if you want to do this:
// form.fs.memoryform();
// You have to do this insteaD:
// $(form).fs.memoryform();

(function($) {
    $.namespace = function(name, objects) {
        var namespace = undefined;
        var isJQueryCall = false;
        var nameHierarchy = name.split('.');
        
        if (nameHierarchy.length > 1) {
            // Recursively create or grab parent namespaces
            var lastName = nameHierarchy.pop();
            var parentNamespace = $.namespace(nameHierarchy.join('.'));
            
            // Create new namespace if one doesn't exist
            if (parentNamespace[lastName] === undefined || parentNamespace[lastName] === null) { parentNamespace[lastName] = {}; }
            namespace = parentNamespace[lastName];
            
            // If first namespace is "fn", then it means it's a jQuery object call
            if (nameHierarchy[0] == "fn") { isJQueryCall = true; }
        } else {
            // Last level of namespace, no need to create parent namespaces
            if ($[name] === undefined || $[name] === null) { $[name] = {}; }
            namespace = $[name];
        }
        
        // If objects is defined, then add the objects to the namespace
        if (objects === undefined || objects === null) {
            return namespace;
        } else {
            // If a jquery call, then we need to make sure the calls work correctly
            if (isJQueryCall) {
                var oldObjects = objects;
                objects = {};
                $.each(oldObjects, function(key, value) {
                    if (typeof value == "function") {
                        // Make sure the calls are still jQuery objects
                        objects[key] = function() {
                            return oldObjects[key].apply($._throwaway.lastJQueryObject, arguments);
                        };
                    } else {
                        // If not function, then no need to manipulate
                        objects[key] = oldObjects[key];
                    }
                });
            }
            
            return $.extend(namespace, objects);
        }
    };
    
    // Use throwaway namespace to store global variables that
    // aren't used publicly
    $.namespace('_throwaway', {
        originalJQueryInit: $.fn.init
    });
    
    // Override original jQuery init function so that we can record what
    // the last retrieved jQuery object is and use it for namespacing
    $.fn.init = function(selector, context) {
        $._throwaway.lastJQueryObject = new $._throwaway.originalJQueryInit(selector, context);
        return $._throwaway.lastJQueryObject;
    };
})(jQuery);// jquery.fs.tvguidemodule
// Fox Sports TV Guide Module Show Details
// (c)2009 Brendan Cartledge/Fox Sports
//
// Creates an overlay/lightbox effect for the details of each show in the tv-guide module.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
// jquery.tools.scrollable.navigator.js
//
// Usage:
// $('input').fs.tvguidemodule();  for the overlay show details to come up on the click of each item in the tvguide
// $('input').fs.tvguideaccordian();  for the accordian effect on display of individual show details

(function($) {    
    var functions = {
    };
    
    // Create fs.accordion jquery call
    $.namespace('fn.fs', {
		accordion: function(opts) {     
			opts = $.extend({}, $.fn.fs.accordion.defaults, opts);
			
			$(this).find('.overlay-show-alt').hide();
			
			$(this).find('.accordian .accordheader').click(function() {
				var accordstatus = $(this).children('a').attr('class');
				
				if (accordstatus == "active") {
					$(this).
						next('.accorditem'). 
						slideUp('normal'); 
					
					$(this).children('a').removeClass('active').addClass('inactive');
					
				}
				else {
					$(this).
						next('.accorditem'). 
						slideDown('normal'); 
					
					$(this).children('a').removeClass('inactive').addClass('active');
					
				}
			});
		}
    });
    
   
    $.namespace('fs.accordion', {
        defaults: {
        }
    });	
})(jQuery);

    
    

	/*jslint evil: true */

// jquery.fs.ad
// Fox Sports MCN adkit (no tracking, tracking is in separate file)
// (c)2009 Edmond Leung/Fox Sports
//
// header and footer ad calls are not supported. The header call in previous adkit
// did nothing anyways, and the footer only did tracking, which is handled by
// tracktr jquery plugin now.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// 
// Initialising the adkit:
// $.fs.ad.init('SPORT.HOME');
// 
// Display an ad:
// $.fs.ad.show('leaderboard');

(function($) {
	
	var functions = {
        initSelectiveAds: function() {
            if ($.fs.ad.data !== null) {
                var selectiveAds = { };
                
                // Find and store all selective ad sections that are enabled
                var items = $.fs.ad.data.response['container-1'][0]['group-content-1'];
                if (items !== undefined) {
                    $.each(items, function(i, adAsset) {
                        if (adAsset.type == "ads") {
                            if (selectiveAds[adAsset.adType] === undefined) {
                                selectiveAds[adAsset.adType] = {};
                            }
                            
                            selectiveAds[adAsset.adType][adAsset.section] = true;
                        }
                    });
                }
                
                this.selectiveAds = selectiveAds;
            }
            
            // On dom ready, add has-ad class names to all modules with ads
            $(function() {
                $('.ad-sandwich').closest($.fs.ad.defaults.adContainers).addClass('has-ad');
            });
        },
        
        isSelectiveAd: function(adType) {
        	for (var i = 0; i < this.opts.selectiveAdTypes.length; i++) {
	            if(this.opts.selectiveAdTypes[i] == adType){
	                return true;
	            }
	        }
	        return false;
        },
        
        selectiveAdSection: function(adType, section) {
            // If sandwich ad, then check if we should show it
            if (this.selectiveAds !== undefined && this.selectiveAds[adType] !== undefined) {
                var tempSection = section;
                
                // See if ad is enabled, or check hierarchy and use parent ads
                while (true) {
                    var adGroup = this.selectiveAds[adType];
                    if (adGroup[tempSection] === undefined) {
                        var lastDotIndex = tempSection.lastIndexOf('.');
                        if (lastDotIndex == -1) { return null; }
                        tempSection = tempSection.substring(0, lastDotIndex);
                    } else {
                        break;
                    }
                }
                
                // If sandwich ad, then always wrap it through JS
                return tempSection;
            }
            
            return null;
        },
        
        shouldDisableAd: function(adType) {
        	// Check if the niam player ads wrapper exists yet
        	var hasNiamPlayerAdsWrapper = $('#niam-player-ads').size() > 0;
        	
        	// If it does, then disable first btyb after that (meaning niam btyb)
        	if (hasNiamPlayerAdsWrapper && !this.niamBtybLoaded && adType == 'btyb') {
        		this.niamBtybLoaded = true;
        		return true;
        	}
        	
        	// If it does, then disable first leaderboard after that (meaning niam leaderboard)
        	if (hasNiamPlayerAdsWrapper && !this.niamLeaderboardLoaded && adType == 'leaderboard') {
        		this.niamLeaderboardLoaded = true;
        		return true;
        	}
        	
        	return false;
        }
	};
	
    $.namespace('fs.ad', {
        // Setup default here for utils
        defaults: {
        	adContainers: '.module, .tvguide-details', 	// Selector that tells adkit which containers hold ads (and should have has-ad applied to it)
            site: 'foxs',   							// Default site is foxsports
            dcopt: true,    							// Turn dcopt on/off
            runads: true,    							// Turn all ads on/off (js kill switch)
            selectiveAdTypes: [ 'sandwich' ]
        },
        
        data: null,
        
        ads: {
        	marketplace:		'300x100',
        	sandwich: 			'288x30',
            leaderboard:        '728x90',
            flexible_lb:        '468x60,728x90',
            btyb:               '110x40',
            island:             '300x250',
            halfpage:           '300x250,300x600',
            banner:             '468x60',
            skyscraper:         '120x600',
            wideskyscraper:     '160x600',
            gutter:				'1x1',
            pushdown:			'1000x40',
            other:              ''
        },
        
        init: function(section, opts) {
            this.opts = $.extend({}, $.fs.ad.defaults, opts);
            
            this.section = section.toLowerCase();
            
            // Initialize tile number
            this.tile = 1;
            
            // Only one random ord per page
            this.ord = parseInt(Math.random() * 10000000, 10);
            
            // Initialize pos numbers for all adtypes
            var self = this;
            $.each($.fs.ad.ads, function(adtype, size) {
                if (self.pos === undefined) { self.pos = {}; }
                self.pos[adtype] = 1;
            });
            
            // Initialise the sandwich ads
            functions.initSelectiveAds.call(this);
        },
        
        show: function(adType, adSettings) {
        	// Check whether ad should be disabled
        	if (functions.shouldDisableAd.call(this, adType)) {
        		return;
        	}
        	
            // If ads are turned off, then ignore this function
            if (!this.opts.runads) { return; }
            
            // If ad type doesn't exist, then quit
            if ($.fs.ad.ads[adType] === undefined) { return; }
            
            // Override default options with passed in options
            adSettings = $.extend({
            	wrapAd: false,			// Use to specify if a wrapper div should be used to wrap the ad
                section: undefined,     // Use to override the section
                pos: undefined,         // Use this to override auto generated pos
                tile: undefined,        // Use to override the tile number
                ord: undefined          // Use to override the ord param
            }, adSettings);
            
            var section = (adSettings.section === undefined) ? this.section : adSettings.section;
            
            // If adtype is a selective ad, then attempt to retrieve hierarchical section to use
            if (functions.isSelectiveAd.call(this, adType)) {
                section = functions.selectiveAdSection.call(this, adType, section);
                adSettings.wrapAd = true;
                
                // If no section found, then selective ad shouldn't be display, so quit
                if (section === null) {
                    return;
                }
            }

            // Turn area (section with underscores) into sec1, sec2, sec3, etc.
            var area = section.replace(/\./g, '_');
            var params = {};
            $.each(area.split('_'), function(i, sec) {
                params["sec" + (i + 1)] = sec.replace(/-/g, '_');
            });
            
            // Grab the keywords from the meta tags
            var keywords = [];            
            $('meta[name=keywords]').each(function() {
                keywords.push($(this).attr('content').toString());
            });
            keywords = keywords.join(',').replace(/, /g, ',');
            
            // Create params
            $.extend(params, {
                area: area.replace(/-/g, '_'),
                tile: (adSettings.tile !== undefined) ? adSettings.tile : this.tile++,     				 // Next tile position
                pos: (adSettings.pos !== undefined) ? adSettings.pos : this.pos[adType]++,	 			 // Use overriden pos in opts, or auto generated pos
                sz: $.fs.ad.ads[adType],                                      				 			 // Grab size based on adtype
                kw: keywords,                                                 				 			 // Use meta tag as keywords
                ord: (adSettings.ord !== undefined) ? adSettings.ord : this.ord 			 			 // Unique id for ord
            });
            
            // Only used dcopt if dcopt is turned on, and first ad on page
            if (this.opts.dcopt && params.pos == 1 && adType == 'leaderboard') {
                params.dcopt = "ist";
            }
            
            // Convert hash of params into a string for the script src
            var paramString = "";
            $.each(params, function(key, value) {
                paramString += ";" + key + "=" + value;
            });
            
            // Write the ad to the page
            var src = "http://ad.au.doubleclick.net/adj/mcn." + this.opts.site + "/sport/" + area.replace(/_/g, '/').replace(/-/g, '_') + paramString + "?";
            
            // Wrap the ad if required
            if (adSettings.wrapAd) { document.write('<scr' + 'ipt type="text/javascript" src="http://media.foxsports.com.au/fatwire/ads/pre_ad_wrapper.js"></scr' + 'ipt>'); }
            document.write('<scr' + 'ipt type="text/javascript" src="' + src + '"></scr' + 'ipt>');
            if (adSettings.wrapAd) { document.write('<scr' + 'ipt type="text/javascript" src="http://media.foxsports.com.au/fatwire/ads/post_ad_wrapper.js"></scr' + 'ipt>'); }
            
            return src;
        }
    });
})(jQuery);// jquery.fs.bbb
// Fox Sports Ball By Ball Cricket Module
// (c)2009 Brendan Cartledge/Fox Sports
//
// Transforms a JSON ball by ball cricket match feed into a module
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('input').fs.bbb();

(function($) {	
	var functions = {
			
		init: function(opts) {
			var self = $(this);
			
			var matchid = self.find('.ball-by-ball').attr('rel');
			var file = opts.path + "Cricket_" + matchid + "_BBB.json";
			
			functions.getData.call(self, opts, file);
			
			self.everyTime(opts.refreshInterval,function(i) {
				functions.getData.call(self, opts, file);
			}); 
		},
		
		getData: function(opts, file)  {
			var self = $(this);
						
			$.getJSON( file, function(data) {
				functions.prematch.call(self, opts, data);
				functions.recentOvers.call(self, opts, data);
				functions.mainCommentary.call(self, opts, data);
			});
		},
		
		createContainers: function(opts)  {
			var self = $(this);
			var bbbContainer = self.find('.ball-by-ball');
			
			//create the recent overs stuff
			//append to .ball-by-ball
			
			if (self.find('.recent-overs-wrapper').size() === 0) {
				var rOversWrapper = $('<div class="recent-overs-wrapper"></div><!-- //.recent-overs-wrapper -->').appendTo(bbbContainer);
				var rOvers = $('<div class="recent-overs"></div><!-- // .recent-overs -->').appendTo(rOversWrapper);
				var rOversHeader = $('<div class="recent-overs-header"></div><!-- //.recent-overs-header -->').appendTo(rOvers);
				rOversHeader.html('<h4>Recent Overs</h4>');
				
				var rOversScroller = $('<ul class="recent-overs-scroller"></ul><!-- // .recent-overs-scroller -->').appendTo(rOversHeader);
				var rOversNavPrev = $('<li class="next"><a ><span>Previous</span></a></li>').appendTo(rOversScroller);
				var rOversNavNext = $('<li class="previous prev"><a ><span>Next</span></a></li>').appendTo(rOversScroller);
				var rOversSummWapper = $('<div class="summary-wrapper"></div> <!-- //.summary-wrapper -->').appendTo(rOvers);
				var bbbItems = $('<div class="bbb-items"></div><!-- //.bbb-items -->').appendTo(rOversSummWapper);
			}
			
			//create the commentary 'scrollable' wrapper.
	
			// no element found
			if(bbbContainer.find('.scrollable').length === 0)  {
				var scrollerDiv = $('<div class="scrollable"></div><!-- //.scrollable  -->').appendTo(bbbContainer);
			} else {
				bbbContainer.find('.scrollable').html('');
			}
		},
		
		prematch: function(opts, data) {
			var self = $(this);
			var preWrapper = self.find('.pre-match-wrapper');
			
			if (data === null || data.match === null || data.match.updates === null || data.match.updates.length === 0) {
				preWrapper.show();
			} else {
				preWrapper.hide();
				functions.createContainers.call(self, opts);
			}	   
		},
		
		recentOvers: function (opts, data) {
			var self = $(this);
			
			var overs = 0;
			var balls = [];
			var bcounter = 0;
			var thisBall;
			var overTrigger = false;
			var endOver = true;
			var ballsInOverCounter = 0;
			
			var summWrapper = self.find('.summary-wrapper');
			var bbbItems = summWrapper.find('.bbb-items');
			
			bbbItems.html('');
			
			var oversToShow = opts.summaryOvers;
			var oversInJson = data.match.updates.length / 6;
			
			//if there are less overs in the JSON file than the options want to show, then only show the number in the file.
			if (oversInJson < oversToShow) {
				oversToShow = oversInJson;
			}
			
			//loop through each ball in update
			for (var i = 0; overs < oversToShow-1; i++) {
				var upWickets = data.match.updates[i].wicket_taken;
				var upRuns = data.match.updates[i].runs;
				var upByes = data.match.updates[i].byes;
				var upLegbyes = data.match.updates[i].legbyes;
				var upNoballs = data.match.updates[i].noballs;
				var upWides = data.match.updates[i].wides;
				
				if (upWickets) {
					thisBall = "W";
				} else if (upRuns > 0) {
					thisBall = upRuns.toString();
				} else if (upByes > 0) {
					thisBall = upByes.toString()+"b";
				} else if (upLegbyes > 0) {
					thisBall = upLegbyes.toString()+"lb";
				} else if (upNoballs > 0) {
					thisBall = upNoballs.toString()+"nb";
				} else if (upWides > 0) {
					thisBall = upWides.toString()+"wd";
				} else {
					thisBall = ".";
				}
				
				balls[ballsInOverCounter] = thisBall;
				
				var overNo = parseInt(data.match.updates[i].overs,10);				 
				
				//if the last ball was the end of the next over to be written, 
				//don't write it 
				if (overTrigger) {
					overTrigger = false;
					endOver = false; //this siginifies that it is not end of over, rather last ball of an over to be written.
				}
				
				ballsInOverCounter += 1;
				
				if (data.match.updates[i].end_of_over && endOver) {
					overNo = parseInt(data.match.updates[i-1].overs,10)+1;
					
					var bbbSummOver = $('<div class="bbb-summ-over"></div><!-- //.bbb-summ-over -->').appendTo(bbbItems);
					
					var summOverNo = $('<div class="over-no" rel="'+overNo+'">'+overNo+'</div>').appendTo(bbbSummOver);
					var summOverDetails = $('<div class=\"over-details\"></div><!-- //.over-details -->').appendTo(bbbSummOver);
					
					//write ul
					
					var summOverDetailsUL = $('<ul></ul>').appendTo(summOverDetails);
					
					//write balls in reverse order to the div
					for(bcounter = 0;  bcounter < (balls.length - 1) ; bcounter ++) {
						summOverDetailsUL.prepend("<li>"+balls[bcounter]+"</li>");
					}
					
					i -= 1; //go back and do this last ball of over in its own over
					overTrigger = true; //set this so that it doesn't come into this 'if' and end the over after only 1 ball
					balls = []; //reset the array so that it only has this over's info in it
					ballsInOverCounter = 0; //start the balls() array from [0] again
					overs++; //the number of overs in the summary
				}
				
				endOver = true; //now that we have skipped that 'if' once, we need to go into it next time there is 'end_of_over'
			}
			
			// Attach scrollable plugin, but only ever once
			var api = summWrapper.data('scrollable-api');
			if (api === undefined) {
				api = summWrapper.scrollable({
					api: true
				});
				
				// Attach scrollable and store api for later use
				summWrapper.data('scrollable-api', api);
			}
			
			// Update scrollable to match new elements and their sizes
			api.reload();
		},
		
		mainCommentary : function(opts, data) {
			var self = $(this);
			
			var bbbContainer = self.find('.ball-by-ball');
			var scrollerDiv = bbbContainer.find('.scrollable');
			
			var commWrapper = $('<div class="wrapper scroll-pane"></div><!-- //.wrapper scroll-pane  -->').appendTo(scrollerDiv);
			var commTable = $('<table></table>').appendTo(commWrapper);
			var commTbody = $('<tbody></tbody>').appendTo(commTable);
			var tableRow;
			
			for (var i = 0 ; i < data.match.updates.length ; i++) {
				var endOfOver = data.match.updates[i].end_of_over;
				var wickets = data.match.updates[i].wickets;
				var totalRuns = data.match.updates[i].total_runs;
				var noOvers = data.match.updates[i].overs;
				var bowler = data.match.updates[i].bowler;
				var striker = data.match.updates[i].striker;
				var runRate = Math.round(totalRuns/parseInt(noOvers+1,10)*100)/100;
				striker = data.match.updates[i].striker;
				var strikerRuns = data.match.updates[i].striker_runs;
				var strikerBalls = data.match.updates[i].striker_balls;
				var nonStriker = data.match.updates[i].non_striker;
				var nonStrikerRuns = data.match.updates[i].non_striker_runs;
				var nonStrikerBalls = data.match.updates[i].non_striker_balls;
				var ballNo = Math.round((noOvers*10) % 10);
				var bowlerName = data.match.updates[i].bowler;
				var bowlerWickets = data.match.updates[i].bowler_wickets;
				var bowlerRuns = data.match.updates[i].bowler_runs;
				var bowlerOvers = data.match.updates[i].bowler_overs;
				
				//check if even or odd row.
				var oddRow = "odd";
				
				if((ballNo%2) === 0) {
					oddRow = "even";
				} else {
					oddRow = "odd";
				}

				var overSuffix = "th";
				
				 // Add st, nd or rd, or th
				var overTemp = parseInt(((noOvers+1) % 10),10);

				switch (overTemp) {
					case 1:
						overSuffix = "st";
						break;
					case 2:
						overSuffix = "nd";
						break;
					case 3:
						overSuffix = "rd";
						break;
					default:
						overSuffix = "th";
				}
				
				// Handle teens
				if ((noOvers+1) > 10 && (noOvers+1) < 20) {
					overSuffix = "th";
				}
					
				var commentary = data.match.updates[i].commentary;
				
				var words = opts.highlightwords; 
				
				//bold the words in the above array in the commentary
				for (var w = 0; w < words.length ; w++) {
					commentary = commentary.replace(new RegExp(words[w], 'g'), '<strong>' + words[w] + '</strong>');
				}
				
				if (endOfOver) {
					//write end of over table row.
					tableRow = $('<tr class="update_type_end"></tr>').appendTo(commTbody);
					tableDef = $('<td colspan="2"></td>').appendTo(tableRow);
					endDiv = $('<div class="end"></div>').appendTo(tableDef);
					
					endDiv.html('<strong>End of '+parseInt(noOvers+1,10)+overSuffix+' Over :: '+wickets+'/'+totalRuns+'</strong> (RR: '+runRate+') :: '+striker+' '+strikerRuns+' ('+strikerBalls+'), '+nonStriker+' '+nonStrikerRuns+' ('+nonStrikerBalls+') :: '+bowlerName+' '+bowlerWickets+'/'+bowlerRuns+' ('+bowlerOvers+')');
				}
				
				//determine what type of update (runs, sundries, wicket etc)
				var updateType = "";
			
				// Find the update type based on the stats of the game
				if (data.match.updates[i].wicket_taken) {
					updateType = "W";
				} else if (data.match.updates[i].runs > 0) {
					updateType = data.match.updates[i].runs.toString();
				} else if (data.match.updates[i].byes > 0) {
					updateType = "b";
				} else if (data.match.updates[i].legbyes > 0) {
					updateType = "lb";
				} else if (data.match.updates[i].noballs > 0) {
					updateType = "nb";
				} else if (data.match.updates[i].wides > 0) {
					updateType = "wd";
				} else {
					updateType = ".";
				}
				
				var ballClass = "";
				
				if (ballNo === 1) {
					//the first ball of over doesn't have bottom border so that yellow shows
					ballClass = "ball1";
				} else if (ballNo === 6) {
					//the last ball of over doesn't have top border so that the shadow works
					ballClass = "ball6";
				}
				
				tableRow = $('<tr class="update_type_'+updateType+' '+oddRow+' '+ballClass+'"></tr>').appendTo(commTbody);
				tableDef = $('<td class="score"></td>').appendTo(tableRow);
				tableDef.html(wickets+'/'+totalRuns+' <br /> ov: <strong>'+noOvers+'</strong>');
				tableDef = $('<td class="commentary"></td>').appendTo(tableRow);
				commText = $('<div class="text"></div>').appendTo(tableDef);
				commText.html(commentary);
			}
			
			$('.bbb-module .scrollable .wrapper').livequery( function() {
				$(this).jScrollPane({
					showArrows:true ,
					scrollbarMargin: '0',
					scrollbarWidth: '11',
					arrowSize: '13',
					dragMinHeight: '10'
				});
			});			
		}
	};
	
	// Create fs.bbb jquery call
	$.namespace('fn.fs', {
		bbb: function(opts) {	 
			opts = $.extend({}, $.fn.fs.bbb.defaults, opts);
			
			return this
				.each(function() {
					var self = $(this);
					self.data('bbbOptions', opts);
					functions.init.call(self, opts);
				});
		}
	});
	
	// Setup defaults for ball by ball plugin
	$.namespace('fn.fs.bbb', {
		defaults: {
			path: "http://www.foxsports.com.au/xmlfeed/cricket/",
			//path: '', // Test path
			highlightwords: ["SIX","FOUR","OUT"],
			refreshInterval: 60000, //in milliseconds (1000th of second) <- every minute
			summaryOvers: 10
		}
	});
})(jQuery);// jquery.fs.bigbashtables
// Fox Sports Page Refresh Disabler
// (c)2011 Brendan Cartledge/Fox Sports
//
// Used to disable page refreshing when a user starts to type in a soapbox or comments field.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// 
// Initialising:
// $('.soapbox-module').fs.bigbashtables();

(function($) {
    $.namespace('fs.bigbashtables', {
        // Setup default here for utils
        defaults: {
        	
        }
    
    });
    $.namespace('fn.fs', {
        bigbashtables: function(opts) {
        	this.opts = $.extend({}, $.fs.bigbashtables.defaults, opts);
        	var self = $(this);
        	
        	$.each(self, function() {
			
				var xmlurl = $(this).attr('rel');
				var moduleclass = $(this).attr('class');

				$.ajax( {
					url: xmlurl,
					dataType: "xml",
					success: function(xml) {
							
						var tabletype = 'sixes';
						var metrics = $(xml).find('sixeslist');
						var playertype = 'batsman';
						if(moduleclass == 'module zinger-speedball-module') {
							tabletype = 'speed';
							metrics = $(xml).find('speedlist');
							playertype = 'bowler';
						}
											
						var rankArray = [];
						var bowlerArray = [];
						var stateArray = [];
						var metricArray = [];
						var i = 0;
						metrics.each( function() {
							
							$(this).find('ranking').each( function() {
								rankArray[i] = $(this).text();
								i++;
							});
							i=0;
							$(this).find(playertype).each( function() {
								bowlerArray[i] = $(this).text();
								i++;
							});
							i=0;
							$(this).find('state').each( function() {
								stateArray[i] = $(this).text();
								i++;
							});
							i=0;
							$(this).find(tabletype).each( function() {
								metricArray[i] = $(this).text();
								i++;
							});
							i=0;

						});
						
						if(rankArray.length < 1)
						{
							self.hide();
						}
						
						var j=0;
						for(j = 0; j < rankArray.length ; j++)
						{
							var row = $('<tr></tr>');
							if((j+1) == rankArray.length) {
								row.attr('class', 'lastrow');
							}
							
							var rankitem = $('<td></td>').addClass('rank').text(rankArray[j]);
							var bowleritem = $('<td></td>').addClass('name').text(bowlerArray[j].toLowerCase());
							var metricitem = '';
							if(tabletype == 'speed')
							{
								
								metricitem = $('<td></td>').addClass('speed').text(parseFloat(metricArray[j]).toFixed(1)+' km/h');
							}
							else
							{
								metricitem = $('<td></td>').addClass('distance').text(parseFloat(metricArray[j]).toFixed(1)+'m');
							}
							
							var statebadge = $('<a></a>').attr('class','small-cricket-team-logo '+stateArray[j]+'-cricket-small-logo').attr('href','#').text(stateArray[j]);
							var statebadgewrapper = $('<div></div>').addClass('badge-wrapper');
							statebadgewrapper.append(statebadge);
							var stateitem = $('<td></td>').attr('class','badge').append(statebadgewrapper);			
							
							row.append(rankitem).append(stateitem).append(bowleritem).append(metricitem);

							if(tabletype == 'speed') { 
								$('.speedballs tbody').append(row); 
							} else {
								$('.big-hitters tbody').append(row);
							}
		
						}
							 
							
					},
					error: function() {
						if(moduleclass === 'module zinger-speedball-module')
						{
							$('.zinger-speedball-module').hide();
						}
						else
						{
							$('.weetbix-biggest-sixes-module').hide();
						}
						
					}
				});
			});

        }
    });
})(jQuery);var loadBiggestFan;

(function($) {
	$.namespace('fs.biggestfan.service');

	// Interface for Biggest Fan Service implementation
	$.fs.biggestfan.service.intaface = $.klass({
		/**
		 * init - Constructure, responsible for doing any setup work required
		 * by your delegate, eg. preloading data.
		 **/
		initialize: function(opts, successDelegate, failureDelegate) {
			throw "init not implemented";
		},
		
		/**
		 * getWeeks - Should return a list of the weeks with entries.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getWeeks: function(successDelegate, failureDelegate) {
			throw "getWeeks not implemented";
		},
		
		/**
		 * getCurrentWeek - Should return the currenty active week.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getCurrentWeek: function(successDelegate, failureDelegate) {
 			throw "getCurrentWeek not implemented";
	    },
	    
		/**
		 * getNextWeek - Should return the next active week.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getNextWeek: function(successDelegate, failureDelegate) {
 			throw "getNextWeek not implemented";
	    },
	    
		/**
		 * getWeekWithId - Should return the week with the specified id.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
	    getWeekWithId: function(id, successDelegate, failureDelegate) {
	    	throw "getWeekWithId not implemented";
	    },

		/**
		 * getUrls - Should return the list of urls.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
	    getUrls: function(successDelegate, failureDelegate) {
	    	throw "getUrls not implemented";
	    }
	});
	
	// JSON based Biggest Fan Service implementation
	$.fs.biggestfan.service.json = $.klass($.fs.biggestfan.service.intaface, {
		defaults: {
		    jsonFilePath: ""
		},
		
		_prepareData: function(json, successDelegate, failureDelegate) {
		    var self = this;
		    
		    try {
		        this.weeks = json.biggestfan.weeks;
		        this.urls = json.biggestfan.urls;
		        
		        $.each(this.weeks, function(i, week) {
		        	if (json.biggestfan.comp_week_id == week.id) {
                        self.nextWeek = week;
                    }
                    
                    if (json.biggestfan.current_week_id == week.id) {
                        self.currentWeek = week;
                    }
		        });
		    } catch (exception) {
		        if (failureDelegate !== undefined) {
		            failureDelegate.call(this);
	            }
	            
		        return;
		    }
			
		    if (successDelegate !== undefined) {
                successDelegate.call(this);
            }
		},
        
		initialize: function(opts, successDelegate, failureDelegate) {    
			var self = this;
            
			this.opts = $.extend({}, this.defaults, opts);
			
			loadBiggestFan = function(json) {
				self._prepareData(json, successDelegate, failureDelegate);
			};
			
			$.ajax({
				type: "GET",
				url: this.opts.jsonFilePath,
				dataType: "jsonp",
				data: { callback: 'biggestfan', cacheBuster: parseInt(Math.random() * 1000000000, 10) },
				error: function() { 
				    if (failureDelegate !== undefined) {
				        failureDelegate.call(self);
				    }
				}
			});
		},
		
		getWeeks: function(successDelegate, failureDelegate) {	
		    if (successDelegate !== undefined) {
                successDelegate.call(this, this.weeks);   
		    }
		},
		
		getCurrentWeek: function(successDelegate, failureDelegate) {
		    if (successDelegate !== undefined) {
                successDelegate.call(this, this.currentWeek);   
		    }
		},
		
		getNextWeek: function(successDelegate, failureDelegate) {
		    if (successDelegate !== undefined) {
                successDelegate.call(this, this.nextWeek);   
		    }
		},
		
	    getWeekWithId: function(id, successDelegate, failureDelegate) {
	    	$.each(this.weeks, function(i, week) {
	    		if (week.id == id && successDelegate !== undefined) {
	    			successDelegate.call(this, week);   
	    		}
	    	});
	    },

	    getUrls: function(successDelegate, failureDelegate) {
		    if (successDelegate !== undefined) {
                successDelegate.call(this, this.urls);   
		    }
	    }
	});
	
	if (!Array.indexOf){
	    Array.prototype.indexOf = function(obj){
	        for (var i = 0; i < this.length; i++){
	            if (this[i] == obj){
	                return i;
	            }
	        }
	        return -1;
	    };
	}
	
	var functions = {
	    createEntryModule: function(week, entry) {
	    	var number = week.entries.indexOf(entry) + 1;
	    
	        var moduleDiv = $('' + 
	            '<div class="module comp-module">' + 
                    '<div class="module-content">' + 
                        '<div class="promo-block">' +
                            '<div class="promo-image">' +
                                '<img width="310" height="240" />' +
                                '<a href="#" class="enlarge-button show-entry-link"><strong>Enlarge</strong></a>' +
                            '</div>' +
                            '<div class="promo-text">' +
                                '<h3 class="heading"></h3>' +
                                '<p></p>' +
                            '</div>' +
                        '</div>' +
                    '</div>' + 
                    '<div class="module-footer">' + 
						'<script type="text/javascript">var addthis_config = {"data_track_clickback":true};</script>' +
						'<div class="button-share-this-small addthis_toolbox addthis_default_style">' +
							'<a href="http://www.addthis.com/bookmark.php?v=250&amp;username=foxsportscomau" class="addthis_button_compact"></a>' +
						'</div>' +
						'<script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#username=foxsportscomau"></script>' +                        
                         										
                        '<a href="#formCheck" class="button-vote-now-small vote_page">Vote Now</a>' + 
                    '</div>' + 
                '</div>');
            
            var promoBlockDiv = moduleDiv.find('.promo-block');
            var imageElement = moduleDiv.find('.promo-image img');
            var showEntryLinkAnchor = moduleDiv.find('.show-entry-link');
            var headingElement = moduleDiv.find('.promo-text .heading');
            var pElement = moduleDiv.find('.promo-text p');
            
            promoBlockDiv.addClass(entry.type.toLowerCase() + '-entry');
            imageElement.attr({
                'src': entry.content.thumbnail_url,
                'title': entry.name,
                'alt': entry.name
            });
            showEntryLinkAnchor.attr('rel', week.id + ',' + (number - 1));
            headingElement.text(number + '. ' + entry.name + ', ' + entry.location);
            pElement.text(entry.description);
            
            return moduleDiv;
	    },
	    
	    createLightboxEntry: function(week, entry) {
    		var lightboxEntryDiv = $('' +
    			'<div class="entry">' +
	    			'<div class="entry-content">' +
	    			'</div>' +
	    			'<p class="entry-details">' +
	    			'</p>' +
    			'</div>');
    		
    		lightboxEntryDiv.addClass(entry.type.toLowerCase() + '-entry');
    		
    		var entryDetailsP = lightboxEntryDiv.find('.entry-details');
    		entryDetailsP.text(entry.name + ', ' + entry.location + ' - ' + week.title);
    		
    		var entryContentDiv = lightboxEntryDiv.find('.entry-content');
    		
    		switch (entry.type.toLowerCase()) {
    		    case "image":
    		        var entryImage = $('<img></img>').attr({
    		            'alt': entry.description,
    		            'src': entry.content.source
    		        }).appendTo(entryContentDiv);
    		        break;
    		    case "video":
    		        entryContentDiv.html(entry.content.source);
    		        break;
    		    case "text":
    		        entryContentDiv.html('<div class="text-entry-content">' + entry.content.source + '</div>');
    		        break;
    		}
    		
    		return lightboxEntryDiv;
	    }
	};
	
	$.namespace('fn.fs.biggestfan', {
	    entrymodules: function(service, opts) {
            opts = $.extend({}, $.fn.fs.biggestfan.entrymodules.defaults, opts);
            
            return this.each(function() {
                var self = $(this);
                
                service.getCurrentWeek(function(currentWeek) {
                    $.each(currentWeek.entries, function(i, entry) {
                        if (!entry.selected || entry.selected == 'false') { return; }
                        
                        var parentItemDiv = self.find('.item.ipos-' + ((i % 2) === 0 ? 1 : 2));
                        var entryModuleDiv = functions.createEntryModule(currentWeek, entry).appendTo(parentItemDiv);
                    });
                });
            });
	    },
	    
	    lightboxentries: function(weekId, service, opts) {
            opts = $.extend({}, $.fn.fs.biggestfan.lightboxentries.defaults, opts);
            
            return this.each(function() {
                var self = $(this);
                
                service.getWeekWithId(weekId, function(week) {
                    $.each(week.entries, function(i, entry) {
                        if (!entry.selected || entry.selected == 'false') { return; }
                        
                    	var lightboxEntryDiv = functions.createLightboxEntry(week, entry).appendTo(self);
                    });
                });
            });
	    }
	});
	
	$.namespace('fn.fs.biggestfan.entrymodules', {
        defaults: {
        }
    });
    
	$.namespace('fn.fs.biggestfan.lightboxentries', {
        defaults: {
        }
    });
    
    $.fs.biggestfan.lightbox = {
    	defaults: {
    	},
    	
    	init: function(service, opts) {
    		this.opts = $.extend({}, $.fs.biggestfan.lightbox.defaults, opts);
    		
    		this.service = service;
    		
    		this.lightboxVeilDiv = $('<div class="lightbox-veil"></div>').appendTo(document.body);
    		
    		this.lightboxDiv = $('' + 
    			'<div class="lightbox">' + 
				    '<div class="lightbox-tools">' + 
				    	'<a class="button-close-lightbox" href="#">Close</a>' + 
				    '</div>' + 
					'<div class="lightbox-content">' +
					'</div>' + 
					'<div class="lightbox-footer">' + 
						'<a class="button-vote-now-medium vote_page" href="#formCheck">Vote Now</a>' + 
                        '<a class="button-share-this-medium addthis_button" href="http://www.addthis.com/bookmark.php?v=250&amp;username=xa-4c6a54467be8d97e"><img src="http://s7.addthis.com/static/btn/sm-share-en.gif" width="83" height="16" alt="Bookmark and Share" style="border:0"/></a><script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#username=xa-4c6a54467be8d97e"></script>' +
						'<script type="text/javascript">var addthis_config = {"data_track_clickback":true};</script>' +
						'<a class="button-share-this-medium addthis_button" href="http://www.addthis.com/bookmark.php?v=250&amp;username=foxsportscomau"><img src="http://s7.addthis.com/static/btn/sm-share-en.gif" width="83" height="16" alt="Bookmark and Share" style="border:0"/></a><script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#username=foxsportscomau"></script>' +
					'</div>' + 
				'</div>').appendTo(this.lightboxVeilDiv);
			
            var closeFunction = function() {
            	$.fs.biggestfan.lightbox.hide();
            	return false;
			};
            
            this.lightboxCloseAnchor = this.lightboxDiv.find('.button-close-lightbox').click(closeFunction);
			
			var lightboxContentDiv = this.lightboxDiv.find('.lightbox-content');
    		
            service.getWeeks(function(weeks) {
            	$.each(weeks, function(i, week) {
            		var weekDiv = $('<div class="week"></div>').addClass('week' + week.id + '-entries').appendTo(lightboxContentDiv);
            		var prevAnchor = $('<a class="prev">Previous</a>').appendTo(weekDiv);
            		var scrollableDiv = $('<div class="scrollable"></div>').appendTo(weekDiv);
            		var entriesDiv = $('<div class="entries"></div>')
            			.fs.biggestfan.lightboxentries(week.id, service)
            			.appendTo(scrollableDiv);
            		var nextAnchor = $('<a class="next">Next</a>').appendTo(weekDiv);
            		
                    var scrollableApi = scrollableDiv.scrollable({ size: 1, clickable: false, api: true });
                    weekDiv.data('scrollableApi', scrollableApi);
            	});
            });
            
			$('.show-entry-link').livequery(function() {
				var showEntryLink = $(this);
				var linkData = showEntryLink.attr('rel').split(',');
				
				var weekId = linkData[0];
				var entryIndex = linkData[1];
				
				showEntryLink.click(function() {
					$.fs.biggestfan.lightbox.showEntry(weekId, entryIndex);
					return false;
				});
			});
			
			$(window).resize(function() {
				$.fs.biggestfan.lightbox.updatePosition();
			});
			
			this.voteNowButton = this.lightboxDiv.find('.button-vote-now-medium').click(function() {
            	$.fs.biggestfan.lightbox.hide();
			});
    	},
    	
    	updatePosition: function() {
    		this.lightboxDiv.css('margin-top', ($(window).height() - this.lightboxDiv.height()) / 2.0);
    	},
    	
    	showEntry: function(weekId, entryIndex) {
    		this.lightboxDiv.find('.week').removeClass('active');
    		
    		var activeWeek = this.lightboxDiv.find('.week' + weekId + '-entries').addClass('active');
    		
            this.service.getWeekWithId(weekId, function(weekData) {
    		    if (weekData.disable_vote) {
    		        $.fs.biggestfan.lightbox.voteNowButton.hide();
    		    } else {
    		        $.fs.biggestfan.lightbox.voteNowButton.show();
    		    }
    		});
    		
    		this.show();
    		
    		var api = activeWeek.data('scrollableApi');
    		var currentIndex = api.getIndex();
    		var moveOffset = entryIndex - currentIndex;
    		
    		api.move(moveOffset, 0);
    		
    		this.updatePosition();
    	},
    	
    	show: function() {
    		this.lightboxVeilDiv.addClass('active');
    	},
    	
    	hide: function() {
    		this.lightboxVeilDiv.removeClass('active');
    	}
    };
})(jQuery);// jquery.fs.comments
// Fox Sports Story Comments
// (c)2009 Edmond Leung/Fox Sports
//
// Sets up the comments list and comments form for a story.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('#comments').fs.comments();

(function($) {    
	
    var functions = {
    	expandForm: function() {
    		var self = $(this);
    		var expandedFieldSet = self.find('.additional-information');
    		
	    	// Only animate if not already visible...
	    	if (!expandedFieldSet.is(':visible')) {
	    		// Wrap fieldset with a div so animation works
		    	var wrapper = $('<div></div>').addClass('additional-information-wrapper').hide();
		    	expandedFieldSet.wrap(wrapper).show();
		    	
		    	// Now slide the wrapper
		    	wrapper = expandedFieldSet.parent();
		    	wrapper.slideDown('fast', function() {
		    		// Oncomplete, remove wrapper
		    		expandedFieldSet.addClass('active').insertAfter(wrapper);
		    		wrapper.remove();
		    	});
			}
    	},
    	
    	collapseForm: function() {
    		var self = $(this);
    		var expandedFieldSet = self.find('.additional-information');
    		
	    	// Only animate if not already visible...
	    	if (expandedFieldSet.is(':visible')) {
	    		// Wrap fieldset with a div so animation works
		    	var wrapper = $('<div></div>').addClass('additional-information-wrapper');
		    	expandedFieldSet.wrap(wrapper);
				
		    	// Now slide the wrapper up
		    	wrapper = expandedFieldSet.parent();
		    	wrapper.slideUp('fast', function() {
		    		// Oncomplete, remove wrapper and hide the fieldset
		    		expandedFieldSet.addClass('active').insertAfter(wrapper).hide();
		    		wrapper.remove();
		    	});
			}
    	},
    	
    	centerNumbers: function() {
    		var self = $(this);
    		
		    // Center all the big numbers
		    self.find('.comment-block').each(function() {
		    	var commentBlock = $(this);
		    	var commentNumber = commentBlock.find('.comment-number');
		    	
		    	commentNumber.css('top', (commentBlock.attr('offsetHeight') - commentNumber.height()) / 2.0);
		    });
    	}
    };
    
    // Create fs.comments jquery call
    $.namespace('fn.fs', {
        comments: function(opts) {     
            opts = $.extend({}, $.fn.fs.comments.defaults, opts);

            return this
                .each(function() { 
                    var self = $(this);  
                    
				    // Apply font sizer to story comments  as well
				    $(self.find('.comments-list')).fs.fontsizer({
				        increaseButtons: '.js-font-inc',
				        decreaseButtons: '.js-font-dec',
				        fontSizes: [ 11, 12, 15, 18, 22 ],
				        lineHeights: [ 17, 18, 22, 26, 31 ],
				        afterResize: function() { functions.centerNumbers.call(this); }	// On resize, center big numbers again
				    });
					
				 	// Hide bottom of comments form by default
				    var expandedFieldSet = self.find('.additional-information').hide();
				    
				    // On focus on comment box, show comments form
				    var commentsTextArea = self.find('#ccomments')
					    .focus(function() {
					    	functions.expandForm.call(self);
					    })
					    // Add character counter, grab the max chars from the markup
					    .charCounter(parseInt(self.find('.field-instruction em').text(), 10), {
							container: '.field-instruction',
							format: "%1 characters left"
						});
						
					var form = self.find('form');
					
					// Method to call on form submit success
					var submitSuccess = function() {
				    	// Use memory form to persist and remember the form
				    	if (form.find('#module-comment-add-save-details').attr('checked')) {
				    		$(form).fs.memoryform('persist');
				    	} else {
				    		// Clear if the user doesn't want to remember
				    		$(form).fs.memoryform('clear');
				    	}
				    	
				    	// Open lightbox and show the iframe in it
				    	$.fn.colorbox({ inline: true, href: "#module-comment-add-form-iframe", transition: 'none', open: true });
				    };
				    
				    // Use validation engine
					form.validationEngine({
						beforeSuccess : submitSuccess,
						failure : function() {}
					});
				    
				    // If anchor to go to comment form is clicked, then focus on comments text area
				    self.find('a[href=#module-comment-add]').click(function() {
				    	commentsTextArea.focus();
				    });
				    
				    // Center the big numbers
				    functions.centerNumbers.call(this);
				    
				    // Iframe it
				    var iframe = $('<iframe frameborder="0" name="module-comment-add-form-iframe" id="module-comment-add-form-iframe"></iframe> ');
				    iframe.appendTo(self);
				    form.attr('target', 'module-comment-add-form-iframe');
				    
				    iframe.load(function() {
			    		// Restore once submitted
			    		$(form).fs.memoryform('restore');
			    		
						// Clear the comments field always
						self.find('#ccomments').val('');
						
						// Hide the form once done
						functions.collapseForm.call(self);
				    });
                });
        }
    });
    
    // Setup defaults for comments plugin
    $.namespace('fn.fs.comments', {
        defaults: {
        }
    });
})(jQuery);(function($) {
	$.namespace('fs.fantasy.service');
	
	// The two types of data tables
	$.namespace('fs.fantasy.datatype', {
		Players: "Players",
		Managers: "Managers"
	});
	
	// Interface for Fantasy Service implementation
	$.fs.fantasy.service.intaface = $.klass({
		/**
		 * init - Constructure, responsible for doing any setup work required
		 * by your delegate, eg. preloading data.
		 **/
		initialize: function() {
			throw "init not implemented";
		},
		
		/**
		 * getHighestScorers - Should return a list of the highest scorers in
		 * the fantasy game.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getHighestScorers: function(code, successDelegate, failureDelegate) {
			throw "getHighestScorers not implemented";
		},
		
		/**
		 * getHighestScorersByType - Should return a list of the highest scorers in
		 * the fantasy game based on player type.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getHighestScorersByType: function(type, code, successDelegate, failureDelegate) {
			throw "getHighestScorersByType not implemented";
		},
		
		/**
		 * getHighestScorersByTeam - Should return a list of the highest scorers in
		 * the fantasy game based on team.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getHighestScorersByTeam: function(team, code, successDelegate, failureDelegate) {
			throw "getHighestScorersByTeam not implemented";
		},
		
		/**
		 * getMostSelected - Should return a list of the most selected players in
		 * the fantasy game.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getMostSelected: function(code, successDelegate, failureDelegate) {
			throw "getMostSelected not implemented";
		},
		
		/**
		 * getMostSelectedByType - Should return a list of the most selected players in
		 * the fantasy game based on type.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getMostSelectedByType: function(type, code, successDelegate, failureDelegate) {
			throw "getMostSelectedByType not implemented";
		},
		
		/**
		 * getMostSelectedByTeam - Should return a list of the most selected players in
		 * the fantasy game based on team.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getMostSelectedByTeam: function(team, code, successDelegate, failureDelegate) {
			throw "getMostSelectedByTeam not implemented";
		},
		
		/**
		 * getOverallManagers - Should return a list of the best fantasy managers.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getOverallManagers: function(code, successDelegate, failureDelegate) {
			throw "getOverallManagers not implemented";
		},
		
		/**
		 * getTeams - Should return a list of teams, each team should be a hash with keys
		 * id and name.
		 **/
		getTeams: function(code, successDelegate, failureDelegate) {
			throw "getTeams not implemented";
		},
		
		/**
		 * getTypes - Should return a list of player types, each type should be a hash with keys
		 * id and name.
		 **/
		getTypes: function(code, successDelegate, failureDelegate) {
			throw "getTypes not implemented";
		}
	});
	
	// Mock Fantasy Service implementation for testing
	$.fs.fantasy.service.mock = $.klass($.fs.fantasy.service.intaface, {
		defaults: {
		},
		
		initialize: function() {
		},
		
		getHighestScorers: function(code, successDelegate, failureDelegate) {
			setTimeout(function() {
				successDelegate.call(this, [
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"},
					{"cost":"7.2","web_name":"Ma'a Nonu","value":"381","type":"Inside Back","id":"1220","team":"Hurricanes","team_code":"HUR"},
					{"cost":"5.1","web_name":"Tanerau Latimer","value":"370","type":"Backrow","id":"957","team":"Chiefs","team_code":"CHI"},
					{"cost":"6.8","web_name":"Pierre Spies","value":"370","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"3.9","web_name":"Thomas Waldrom","value":"362","type":"Backrow","id":"1350","team":"Crusaders","team_code":"CRU"},
					{"cost":"7.2","web_name":"Isaia Toeava","value":"361","type":"Inside Back","id":"953","team":"Blues","team_code":"BLU"},
					{"cost":"6.4","web_name":"Luke Watson","value":"357","type":"Backrow","id":"1191","team":"Stormers","team_code":"STO"},
					{"cost":"7.7","web_name":"David Pocock","value":"355","type":"Backrow","id":"939","team":"Western Force","team_code":"WES"},
					{"cost":"11.4","web_name":"Matt Giteau","value":"345","type":"Inside Back","id":"1243","team":"Western Force","team_code":"WES"},
					{"cost":"5.6","web_name":"Adam Thompson","value":"331","type":"Backrow","id":"1174","team":"Highlanders","team_code":"HIG"}
				]);
			}, Math.random() * 1000);
		},
		
		getHighestScorersByType: function(type, code, successDelegate, failureDelegate) {
			setTimeout(function() {
				successDelegate.call(this, [
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"},
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"},
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"},
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"},
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"},
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"},
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"},
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"},
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"},
					{"cost":"7.9","web_name":"Liam Messam","value":"406","type":"Backrow","id":"947","team":"Chiefs","team_code":"CHI"}
				]);
			}, Math.random() * 1000);
		},
		
		getHighestScorersByTeam: function(team, code, successDelegate, failureDelegate) {
			setTimeout(function() {
				successDelegate.call(this, [
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"}
				]);
			}, Math.random() * 1000);
		},
		
		getMostSelected: function(code, successDelegate, failureDelegate) {
			setTimeout(function() {
				successDelegate.call(this, [
					{"cost":"6.8","web_name":"Pierre Spies","value":"12955","type":"Backrow","id":"1204","team":"Bulls","team_code":"BUL"},
					{"cost":"5.3","web_name":"Morn Steyn","value":"12276","type":"Inside Back","id":"1301","team":"Bulls","team_code":"BUL"},
					{"cost":"6.1","web_name":"Lelia Masaga","value":"11982","type":"Outside Back","id":"946","team":"Chiefs","team_code":"BUL"},
					{"cost":"7.1","web_name":"Mils Muliaina","value":"11171","type":"Outside Back","id":"242","team":"Chiefs","team_code":"BUL"},
					{"cost":"7.9","web_name":"Liam Messam","value":"10928","type":"Backrow","id":"947","team":"Chiefs","team_code":"BUL"},
					{"cost":"2.3","web_name":"Arizona Taumalolo","value":"10735","type":"Prop","id":"3479","team":"Chiefs","team_code":"BUL"},
					{"cost":"5.1","web_name":"Tanerau Latimer","value":"10590","type":"Backrow","id":"957","team":"Chiefs","team_code":"BUL"},
					{"cost":"5.2","web_name":"Rory Kockott","value":"9793","type":"Scrum Half","id":"1465","team":"Sharks","team_code":"BUL"},
					{"cost":"6.9","web_name":"Fourie du Preez","value":"9757","type":"Scrum Half","id":"1186","team":"Bulls","team_code":"BUL"},
					{"cost":"8.1","web_name":"Stephen Donald","value":"9652","type":"Inside Back","id":"1268","team":"Chiefs","team_code":"BUL"}
				]);
			}, Math.random() * 1000);
		},
		
		getMostSelectedByType: function(type, code, successDelegate, failureDelegate) {
		},

		getMostSelectedByTeam: function(team, code, successDelegate, failureDelegate) {
		},
		
		getOverallManagers: function(code, successDelegate, failureDelegate) {
			setTimeout(function() {
				failureDelegate.call(this, [
					{"player_name":"jason munday","overall_rank":"1","overall_score":"987","round_score":"63","team_name":"mooney town","team_code":"BUL","id":"2496"},
					{"player_name":"Alex Macdonald","overall_rank":"2","overall_score":"924","round_score":"70","team_name":"Ask your mum","team_code":"BUL","id":"22417"},
					{"player_name":"Lyn Doyle","overall_rank":"3","overall_score":"923","round_score":"79","team_name":"lyns11","team_code":"BUL","id":"35"},
					{"player_name":"jamie wareham","overall_rank":"4","overall_score":"923","round_score":"63","team_name":"fingerbashing rovers","team_code":"BUL","id":"2975"},
					{"player_name":"Daniel Barker","overall_rank":"5","overall_score":"921","round_score":"74","team_name":"FC Barkerlona","team_code":"BUL","id":"3197"},
					{"player_name":"Michael Haddad","overall_rank":"6","overall_score":"920","round_score":"50","team_name":"Thanks 4 da Tim Tams","team_code":"BUL","id":"1039"},
					{"player_name":"Braden Mewing","overall_rank":"7","overall_score":"918","round_score":"65","team_name":"Vitale Ferrante","team_code":"BUL","id":"4985"},
					{"player_name":"Darren Snowdon","overall_rank":"8","overall_score":"917","round_score":"56","team_name":"Viva La Mullet","team_code":"BUL","id":"12922"},
					{"player_name":"John M","overall_rank":"9","overall_score":"915","round_score":"60","team_name":"Kwasnik is a Gun!","team_code":"BUL","id":"10311"},
					{"player_name":"stan  tag","overall_rank":"10","overall_score":"914","round_score":"64","team_name":"Beresfield All Stars","team_code":"BUL","id":"7762"}
				]);
			}, Math.random() * 1000);
		},
		
		getTeams: function(code, successDelegate, failureDelegate) {
			successDelegate.call(this, $.fs.ism.teams[code]);
		},

		getTypes: function(code, successDelegate, failureDelegate) {
			successDelegate.call(this, $.fs.ism.types[code]);
		}		
	});
	
	// JSON based Fantasy Service implementation
	$.fs.fantasy.service.json = $.klass($.fs.fantasy.service.intaface, {
		defaults: {
			path: "http://www.foxsports.com.au/xmlfeed/ism/feeds"
		},
		
		initialize: function(opts) {
			this.opts = $.extend({}, this.defaults, opts);
			
			// Used to store cached data (so we don't have to reload data)
			// We cache each code separately
			this.cachedData = {};
		},
		
		// Private helper method to load the data (handles caching as well)
		_loadData: function(code, fileName, successDelegate, failureDelegate) {
			var self = this;
			
			// ID for caching
			var uniqueId = code + fileName;
			
			// Once data has loaded (from cache or remotely) then find round we want
			var dataLoaded = function(data) {
				// Cache it
				self.cachedData[uniqueId] = data;
				successDelegate.call(self, data.playerStatistics.playerStatistic.players.player);
			};
			
			if (this.cachedData[uniqueId] === undefined) {
				$.ajax({
					type: "GET",
					url: this.opts.path + "/foxau_" + code + "f/" + fileName,  
					data: { cacheBuster: parseInt(Math.random() * 1000000000, 10) },
					success: dataLoaded,
					error: failureDelegate,
					dataType: "json"
				});	
			} else {
				// We know cache data is success, because it only gets cached if success
				dataLoaded(this.cachedData[uniqueId]);
			}
		},
		
		getHighestScorers: function(code, successDelegate, failureDelegate) {
			this._loadData(code, "elements_total.json", successDelegate, failureDelegate);
		},
		
		getHighestScorersByType: function(type, code, successDelegate, failureDelegate) {
			this._loadData(code, "elements_type_" + type + "_total.json", successDelegate, failureDelegate);
		},
		
		getHighestScorersByTeam: function(team, code, successDelegate, failureDelegate) {
			this._loadData(code, "elements_team_" + team + "_total.json", successDelegate, failureDelegate);
		},
		
		getMostSelected: function(code, successDelegate, failureDelegate) {
			this._loadData(code, "elements_selected.json", successDelegate, failureDelegate);
		},
		
		getMostSelectedByType: function(type, code, successDelegate, failureDelegate) {
			this._loadData(code, "elements_type_" + type + "_selected.json", successDelegate, failureDelegate);
		},

		getMostSelectedByTeam: function(team, code, successDelegate, failureDelegate) {
			this._loadData(code, "elements_team_" + team + "_selected.json", successDelegate, failureDelegate);
		},
		
		getOverallManagers: function(code, successDelegate, failureDelegate) {
			// TODO: Need to implement this method properly (right now always failing)
			failureDelegate.call(this);
		},
		
		getTeams: function(code, successDelegate, failureDelegate) {
			successDelegate.call(this, $.fs.ism.teams[code]);
		},

		getTypes: function(code, successDelegate, failureDelegate) {
			successDelegate.call(this, $.fs.ism.types[code]);
		}		
	});
})(jQuery);// jquery.fs.fantasymodule
// Fox Sports Fantasy Module
// (c)2009 Edmond Leung/Fox Sports
//
// Adds JS functionality to a fantasy module.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('.fantasy-module').fs.fantasymodule();

(function($) {    
    var functions = {
    	getTeamID: function(fantasyModule, teamName) {
    		var self = $(fantasyModule);
    		var teams = self.data('fantasyTeams');
    		
    		var teamID = undefined;
    		
    		$.each(teams, function(i, team) {
    			if (team.name == teamName) { teamID = team.id; }
    		});
    		
    		return teamID;
    	},
    	
    	getTypeID: function(fantasyModule, typeName) {
    		var self = $(fantasyModule);
    		var types = self.data('fantasyTypes');
    		
    		var typeID = undefined;
    		
    		$.each(types, function(i, type) {
    			if (type.name == typeName) { typeID = type.id; }
    		});
    		
    		return typeID;
    	},
    	
    	generateFilter: function(fantasyModule) {
    		var self = $(fantasyModule);
    		
    		// Retrieve stored variables
    		var code = self.data('fantasyCode');
    		var service = self.data('fantasyService');
    		var teams = self.data('fantasyTeams');
    		var types = self.data('fantasyTypes');
    		
    		var filter = $("<select name='fantasy-filter'></select>");
    		
    		$('<option>Overall Score</option>').appendTo(filter);
    		$('<option>Most Selected</option>').appendTo(filter);
    		
    		// Add types
    		$.each(types, function(i, type) {
    			$('<option>' + type.name + '</option>').appendTo(filter);
    		});
    		
    		// Add teams
    		$.each(teams, function(i, team) {
    			$('<option>' + team.name + '</option>').appendTo(filter);
    		});
    		
    		$('<option>Overall Managers</option>').appendTo(filter);
    		
        	// On filter change, then reload the data
        	filter.change(function() {
        		functions.reloadData.call(self, $(this).val());
        	});
        	
        	// Set the default filter
        	var filterWrapper = self.find('.fantasy-filter');
        	var defaultFilter = filterWrapper.attr('title');
        	if (defaultFilter !== "" && defaultFilter !== undefined) {
        		filter.val(defaultFilter);
        	}
        	
    		functions.reloadData.call(self, filter.val());
    		
    		return filter;
    	},
    	
    	generateHeader: function(fantasyModule, dataType) {
    		var headerRow = $("<tr></tr>");
    		
    		// Different header fields bnase
    		var headerFields;
    		if (dataType == $.fs.fantasy.datatype.Managers) {
    			headerFields = [
	    			{ id: "overall_rank", name: "Rank" },
	    			{ id: "player_name", name: "Player" },
	    			{ id: "team_name", name: "Team" },
	    			{ id: "overall_score", name: "Score" }
    			];
			} else {
    			headerFields = [
	    			{ id: "web_name", name: "Player" },
	    			{ id: "team", name: "Team" },
	    			{ id: "type", name: "Position" },
	    			{ id: "cost", name: "Price" },
	    			{ id: "value", name: "Points", abbr: "Pts" }
    			];
			}
    		
    		$.each(headerFields, function(i, column) {
    			$('<th></th>').addClass(column.id)
    					      .attr('abbr', column.abbr || column.name)
    					      .attr('title', column.name)
    					      .appendTo(headerRow)
    					      .text(column.abbr || column.name);
    		});
    		
    		return headerRow;
    	},
    	
    	generateTable: function(fantasyModule, data, dataType) {
    		var table = $("<table><tbody></tbody></table>");
    		var tbody = table.find('tbody');
    		
    		// Generate the header row
			functions.generateHeader(fantasyModule, dataType).appendTo(tbody);
    		
    		// Generate the data
    		$.each(data, function(i, record) {
    			var dataRow = $("<tr></tr>").appendTo(tbody);
    			var fieldNames;
    			
    			// Different fields based on what type of record was returned
    			if (dataType == $.fs.fantasy.datatype.Managers) {
					fieldNames = ["overall_rank", "player_name", { abbr: "team_code", actual: "team_name" }, "overall_score"];			
    			} else {
    				fieldNames = ["web_name", { abbr: "team_code", actual: "team" }, "type", "cost", "value"];
    			}
    			
    			$.each(fieldNames, function(i, fieldName) {
    				var toolTipFieldName;
    				
    				// Get tooltip
    				if (typeof(fieldName) != "string") {
    					toolTipFieldName = fieldName.actual;
    					fieldName = fieldName.abbr;
    				}
    				
    				var td = $('<td></td>').addClass(fieldName).appendTo(dataRow);
    				var span = $('<span></span>').appendTo(td).text(record[fieldName]);
    				
    				// Add tooltip
    				if (toolTipFieldName !== undefined) {
    					span.attr('title', record[toolTipFieldName]);
    				}
    			});
    		});
    		
    		// Add first and last classes
    		table.find('th:first-child, td:first-child').addClass('first');
    		table.find('th:last-child, td:last-child').addClass('last');
    		
    		return table;
    	},
    	
    	reloadFilter: function() {
    		var self = $(this);
    		
    		// Only load filter if both teams and types have been loaded
    		if (!self.data('fantasyTeams') || !self.data('fantasyTypes')) { return; }
    		
    		var filter = functions.generateFilter(this);
    		var currentFilter = self.find('select[name=fantasy-filter]');
    		
    		// Add new filter, then remove old one
    		currentFilter.after(filter);
    		currentFilter.remove();
    	},
    	
    	reloadData: function(filterName) {
    		var self = $(this);
    		var parentModule = self.closest('.module');
    		
    		// Retrieve stored variables
    		var code = self.data('fantasyCode');
    		var service = self.data('fantasyService');
    		var opts = self.data('fantasyOptions');
    		
    		// Default data type is Players mode
    		var dataType = $.fs.fantasy.datatype.Players;
    		
    		// Success call back method (called when data is successfully loaded)
    		var success = function(data) {
	    		self.find('table, p.module-error').remove();
	    		self.find('.fantasy-filter').after(functions.generateTable(self, data, dataType));
	    		
	    		// Data has loaded, no longer in 'loading' state
    			parentModule.removeClass('loading');
    		};
    		
    		var failure = function() {
    			// Show error message, and stop loading indicator
    			self.find('table, p.module-error').remove();
    			
    			var fantasyFilter = self.find('.fantasy-filter');
    			var filterSelect = self.find('select[name=fantasy-filter]');
    			
    			var errorMessage = $('<p class="module-error"></p>').text(opts.errorMessage);
    			var tryAgainLink = $('<a href="#reload-fantasy">Please try again.</a>').click(function() {
    				functions.reloadData.call(self, filterSelect.val());
    				return false;
    			}).appendTo(errorMessage);
    			
    			fantasyFilter.after(errorMessage);
    			
    			parentModule.removeClass('loading');
    		};
    		
    		// Let CSS know the module is in 'loading' state
    		parentModule.addClass('loading');
    		
    		// Retrieve data based on filter selected
    		switch (filterName) {
    			case "Overall Score":
    				service.getHighestScorers(code, success, failure);
    				break;
    			case "Most Selected":
    				service.getMostSelected(code, success, failure);
    				break;
    			case "Overall Managers":
    				service.getOverallManagers(code, success, failure);
    				dataType = $.fs.fantasy.datatype.Managers;
    				break;
    		}
    		
    		// Handle team and type filters
    		var teamID = functions.getTeamID(this, filterName);
    		var typeID = functions.getTypeID(this, filterName);
    		
    		if (teamID !== undefined) {
    			service.getHighestScorersByTeam(teamID, code, success, failure);
			} else if (typeID !== undefined) {
    			service.getHighestScorersByType(typeID, code, success, failure);
    		}
    	}
    };
    
    // Create fs.fantasymodule jquery call
    $.namespace('fn.fs', {
        fantasymodule: function(service, opts) {
            opts = $.extend({}, $.fn.fs.fantasymodule.defaults, opts);

            return this
                .each(function() {
                	var self = $(this);
                	var parent = self.closest('.module');
                	
                	// Inject loading indicator
                	var moduleHeader = parent.find('.module-header');
                	var loadingIndicator = $('<span class="module-load-indicator">Loading...</span>').appendTo(moduleHeader);
                	
                	// Get the sport code this fantasy module represents
                	var code = null;
                	var classNames = parent.attr('class').toLowerCase().split('-').join('').split(' ');
                	$.each($.fs.ism.teams, function(key, value) {
                		if ($.inArray(key, classNames) > -1) { code = key; }	
                	});

                	// Exit if no code found
                	if (code === null) { return; }
                	
                	// Find the filter select box
                	var filter = self.find('select[name=fantasy-filter]');
                	
                	// Store variables so we can use later
                	self.data('fantasyService', service);
                	self.data('fantasyCode', code);
                	self.data('fantasyOptions', opts);
                	
                	// Load teams then attempt to reload filter
                	var loadTeams = function(teams) {
                		self.data('fantasyTeams', teams);
                		functions.reloadFilter.call(self);
                	};
                	
                	// Load types then attempt to reload filter
                	var loadTypes = function(types) {
                		self.data('fantasyTypes', types);
                		functions.reloadFilter.call(self);
                	};
                	
                	// Grab the data and pass into above callback methods
                	service.getTeams(code, loadTeams);
                	service.getTypes(code, loadTypes);
                });
        }
    });
    
    // Setup defaults for fantasymodule plugin
    $.namespace('fn.fs.fantasymodule', {
        defaults: {
        	errorMessage: "Unable to load the required data. "
        }
    });
})(jQuery);// jquery.fs.filterform
// Fox Sports Filter Form
// (c)2009 Brendan Cartledge/Fox Sports
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('form').fs.filterform();

(function($) {    
    var functions = {
    };
    
    // Create fs.filterform jquery call
    $.namespace('fn.fs', {
        filterform: function(opts) {     
            opts = $.extend({}, $.fn.fs.filterform.defaults, opts);

            return this
                .each(function() {
                	var self = $(this);
                	
                	self.find('select').change( function() {
                		
                		//make sure not to submit the "select team" etc option.
                		//for these, the value will be empty.
                		var thisval = $(this).find('option:selected').val();
                		
                		if(thisval !== "")
                		{
                			self[0].submit();
                		}
                		
                		                		
	                	// Make sure submit doesn't call non-ajax submit
	                	self.submit(function(e) {
	                		e.preventDefault();
	                		e.stopPropagation();
	                	});
                	});
				    
                });
        },
        footballteamfilter: function(opts) {     
            opts = $.extend({}, $.fn.fs.footballteamfilter.defaults, opts);

            return this
                .each(function() {
                	var self = $(this);
                	
                	//only the epl and aleague will be abel to filter by team
                	//at the moment all of this is hardcoded (the first number is teamid in the db)
                	//but this could be changed easily to call a json file in the future
                	var epl = [['4282','Arsenal'],['4281','Aston Villa'],['4312','Birmingham'],['4293','Blackburn'],['4289','Bolton'],['4313','Burnley'],['4280','Chelsea'],['4283','Everton'],['4286','Fulham'],['4288','Hull'],['4279','Liverpool'],['4287','Man City'],['4278','Man United'],['4256','Portsmouth'],['4292','Stoke'],['4290','Sunderland'],['4291','Tottenham'],['4285','West Ham'],['4284','Wigan'],['4314','Wolverhampton']];
                	var aleague = [['123','Adelaide'],['122','Brisbane'],['346','Central Coast'],['56','Gold Coast'],['324','Melbourne'],['3456','Newcastle'],['64534','North Qld'],['1214','Perth'],['221','Sydney'],['176','Wellington']];
                	
                	self.find('select').change( function() {
                		var updateform = self.siblings('form');
                		
                		//get the selected compid
                		var compid = self.find('select option:selected').val();
                		
                		//empty all the options from the team listing select
                		updateform.find('option').remove();
                		
                		var i = 0;
                		
                		if(compid == 'EPL')
                		{
                			for(i = 0; i < epl.length; i++) 
                			{
                				updateform.find('select').removeAttr("disabled");
                				updateform.find('select').append($("<option></option>").attr("value",epl[i][0]).text(epl[i][1]));
                			}
                		}
                		else if(compid == 'A-League')
                		{
                			for(i = 0; i < aleague.length; i++) 
                			{
                				updateform.find('select').removeAttr("disabled");
                				updateform.find('select').append($("<option></option>").attr("value",aleague[i][0]).text(aleague[i][1]));
                			}
                		}
                		else
                		{
                			//for any other league, disable the team select box
                			updateform.find('select').attr("disabled","disabled");
                		}

                	});
				    
                });
        }
    });
    
    // Setup defaults for filterform plugin
    $.namespace('fn.fs.filterform', {
        defaults: {
        }
    });
    
    $.namespace('fn.fs.footballteamfilter', {
        defaults: {
        }
    });
    
})(jQuery);// jquery.fs.fontsizer
// Fox Sports Font Sizer
// (c)2009 Edmond Leung/Fox Sports
//
// Gives users the ability to change the font size of selected elements,
// by using the buttons specified in the options. An element ID is required
// on elements with font-sizes you want persisted with cookies.
// 
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('#story-body').fs.fontsizer({
//    increaseButtons: '.js-font-inc',
//    decreaseButtons: '.js-font-dec'
// });

(function($) {    
    var functions = {
        // Update the font size based on growing direction (negative to shrink)
        changeByDirection: function(direction, opts) {
            var element = $(this);
            
            var fontSize = parseInt(element.css('font-size'), 10);
            var level = $.inArray(fontSize, opts.fontSizes) + direction;
            
            // Clamp the font size
            if (level >= opts.fontSizes.length) {
                level = opts.fontSizes.length - 1;
            } else if (level < 0) {
                level = 0;
            }
            
            // After finding level using direction and current size,
            // change the font size
            functions.changeBySizeLevel.call(this, level, opts);
        },
        
        // Update the font size by setting the font size level directly
        changeBySizeLevel: function(level, opts) {
            var element = $(this);
            
            var newFontSize = opts.fontSizes[level];
            var newLineHeight = opts.lineHeights[level];
            
            element.css({ 
                "fontSize": newFontSize,
                "lineHeight": newLineHeight + "px"
            });
            
            // Persist with cookies
            var elementID = element.attr('id');
            if (elementID !== undefined) {
                $.cookie(elementID + "_font-size-level", level);
            }
            
            // Call callback function
            opts.afterResize.call(this);
        },
        
        // Change a list of elements by direction
        changeAllByDirection: function(direction, opts) {
            this.each(function() {
                functions.changeByDirection.call(this, direction, opts);
            });
        },
        
        // Change a list of elements by font size level
        changeAllBySizeLevel: function(level, opts) {
            this.each(function() {
                functions.changeBySizeLevel.call(this, level, opts);
            });
        }
    };
    
    // Create fs.fontsizer jquery call
    $.namespace('fn.fs', {
        fontsizer: function(opts) {     
            var self = $(this);
            opts = $.extend({}, $.fn.fs.fontsizer.defaults, opts);
            
            // Button click event for increasing/decreasing
            var buttonClick = function(direction) {
                var button = $(this);
                
                // Store old position and old scrolling position
                var beforePosition = button.offset();
                var beforeScrollTop = $(window).scrollTop();
                
                // Do the change
                functions.changeAllByDirection.call(self, direction, opts);
                
                // Now auto scroll the page to correct position
                var afterPosition = button.offset();
                var positionDifference = parseInt(afterPosition.top - beforePosition.top, 10);
                var afterScrollTop = beforeScrollTop + positionDifference;
                
                $(window).scrollTop(afterScrollTop);
            };
            
            var increaseClick = function() {
                buttonClick.call(this, 1);
                return false;
            };
            
            var decreaseClick = function() {
                buttonClick.call(this, -1);
                return false;
            };
            
            var oldIncreaseClick = self.data('increaseClickHandler');
            var oldDecreaseClick = self.data('decreaseClickHandler');
            
            if (oldIncreaseClick) {
            	$(opts.increaseButtons).unbind('click', oldIncreaseClick);
            }
            
            if (oldDecreaseClick) {
            	$(opts.decreaseButtons).unbind('click', oldDecreaseClick);
            }
            
            // Increase with positive direction
            $(opts.increaseButtons).click(increaseClick);
            self.data('increaseClickHandler', increaseClick);
            
            // Decrease with negative direction
            $(opts.decreaseButtons).click(decreaseClick);
            self.data('decreaseClickHandler', decreaseClick);
            
            return this.each(function() {
                // Load persisted size levels
                var element = $(this);
                var elementID = element.attr('id');
                
                if (elementID !== undefined) {
                    var level = $.cookie(elementID + "_font-size-level");
                    if (level !== undefined && level !== null) { functions.changeBySizeLevel.call(this, level, opts); }
                }
            });
        }
    });
    
    // Setup defaults for fontsizer plugin
    $.namespace('fn.fs.fontsizer', {
        defaults: {
            persistentIdentifier: "",               // Unique id for persisting font level
            fontSizes: [ 11, 13, 16, 19, 23 ],      // Default font sizes
            lineHeights: [ 17, 19, 23, 27, 32 ],    // Default line heights
            increaseButtons: "",                    // The buttons that will increase the size
            decreaseButtons: "",                    // The buttons that will decrease the size
            afterResize: function() {}				// Callback, called when resize has occured ('this' is the element that was resized)
        }
    });
})(jQuery);// jquery.fs.formbuilder
// Fox Sports FormBuilder Implementation (based on Foundations Form Builder)
// (c)2009 Edmond Leung/Fox Sports
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('form').fs.formbuilder();

(function($) {    
    var functions = {
    };
    
    // Create fs.formbuilder jquery call
    $.namespace('fn.fs', {
        formbuilder: function(opts) {     
            opts = $.extend({}, $.fn.fs.formbuilder.defaults, opts);

            return this
                .each(function() {
                	var self = $(this);
                	var jsEnabledInput = $('<input type="hidden" name="jsEnabled" value="true"/>').appendTo(self);
                	
                	// Convert to validation engine compatible classes
                	var fields = self.find('.required-field, .email');
                	fields.each(function() {
                		var field = $(this);
                		var validations = [];
                		
                		if (field.hasClass('required-field')) { validations.push('required'); }
                		if (field.hasClass('email')) { validations.push('custom[email]'); }
                		
                		// Add the class required by validation engine
                		if (validations.length > 0) {
                			field.attr('className', 'validate[' + validations.join(',') + '] ' + field.attr('className'));	
                		}                		
                	});
                	
                	// Make sure submit doesn't call non-ajax submit
                	self.submit(function(e) {
                		e.preventDefault();
                		e.stopPropagation();
                	});
                	
				    // Use validation engine
					self.validationEngine({
						beforeSuccess: function() {
							$.ajax({
								type: 'POST',
								url: self.attr('action'),
								data: self.serialize(),
								success: function(response) {
									var result = $.trim(response);			        
									self.trigger('submitsuccess', result);
								},
								failure: function() {
									self.trigger('submitfailure', result);
								}
							});
						},
						failure: function() {}
					});
                });
        }
    });
    
    // Setup defaults for formbuilder plugin
    $.namespace('fn.fs.formbuilder', {
        defaults: {
        }
    });
})(jQuery);// jquery.fs.formchecktranslator
// Fox Sports Form Check Translator
// Translates MooTools formcheck class names to jquery form validation class names
// (c)2010 Edmond Leung/Fox Sports
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('form').fs.formchecktranslator();

function validateByLength(el, len) {
	var valid = false;
	var words = $(el).attr('value');
	
	// Trim leading and trailing whitespace
	var cleanWords = words.replace(/\s+/g, ' ').trim();
	var wordArray = cleanWords.split(' ');
	
	if (wordArray.length <= len) {
		valid = true;
	}
	
	return valid;
}

function customMax25Validation(el) {
	return validateByLength(el, 25);
}

function customMax50Validation(el) {
	return validateByLength(el, 50);
}

function customMax100Validation(el) {
	return validateByLength(el, 100);
}

(function($) {    
    var functions = {
    	replaceClass: function(className, replaceClassName) {
    		var self = $(this);
    		className.replace(/\]/g, "\\" + "]");
    		className.replace(/\[/g, "\\" + "[");
    		self.find('*[class=' + className + ']').each(function() {
    			var element = $(this);
    			element.removeClass(className);
    			element.addClass(replaceClassName);
    		});
    	}
    };
    
    // Create fs.formchecktranslator jquery call
    $.namespace('fn.fs', {
        formchecktranslator: function(opts) {     
            opts = $.extend({}, $.fn.fs.formchecktranslator.defaults, opts);
            
            return this
                .each(function() {
                	var self = $(this);
                	
                	// Translate class names so validationEngine can understand them
                	functions.replaceClass.call(this, "validate['required']", "validate[required]");
                	functions.replaceClass.call(this, "validate['required','email']", "validate[required,custom[email]]");
                	functions.replaceClass.call(this, "validate['required','digit[1900,2009]']", "validate[required,custom[onlyNumber],length[4,4]]");
                	functions.replaceClass.call(this, "validate['required','digit']", "validate[required,custom[onlyNumber]]");
                	functions.replaceClass.call(this, "validate['required','%customMax25Validation']", "validate[required,funcCall[customMax25Validation]]");
                	functions.replaceClass.call(this, "validate['required','%customMax50Validation']", "validate[required,funcCall[customMax50Validation]]");
                	functions.replaceClass.call(this, "validate['required','%customMax100Validation']", "validate[required,funcCall[customMax100Validation]]");
                	
                	// Add id to radio buttons to avoid validation errro
                	self.find('input[type=radio],input[type=checkbox]').each(function() {
                		var radio = $(this);
                		radio.attr('id', parseInt(Math.random() * 1000000000, 10));
                	});
                	
                	self.find('input[type=radio][class*=validate]').each(function() {
                		var radio = $(this);
                		radio.closest('.field').find('input').attr('class', radio.attr('class'));
                	});
                	
                	// Then activate validation engine
					self.validationEngine({
						validationEventTriggers: 'blur',
						liveEvent: false
					});
                });
        }
    });
    
    // Setup defaults for formchecktranslator plugin
    $.namespace('fn.fs.formchecktranslator', {
        defaults: {
        }
    });
})(jQuery);// jquery.fs.watermark
// Fox Sports Watermarked Textbox
// (c)2009 Edmond Leung/Fox Sports
//
// Creates a watermark for textboxes (default text when textbox is empty).
// The textbox uses the contents of its 'title' attribute as the watermark text.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('input').fs.freetable();

(function($) {    
    var functions = {
        removeAttribs: function(opts) {
            var self = $(this);
            self.attr("border","0");
			self.attr("cellspacing","0");
			self.attr("cellpadding","0");
        }
    };
    
    // Create fs.freetable jquery call
    $.namespace('fn.fs', {
        freetable: function(opts) {     
            opts = $.extend({}, $.fn.fs.freetable.defaults, opts);

            return this
                .each(function() { 
                    var self = $(this);                                        
                    functions.removeAttribs.call(this, opts);
                    
					self.find("td:first-child").addClass('first');
					self.find("td:last-child").addClass('last');
                });
        }
    });
    
    // Setup defaults for freetable plugin
    $.namespace('fn.fs.freetable', {
        defaults: {
           
        }
    });
})(jQuery);// jquery.fs.gallery
// Fox Sports Gallery
// (c)2009 Brendan Cartledge/Fox Sports
//
// Creates a gallery slider functionality for gallery pages.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
// jquery.tools.scrollable.navigator.js
//
// Usage:
// $('input').fs.gallery();  for the main thumbnail gallery scroller
// $('input').fs.moregalleries();  for the more galleries scroller

(function($) {    
    var functions = {
    };
    
    // Create fs.gallery jquery call
    $.namespace('fn.fs', {
        gallery: function(opts) {     
            opts = $.extend({}, $.fn.fs.gallery.defaults, opts);
			
            return this
            	.each(function() { 
                	var self = $(this);
                	
                	// Show preroll for a certain amount of time if we're on preroll page
                	if (self.hasClass('gallery-preroll')) {
                		// Use the link in the skip link, and redirect to it once preroll is finished
                		setTimeout(function() {
                    		var skipLinkHref = self.find('.skip-link').attr('href');
                    		window.location = skipLinkHref;
                		}, opts.prerollAdDelay);
                	} else {
                    	var navi = self.find(".gal-pages");
                    	if (navi.size() === 0) {
                    		navi = $('<ul class="gal-pages"></ul>').appendTo(self.find('.gal-sels'));
                    	}
                    	
                    	var size = opts.imagesPerPage;
    					
    					// Count the number of items in the gallery, write the 
    					// Correct number of page navigators
    					var count = Math.ceil(self.find(".gal-items .gal-thumb").size() / size);
    					var i = 1;
    					while(i <= count)
    					{
    						navi.append("<li><a class='gal-sel' title='Page " + i + "'>" + i + "</a></li>");
    						i++;
    					}
    					
    					var galleryNavigation = self.find('.gallery-navigation');
    					var api = galleryNavigation.scrollable({
    						api: true,
    			    		items: ".gal-items",
    			    		item: ".gal-thumb",
    			            nextPage: ".gal-right-nav",
    			            prevPage: ".gal-left-nav",
    			            size: size,
    			            clickable: false,
    			            keyboard: false
                    	});
    					
    					galleryNavigation.navigator({
                    		navi: ".gal-pages li",
                    		indexed: true,
                    		activeClass: "gal-sel-active"
                    	});
    					
    					// Scroll to the currently active gallery image
    					var activeThumb = self.find('.gal-active');
    					api.seekTo(galleryNavigation.find('.gal-thumb').index(activeThumb), 0);
                    	
    					// Add effects to show previous and next image buttons on rollover
                    	self.find('.gal-prev-img, .gal-next-img')
                    		.each(function() {
                    			$(this).css({
                    				opacity: 0,
                    				display: 'block'
                    			});
    	                	})
    	                	.hover(function() {
    	                		if ($.support.opacity) {
    	                			$(this).animate({ opacity: 1.0 }, "fast");	
    	                		} else {
    	                			$(this).css({
    	                				opacity: null
    	                			});
    	                		}
    	                	}, function() {
    	                		if ($.support.opacity) {
    	                			$(this).animate({ opacity: 0 }, "fast");	
    	                		} else {
    	                			$(this).css({
    	                				opacity: 0
    	                			});
    	                		}
    	                	});
                	}
                });
	        },
        moregalleries: function(opts) {     
            opts = $.extend({}, $.fn.fs.gallery.defaults, opts);

			
            return this
            	.each(function() { 
                	var self = $(this);
                	
					var moreGalleriesContainer = self.find('#more-galleries-cont');
					var api = moreGalleriesContainer.scrollable({
						api: true,
                		items: ".more-gallery-container",
			    		item: ".more-gallery-items",
			            nextPage: ".more-gal-right-nav a",
			            prevPage: ".more-gal-left-nav a",
			            size: 1,
			            clickable: false,
			            keyboard: false
                	});
					
					moreGalleriesContainer.navigator({
						navi: ".more-gal-sels",
						naviItem: "li.more-gal-sel a",
                		activeClass: "more-gal-sel-active"
                	});

					// Scroll to the currently active gallery image by finding the active page
					var activePage = self.find('.active-gallery').closest('.more-gallery-items');
					api.seekTo(moreGalleriesContainer.find('.more-gallery-items').index(activePage), 0);
                	
					// Add effect to show/hide gallery description on roll over
                	self.find('.more-gallery-description a')
                		.each(function() {
                			$(this).css({
                				opacity: 0,
                				display: 'block'
                			});
	                	})
	                	.hover(function() {
	                		var a = $(this);
	                		
	                		if ($.support.opacity) {
	                			a.animate({ opacity: 1.0 }, "fast");	
	                		} else {
	                			a.css('opacity', null);
	                		}
	                	}, function() {
	                		var a = $(this);
	                		
	                		if ($.support.opacity) {
	                			a.animate({ opacity: 0 }, "fast");	
	                		} else {
	                			a.css('opacity', 0);
	                		}
	                	});
                });
        }        
    });
    
    // Setup defaults for gallery plugin
    $.namespace('fn.fs.gallery', {
        defaults: {
    		imagesPerPage: 5,		// Number of images shown in each page
    		prerollAdDelay: 5000	// How long to show the preroll ad in milliseconds
        }
    });
})(jQuery);

    
    
(function($) {
	// List of ism based teams id/name mappings
	$.namespace('fs.ism.teams', {
		aleague: [
			{ id: 60001, name: "Adelaide" },
			{ id: 60006, name: "Brisbane" },
			{ id: 60002, name: "Central Coast" },
			{ id: 60208, name: "Gold Coast" },
			{ id: 60003, name: "Melbourne" },
			{ id: 60004, name: "Newcastle" },
			{ id: 60209, name: "North Queensland" },
			{ id: 60005, name: "Perth" },
			{ id: 60007, name: "Sydney" },
			{ id: 60008, name: "Wellington" }
		],
		
		s14: [
			{ id: 50012, name: "Blues" },
			{ id: 50002, name: "Brumbies" },
			{ id: 50007, name: "Bulls" },
			{ id: 50014, name: "Cheetah" },
			{ id: 50010, name: "Chiefs" },
			{ id: 50001, name: "Crusaders" },
			{ id: 50003, name: "Highlanders" },
			{ id: 50011, name: "Hurricanes" },
			{ id: 50009, name: "Lions" },
			{ id: 50005, name: "Queensland Reds" },
			{ id: 50006, name: "Stormers" },
			{ id: 50008, name: "Sharks" },
			{ id: 50004, name: "Waratahs" },
			{ id: 50013, name: "Western Force" }	
		],
		
		nrl: [
			{ id: 55016, name: "Broncos", tla: "BRI" },
			{ id: 55005, name: "Bulldogs", tla: "BUL" },
			{ id: 55008, name: "Cowboys", tla: "NQL" },
			{ id: 55012, name: "Dragons", tla: "STI" },
			{ id: 55010, name: "Eels", tla: "PAR" },
			{ id: 55007, name: "Knights", tla: "NEW" },
			{ id: 55011, name: "Panthers", tla: "PEN" },
			{ id: 55017, name: "Rabbitohs", tla: "SOU" },
			{ id: 55004, name: "Raiders", tla: "CAN" },
			{ id: 55013, name: "Roosters", tla: "SYD" },
			{ id: 55009, name: "Sea Eagles", tla: "MAN" },
			{ id: 55006, name: "Sharks", tla: "CRO" },
			{ id: 55015, name: "Storm", tla: "MEL" },
			{ id: 55014, name: "Tigers", tla: "WST" },
			{ id: 55044, name: "Titans", tla: "GLD" },
			{ id: 55003, name: "Warriors", tla: "WAR" }
		],
		
		afl: [
			{ id: 30, name: "Blues" },
			{ id: 50, name: "Bombers" },
			{ id: 140, name: "Bulldogs" },
			{ id: 70, name: "Cats" },
			{ id: 10, name: "Crows" },
			{ id: 90, name: "Demons" },
			{ id: 60, name: "Dockers" },
			{ id: 150, name: "Eagles" },
			{ id: 80, name: "Hawks" },
			{ id: 100, name: "Kangaroos" },
			{ id: 20, name: "Lions" },
			{ id: 40, name: "Magpies" },
			{ id: 110, name: "Power" },
			{ id: 130, name: "Saints" },
			{ id: 160, name: "Swans" },
			{ id: 120, name: "Tigers" }
		],
		
		epl: [
			{ id: 1006, name: "Arsenal" },
			{ id: 2, name: "Aston Villa" },
			{ id: 45, name: "Birmingham" },
			{ id: 22, name: "Blackburn" },
			{ id: 47, name: "Bolton" },
			{ id: 70, name: "Burnley" },
			{ id: 4, name: "Chelsea" },
			{ id: 8, name: "Everton" },
			{ id: 55, name: "Fulham" },
			{ id: 26, name: "Hull City" },
			{ id: 9, name: "Liverpool" },
			{ id: 11, name: "Man City" },
			{ id: 12, name: "Man Utd" },
			{ id: 36, name: "Portsmouth" },
			{ id: 38, name: "Stoke City" },
			{ id: 39, name: "Sunderland" },
			{ id: 19, name: "Tottenham" },
			{ id: 43, name: "West Ham" },
			{ id: 68, name: "Wigan" },
			{ id: 44, name: "Wolves" }
		]
	});
	
	// List of ism based types id/name mappings
	$.namespace('fs.ism.types', {
		aleague: [
			{ id: 1, name: "Goalkeeper" },
			{ id: 2, name: "Defender" },
			{ id: 3, name: "Midfielder" },
			{ id: 4, name: "Forward" }
		],
		
		s14: [
			{ id: 1, name: "Coach" },
			{ id: 2, name: "Prop" },
			{ id: 3, name: "Hooker" },
			{ id: 4, name: "Lock" },
			{ id: 5, name: "Backrow" },
			{ id: 6, name: "Scrum Half" },
			{ id: 7, name: "Inside Back" },
			{ id: 8, name: "Outside Back" }
		],
		
		nrl: [
			{ id: 1, name: "Prop Forwards" },
			{ id: 2, name: "Hookers" },
			{ id: 3, name: "Backrowers" },
			{ id: 4, name: "Halfbacks" },
			{ id: 5, name: "Inside Backs" },
			{ id: 6, name: "Outside Backs" }
		],
		
		afl: [
			{ id: 1, name: "Forwards" },
			{ id: 2, name: "Ruckmen" },
			{ id: 3, name: "Centres" },
			{ id: 4, name: "Backs" }
		],
		
		epl: [
			{ id: 1, name: "Goalkeeper" },
			{ id: 2, name: "Defender" },
			{ id: 3, name: "Midfielder" },
			{ id: 4, name: "Forward" }
		]
	});
})(jQuery);// jquery.fs.lightbox
// Fox Sports Lightbox Textbox
// (c)2009 Edmond Leung/Fox Sports
//
// Plugin that automatically picks anchor elements that are targeted
// to open up a lightbox, and adds lightbox functionality to it.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
// jquery.colorbox.js
//
// Usage:
// $('input').fs.lightbox();

(function($) {    
    var functions = {
    };
    
    // Create fs.lightbox jquery call
    $.namespace('fn.fs', {
        lightbox: function(opts) {     
            opts = $.extend({}, $.fn.fs.lightbox.defaults, opts);

            return this
            	.click(function() {
            		var id = $(this).attr('href');
            		var scriptTags = $(id).find('script').remove();
            		$.fn.colorbox({ inline: true, href: id, transition: 'none', open: true });
            		
            		// Pause all videos when lightbox is opened
            		$.fs.videoplayer.pause();
            		
            		// Show iframe ads for NIAM
            		var colorboxContent = $(id);
            		var ads = $('#niam-player-ads').find('.ad');
            		ads.each(function() {
            			var ad = $(this);
            			
            			// Ignore if ad has already been loaded
            			if (ad.find('iframe').size() > 0) {
            				return;
            			}
            			
            			// Otherwise, create an iframe to load the ad and inject into ad placement
            			$('<iframe frameborder="0"></iframe>')
            				.attr('src', 'http://media.foxsports.com.au/fatwire/ads/niam/' + ad.attr('class') + '.html')
            				.appendTo(ad);
            		});
            		
            		return false;
            	});
        }
    });
    
    // Setup defaults for lightbox plugin
    $.namespace('fn.fs.lightbox', {
        defaults: {
        }
    });
})(jQuery);// jquery.fs.memoryform
// Fox Sports Memory Form
// (c)2009 Edmond Leung/Fox Sports
//
// Stores and persists form fields, for use by 'remember me' features.
//
// Methods:
//  - restore: Restores the form from cookies.
//  - persist: Saves the form to cookies.
//  - clear: Clears all data that has been persisted.
//
// Requirements:
// The form needs an id, so we know what we're persisting.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('form').fs.memoryform();

(function($) {    
    var functions = {
    };
    
    // Create fs.memoryform jquery call
    $.namespace('fn.fs', {
    	// First param can be options or the method name
    	// If first is method name, then second becomes options
        memoryform: function(methodOrOpts, opts) {
        	// Default method to to restore
        	var method = "restore";
			
        	if (typeof(methodOrOpts) == "string") {
        		method = methodOrOpts;
        	} else {
        		opts = methodOrOpts;
        	}
        	
            opts = $.extend({}, $.fn.fs.memoryform.defaults, opts);
            			
            return this
                .each(function() { 
                	var self = $(this);
                	
                	self.find('input, textarea').each(function() {
                		var field = $(this);
                		
                		// If tagged as forget, then don't remember!
                		if (field.hasClass('forgettable')) { return; }
                		
                		var cookieName = self.attr('id') + "_" + field.attr('id');
						
						var attribute;
						
						// Use different attribute based on field type
                		switch (field.attr('tagName').toLowerCase()) {
	                		case "input":
	                			switch (field.attr('type'))	{
	                				case "text":
	                					attribute = "value";
	                					break;
	                				case "checkbox":
	                					attribute = "checked";
	                					break;
	                			}
	                			break;
	                		case "textarea":
	                			attribute = "value";
	                			break;
                		}
                		
                		// Store or persist based on method, only do this if attribute can be saved/restored
                		if (attribute !== undefined) {
                			switch (method) {
                				case "restore":
                					var value = $.cookie(cookieName);
                					
                					// Adjust for boolean type
                					if (attribute == "checked") {
                						value = (value == "true");
                						attribute = 'defaultChecked';
                					}
                					
                					if (value === null || value === undefined) { break; }
                					
                					field.attr(attribute, value);
                					break;
                				case "persist":
                					$.cookie(cookieName, field.attr(attribute));
                					break;
                				case "clear":
                					$.cookie(cookieName, null);
                					break;
                			}
                		}
                	});
                });
        }
    });
    
    // Setup defaults for memoryform plugin
    $.namespace('fn.fs.memoryform', {
        defaults: {
        }
    });
})(jQuery);// jquery.fs.videomodule
// Fox Sports Video Module
// (c)2009 Brendan Cartledge/Fox Sports
//
// Puts a 'play' button overlay on the video thumbnail and video description on hover
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('input').fs.morevideos();  for the play overlay, and hover video description

(function($) {    
    var functions = {
    };
    
    // Create fs.gallery jquery call
    $.namespace('fn.fs', {
        morevideos: function(opts) {     
            opts = $.extend({}, $.fn.fs.morevideos.defaults, opts);

			
            return this
            	.each(function() { 
                	var self = $(this);
                	
                	self.find('.video-description')
	            		.each(function() {
	            			$(this).css({
	            				opacity: 0,
	            				display: 'block'
	            			});
	                	})
	                	.hover(function() {
	                		$(this).animate({ opacity: 1.0 }, "fast");
	                	}, function() {
	                		$(this).animate({ opacity: 0 }, "fast");
	                	});
                });
        }
    });
    
    // Setup defaults for gallery plugin
    $.namespace('fs.morevideos', {
        defaults: {
        }
    });
})(jQuery);

    
    
// jquery.fs.nav
// Fox Sports Navigation
// (c)2009 Edmond Leung/Fox Sports
//
// Places tier-3 menus under tier-2 menus. Built on top of superfish and options
// are identical to superfish.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js, jquery.superfish.js
//
// Usage:
// $('#nav-level1 .tier-1').fs.nav({
//      speed: 0,
//      delay: 100,
//      dropShadows: false,
//      autoArrows: false
// });

(function($) {    
    var functions = {
        hideAllTier3: function(opts, delay) {
            // Hide all opened tier-3 menus
            this.find('> li > .tier-3').each(function() {
                functions.hideTier3.call(this, opts, delay);
            });
        },
        
        hideTier3: function(opts, delay) {
            var tier3Ul = $(this);
            if (!tier3Ul.hasClass('tier-3')) { return; }
            
            // Clear previous attempt to hide tier3 menu
            clearTimeout(tier3Ul.data('timer'));
            
            // Setup function to call to hide tier3 menu
            var func = function() {
                var tier2Li = tier3Ul.data('tier2Li');
                if (tier2Li === undefined) { return; }
                
                tier3Ul.removeClass('tier-2')
                  .appendTo(tier2Li)
                  .css('visibility', 'hidden')
                  .hide();
                 
                // No longer active (tier2)
                tier2Li.removeClass(opts.hoverClass);
            };
            
            // If no delay, call straight away, otherwise delay the hiding
            if (delay === undefined) {
                func();
            } else {
			    tier3Ul.data('timer', setTimeout(func, delay));   
            }
        }  
    };
    
    // Create fs.nav jquery call
    $.namespace('fn.fs', {
        nav: function(opts) {
            var self = this;
            
            opts = $.extend({}, opts, {
                onBeforeShow: function() {
                    var ul = $(this);
                	var li = ul.parent();
                	var liClassName = li.attr('className');
                	
	                // Perform JS hack to do fake multi-class selectors
                	if (liClassName !== undefined) {
                    	var liClasses = li.attr('className').split(' ');
                    	$.each(liClasses, function(i, className) {
                    		// If not already a hoverclassed class, then make it one
                    		if (className.indexOf(opts.hoverClass) == -1) {
	                    		li.addClass(className + '-' + opts.hoverClass);
    	            		}
                 	   });
                	}
                    
                    // If showing tier-2, then hide all tier-3 first
                    if (ul.hasClass('tier-2')) {
                        functions.hideAllTier3.call(self, opts);
                    }
                    
                    // Before tier3 menu is shown...
                    if (ul.hasClass('tier-3')) {
                        functions.hideAllTier3.call(self, opts);
                        
                        var tier2Li = ul.parent();
                        var tier2Ul = tier2Li.parent();
                        var tier1Li = tier2Ul.parent();
                        
                        var topPosition = tier2Li.position().top + tier2Ul.position().top;
                        
                        // Remove it from it's current hierarchy and position it under
                        // tier2
                        ul.addClass('tier-2')
                          .data('tier2Li', tier2Li)
                          .appendTo(tier1Li)
                          .css('top', topPosition);
                        
                        // Reset any attemps to hide this tier3 menu
                        clearTimeout(ul.data('timer'));
                    }
                    
                    // If no menus available (then it means the menu is reaccessed)
                    if (this.size() === 0) {
                        // Then clear the hiding timer (since we opened it again)
                        self.find('> li > .tier-3').each(function() {
                            clearTimeout($(this).data('timer'));
                        });
                    }
                },
                onHide: function() {
	                // Perform JS hack to do fake multi-class selectors
                	var lis = $(this).parent();
                	lis.each(function() {
                		var li = $(this);
	                	var liClassName = li.attr('className');
	                	
	                	if (liClassName !== undefined) {
	                    	var liClasses = li.attr('className').split(' ');
	                    	$.each(liClasses, function(i, className) {
	                    		if (className.indexOf(opts.hoverClass) >= 0) {
		                    		li.removeClass(className);
	    	            		}
	                 	   });
	                	}
                	});
                	
                    // On hiding, hide tier3 menu with delay
                    $(this).each(function() { functions.hideTier3.call(this, opts, opts.delay); });
                    
                    // On hide and no element to hide (it means tier3 menu is opened, but tier2 doesn't knpw)
                    if (this.size() === 0) {
                        // So make sure sfHover class is still set
                        self.find('> li > .tier-3').each(function() {
                            var tier2Li = $(this).data('tier2Li');
                            tier2Li.addClass(opts.hoverClass);
                        });
                    }
                }
            });
            
            // Default hover class
            if (opts.hoverClass === undefined) {
                opts.hoverClass = $.fn.superfish.defaults.hoverClass;
            }
            
            // Setup superfish menu
            this.superfish(opts);
            
            // If mousing out of tier3 menu, then hide it
            // If mouse in, then cancel hiding
            this.find('.tier-3').mouseleave(function() { functions.hideTier3.call(this, opts, opts.delay); })
                                .mouseenter(function() { clearTimeout($(this).data('timer')); })
                                .parent().addClass('has-children');
                                
            // If losing focus (mouse or tab) for tier2 menu, then hide all tier3 menus
            this.find('.tier-2 > li').mouseleave(function(event) {
                var ignore = false;
                
                $(event.relatedTarget).parents().each(function() {
                    if ($(this).hasClass('tier-3')) { ignore = true; }
                });
                
                if (ignore) { return; }
                
                functions.hideAllTier3.call(self, opts, opts.delay);
            }).blur(function() {
                functions.hideAllTier3.call(self, opts, opts.delay);
            });
            
            // Set to position static to fix IE png link problem
            this.find('.tier-2 li').css('position', 'static');
            this.find('.tier-2 li a').css('position', 'relative');
            
            return this;
        }
    });
})(jQuery);(function($) {    
	var functions = {
		init: function(opts) {
			var self = $(this);
			
			var overlayClose;
			var overlayBg = $('#overlay-bg');
			
			// If they don't already exist, create them
			if (overlayBg.size() === 0) {
				overlayBg = $('<div id="overlay-bg"></div>').appendTo(document.body);
				var overlayBox = $('<div id="overlay-box"></div>').appendTo(document.body);
				
				overlayClose = $('<a title="Close" class="overlay-close"></a>').appendTo(overlayBox);
				var overlayHeader = $('<div class="overlay-header"></div>').appendTo(overlayBox);
				var overlayContent = $('<div class="overlay-content"></div>').appendTo(overlayBox);
				var overlayFooter = $('<div class="overlay-footer"></div>').appendTo(overlayBox);
				
		        // PNG fix for IE6
		        $("#overlay-bg, #overlay-box").supersleight({
		            shim: 'images/supersleight/x.gif',
		            apply_positioning: false
		       });				
			} else {
				overlayClose =  $('#overlay-box .overlay-close');
			}
			
			// Remove any old click events, and add new
			overlayClose.unbind('click').click(function() {
				functions.close.call(self, opts);
			});
			
			// Remove any old click events, and add new
			overlayBg.unbind('click').click(function() {
				functions.close.call(self, opts);
			});
		},
		
		close: function(opts) {
			var onFadeOut = function() {
				var self = $(this);	
				var overlayContent = self.find('.overlay-content');
				
				// Add any children back to their original place
				self.removeClass(opts.className);
				overlayContent.children().each(function() {
					var element = $(this);
					if (element.data('originalParent') !== undefined) {
						element.appendTo(element.data('originalParent'));
					}
				});
				
				// Remove left right align classes
				self.removeClass('overlay-right').removeClass('overlay-left');
				
				// Clear the overlay content
				overlayContent.html('');
			};
			
			if ($.support.opacity) {
				// Fade out the bg and box
				$('#overlay-bg').fadeOut('fast');
				$('#overlay-box').fadeOut('fast', onFadeOut);
			} else {
				// Just hide the bg and box
				var overlayBox = $('#overlay-box');
				$('#overlay-bg').hide();
				overlayBox.hide();
				
				onFadeOut.call(overlayBox);
			}
		},
		
		show: function(opts) {
			var self = $(this);

			// Retrieve the objects
			var overlayBg = $('#overlay-bg');
			var overlayBox = $('#overlay-box');
			var overlayContent = $('#overlay-box .overlay-content');
			
            // Show temporarily so we can position properly
            overlayBox.css('opacity', 0).show().addClass(opts.className);
            
            // Make the overlay bg cover the whole page
			overlayBg.css({ 
				height: $(document).height(),
				width: $(document).width()
			});
			
            // Obtain sizes and positions so we can calculate where overlay will go
            var elementOffset = self.offset();
            var elementSize = { width: self.outerWidth(), height: self.outerHeight() };
            var overlaySize = { width: overlayBox.outerWidth(), height: overlayBox.outerHeight() };
            
            var position = elementOffset;
            
            // Adjust final horizontal anchor position based on element anchor
            switch (opts.elementAnchor.horizontal) {
            case "middle":
            	position.left += elementSize.width / 2.0;
            	break;
            case "right":
            	position.left += elementSize.width;
            	break;
            }
            
            // Adjust final vertical anchor position based on element anchor
            switch (opts.elementAnchor.vertical) {
            case "middle":
            	position.top += elementSize.height / 2.0;
            	break;
            case "bottom":
            	position.top += elementSize.height;
            	break;
            }
            
            // Adjust final horizontal anchor position based on overlay anchor
            switch (opts.overlayAnchor.horizontal) {
            case "middle":
            	position.left -= overlaySize.width / 2.0;
            	break;
            case "right":
            	position.left -= overlaySize.width;
            	break;
            }

            // Adjust final vertical anchor position based on overlay anchor
            switch (opts.overlayAnchor.vertical) {
            case "middle":
            	position.top -= overlaySize.height / 2.0;
            	break;
            case "bottom":
            	position.top -= overlaySize.height;
            	break;
            }
            
            if (position.left + overlaySize.width >= $(window).width()) {
            	var newOpts = $.extend({}, opts);
            	
            	// Extend a blank hash as we don't want to override the old ones
            	newOpts.overlayAnchor = $.extend({}, newOpts.overlayAnchor);
            	newOpts.elementAnchor = $.extend({}, newOpts.elementAnchor);
            	
            	newOpts.overlayAnchor.horizontal = "right";
            	newOpts.elementAnchor.horizontal = "left";
            	
            	functions.show.call(self, newOpts);
            	return;
            }
            
            // Add classes for mirroring
            if (opts.overlayAnchor.horizontal == "right") {
            	overlayBox.addClass('overlay-right');	
            } else if (opts.overlayAnchor.horizontal == "left") {
            	overlayBox.addClass('overlay-left');
            }
            
            // Position the overlay box
            overlayBox.css({
            	left: position.left,
            	top: position.top
            });
            
            if ($.support.opacity) {
            	overlayBox.css('opacity', 1.0);
            } else {
            	overlayBox.css('opacity', null);
            }
            
        	overlayBg.css('opacity', opts.overlayBgOpacity).show();
		}
	};
	
	$.namespace('fn.fs', {
		overlay: function(opts) {
			opts = $.extend({}, $.fn.fs.overlay.defaults, opts);
			
			return this.each(function() {
				var self = $(this);
				
				// Create or reuse old overlay objects
				functions.init.call(self, opts);

				// Retrieve the overlay content to populate it with content
				var overlayContent = $('#overlay-box .overlay-content');
				
	            // If in HTML mode, then insert HTML content into overlay
	            if (opts.html !== null) {
	            	overlayContent.html(opts.html);
	            	functions.show.call(self, opts);
	            } else if (opts.ajax !== null) {
	            	// Only call show when content is loaded
	            	overlayContent.load(opts.ajax.url, opts.ajax.data, function() {
	            		functions.show.call(self, opts);
	            	});
	            } else if (opts.inline !== null) {
	            	// Store the original inline elements parent, so we can
	            	// inject it back in when overlay is closed
	            	var inlineElement = $(opts.inline);
	            	inlineElement.data('originalParent', inlineElement.parent());
	            	
	            	// Append it to the overlay
	            	inlineElement.appendTo(overlayContent);
	            	functions.show.call(self, opts);
	            }
			});
		}
	});
	
	$.namespace('fn.fs.overlay', {
		defaults: {
			className: "",	// Class name to add to the overlay box
		
			html: null,		// Use this if you want to insert HTML content
			ajax: null,		// Use this if you want to call ajax content, should be { url:, data: }
			inline: null,   // Use this if you want to display an inline HTML element
			
			elementAnchor: { horizontal: "right", vertical: "middle" },
			overlayAnchor: { horizontal: "left", vertical: "middle" },
			
			overlayBgOpacity: 0.7
		}
	});
})(jQuery);// jquery.fs.polls
// Fox Sports Poll Popup/Form Submission
// (c)2009 Brendan Cartledge/Fox Sports
//
// Creates an overlay/lightbox effect for the poll question and poll results from links.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('input').fs.pollpopup();  for the overlay show details to come up on the click of each item in the tvguide
// $('input').fs.pollform();  for the submission of the form without having to click the submit button


(function($) {    
    var functions = {
    };
    
    // Create fs.pollpopup jquery call
    $.namespace('fn.fs', {
        pollpopup: function(opts) {     
            opts = $.extend({}, $.fn.fs.pollpopup.defaults, opts);
			
			return this.click(function(e) {
				var self = $(this);
				
				e.preventDefault();
				e.stopPropagation();
				
				$(this).fs.overlay({ className: "foxsports-pollmodule", ajax: { url: self.attr('href') } });
				
				return false;
			});
	    },
	    
		pollform: function (opts) {
			opts = $.extend({}, $.fn.fs.pollform.defaults, opts);
			
			return this.each(function() {
				var self = $(this);
				var pollform = self.find('.pollform');
				
				// Change target to render into based on if popup or not
				var target = self.find('.module-content');
				if (self.attr('id') == "overlay-box") {
					target = self.find('.overlay-content');
				}
				
				// Apply the ajaxForm to each pollform inside each module (identified by id)
				pollform.ajaxForm({
					target: target
				});
				
				// Make the form submit on click of radio button
				self.find('.poll-radio').click( function() {
					pollform.submit();
				});
			});
		}
    });
    
    // Setup defaults for gallery plugin
    $.namespace('fs.pollpopup', {
        defaults: {
        }
    });
    
	$.namespace('fs.pollform', {
        defaults: { 
        }
    });
})(jQuery);(function($) {    
    var functions = {
    	retrieveData: function(table) {
	        // Stores the data retrieved from the table
	        var data = [];
	        
	        // Retrieve the data and store in json format
	        table.find('tr').each(function() {
	        	var tr = $(this);
	        	
	        	var rowData = {
	        		imageElement: tr.find('img'),
	        		teamName:  tr.find('td:eq(1)').text(),
	        		thisWeekRank: parseInt(tr.find('td:eq(2)').text(), 10),
	        		lastWeekRank: parseInt(tr.find('td:eq(3)').text(), 10),
	        		comments: tr.find('td:eq(4)').html()
	        	};
	        	
	        	data.push(rowData);
	        });
	        
	        functions.orderData(data);
	        
	        return data;
    	},
    	
    	orderData: function(data) {
    		// Function sort only by this week's rank
    		var sortRanks = function(row1, row2) {
    			return row1.thisWeekRank > row2.thisWeekRank;
    		};
    		
    		data.sort(sortRanks);
    	},
    	
    	createModule: function(title, data) {
            // Create the actual power rankings module
            var module = $('<div class="module wide-module powerrankings-module"></div>');
            var moduleHeader = $('<div class="module-header"><h3 class="heading">' + title + '</h3></div>').appendTo(module);
            var moduleBorder = $(
            	'<div class="module-border">' + 
            		'<div class="module-content">' + 
            			'<table class="power-rankings-table">' + 
            				'<tbody></tbody>' +
            			'</table>' + 
            		'</div>' +
            	'</div>').appendTo(module);
            
            // Grab tbody to stick new rows into 
            var tbody = moduleBorder.find('tbody');
            var tableHeader = $(
            	'<tr class="header">' +
					'<th class="th-team">Team</th>' + 
					'<th></th>' +
					'<th class="th-thisweek">TW</th>' +
					'<th></th>' +
					'<th class="th-lastweek">LW</th>' +
					'<th class="th-comments">Comments</th>' +
				'</tr>').appendTo(tbody);
            
            $.each(data, function(i, rowData) {
            	// Work out whether rank went up, down or stayed the same
            	var change;
            	if (rowData.thisWeekRank > rowData.lastWeekRank) { change = 'Down'; }
            	else if (rowData.thisWeekRank < rowData.lastWeekRank) { change = 'Up'; }
            	else if (rowData.thisWeekRank == rowData.lastWeekRank) { change = 'Same'; }
            	
            	var tr = $('<tr class="ranking-item"></tr>').appendTo(tbody);
            	
            	// Generate the proper power rankings table row
            	var teamBadge = $(
            		'<td class="team-badge">' +
					'</td>').appendTo(tr);
            	
            	// Add team badge image
            	rowData.imageElement.appendTo(teamBadge);

            	var teamName = $('<td class="team-name">' + rowData.teamName + '</td>').appendTo(tr);
            	var thisWeekRank = $('<td class="td-thisweek">' + rowData.thisWeekRank + '</td>').appendTo(tr);
            	
            	var positionChange = $(
           			'<td class="pos-change">' + 
           				'<div class="pr-posicon">' + 
           					'<a class="pr-' + change.toLowerCase() + '">' + change + '</a>' +
           				'</div>' +
           			'</td>').appendTo(tr);
            	
            	var lastWeekRank = $('<td class="td-lastweek">' + rowData.lastWeekRank + '</td>').appendTo(tr);
            	var comments = $('<td class="td-comments">' + rowData.comments + '</td>').appendTo(tr);
            });
            
            return module;
    	}
    };
    
    // Create fs.powerrankings jquery call
    $.namespace('fn.fs', {
        powerrankings: function(opts) {     
            opts = $.extend({}, $.fn.fs.powerrankings.defaults, opts);

            return this
                .each(function() { 
                    var self = $(this);

                    // Retrieve title and data from markup
                    var title = self.find('caption').text();
                    var data = functions.retrieveData(self);
                    
                    // Replace power rankings data table with new power rankings module 
                    functions.createModule(title, data).insertAfter(self);
                    self.remove();
                });
        }
    });
    
    // Setup defaults for powerrankings plugin
    $.namespace('fn.fs.powerrankings', {
        defaults: {
            powerrankingsedClass: "powerrankingsed" // Class applied when powerrankings is visible
        }
    });
})(jQuery);// jquery.fs.refresher
// Fox Sports Page Refresher
// (c)2009 Edmond Leung/Fox Sports
//
// Used to replace meta refresh tags, so we have a much better control of it.
// For example, the video player can directly disable/enable the page refresh
// whenever a video is playing.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
// jquery.cookie.js
//
// Usage:
// 
// Initialising:
// $.fs.refresher.init({ refreshRate: 240 });

(function($) {
    $.namespace('fs.refresher', {
        // Setup default here for utils
        defaults: {
        	refreshRate: 240
        },
        
        init: function(opts) {
        	this.opts = $.extend({}, $.fs.refresher.defaults, opts);
        	this.enable();
        	
        	// If refreshed, then scroll back to the previous position
        	var refreshPosition = $.cookie('refreshPosition');
        	
        	if (refreshPosition !== null) {
        		$(function() {
        			window.scrollTo(0, refreshPosition);
        		});
        	}
        	
        	// Clear the refreshed cookie, since the refresh already occurred
        	$.cookie('refreshPosition', null);
        },
        
        // Does the page refresh
        refresh: function() {
        	// Use a cookie to signify the page was a refresh
        	$.cookie('refreshPosition', $(window).scrollTop());
        	
        	location.reload(true);
        },
        
        // Enables the refresher
        enable: function() {
        	this.disable();
        	this.timer = setTimeout(this.refresh, this.opts.refreshRate * 1000);
        },
        
        // Disables the refresher
        disable: function() {
        	clearTimeout(this.timer);
        }
    });
})(jQuery);// jquery.fs.refreshformsfix
// Fox Sports Page Refresh Disabler
// (c)2011 Brendan Cartledge/Fox Sports
//
// Used to disable page refreshing when a user starts to type in a soapbox or comments field.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// 
// Initialising:
// $('.soapbox-module, .comments-form').fs.refreshformsfix();

(function($) {
    $.namespace('fs.refreshformsfix', {
        // Setup default here for utils
        defaults: {
        	
        }
    
    });
    $.namespace('fn.fs', {
        refreshformsfix: function(opts) {
        	this.opts = $.extend({}, $.fs.refreshformsfix.defaults, opts);
        	var self = $(this);
        	
        	$.each(self, function() {
				
				var inputs = $(this).find('input, textarea');
				inputs.focus(function() {
					jQuery.fs.refresher.disable();
				});
				
				
			});

        }
    });
})(jQuery);// jquery.fs.scoreboard
// Fox Sports Scoreboard
// (c)2009 Edmond Leung/Fox Sports
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('input').fs.scoreboard();

(function($) {
    var functions = {
    	focusOnLiveMatches: function() {
    		var self = $(this);
    		var api = self.data('scroller-api');
            if(!api)
                return;
    		var itemWrap = api.getItemWrap();
    		
    		// If no focused, then we haven't centered before, then center
    		if (itemWrap.find('li.focused').size() === 0) {
				var liveMatches = itemWrap.find('li.live');
				
				// If there are live matches
				if (liveMatches.size() > 0) {
					// Find the central live game
	    			var liveMatchesFocalIndex = parseInt(liveMatches.size() / 2, 10);
	    			var	focalLiveMatch = liveMatches[liveMatchesFocalIndex];
	    			var focalIndex = parseInt(api.getItems().index(focalLiveMatch) - (api.getConf().size / 2), 10);
	    			
	    			// And center on it
	    			api.seekTo(focalIndex, 0);
	    			
	    			// Let scoreboard know we've already focused
	    			$(focalLiveMatch).addClass('focused');
				} else {
					api.seekTo(itemWrap.find('li.match').size() / 2.0, 0);
				}
    		}
    	},
    	
    	removeExpired: function(matches) {
    		var self = $(this);
    		var api = self.data('scroller-api');
    		var pages = api.getPageAmount();
    		
    		// Remove DOM elements that don't exist in the data anymore
    		api.getItems().each(function() {
    			var li = $(this);
    			var id = li.attr('rel');
    			
    			// If an element exists that isn't in the data
    			var shouldDelete = true;    			
    			$.each(matches, function(i, matchData) {
    				if (matchData.id == id) { shouldDelete = false; }
    			});
    			
    			// Then remove
    			if (shouldDelete) { li.remove(); }
    			
    			// Make sure scrollable area is adjusted to cater for deleted item
    			if (api.getVisibleItems().size() < api.getConf().size && pages > 1) {
	    			api.reload().prev(0);
	    		}
    		});
    	},
    	
    	findGroup: function(data) {
    		return data.response['container-1'][0];
    	},
    	
    	// Condition used to find the scoreboard
    	scoreboardCondition: function(item) {
    		return item.type == "nmdata";
    	},
    	
    	// Condition used to find the ad
    	adCondition: function(item) {
    		return item.type == "ads";
    	},
    	
    	// Grabs an item inside a group based on the conditional function given
    	findItem: function(group, condition) {
    		var itemFound = undefined;
    		
    		var func = function(i, item) {
				if (condition(item)) { itemFound = item; }
			};
			
    		for (var i = 1; i <= 5; i++) {
    			var items = group['group-content-' + i];
    			if (items === undefined) { continue; }
    			
    			// Search inside group items
    			$.each(items, func);
    		}
    		
    		return itemFound;
    	},
    	
    	// Find live scoreboard item inside group
    	findLiveScoreboardItem: function(group) {
    		return functions.findItem.call(this, group, functions.scoreboardCondition);
    	},
    	
    	// Find live scoreboard item inside group
    	findAdItem: function(group) {
    		return functions.findItem.call(this, group, functions.adCondition);
    	},
    	
    	updateLink: function(li, matchData) {
			// Remove old links
			li.unbind('click');
			
			// If match url exists
			if (matchData.match_url !== undefined && matchData.match_url !== "" && matchData.status != "Soon") {
				// Create link to the match url
    			li.addClass('accept-hover') 		// Make it hoverable
    			  .attr('title', 'Full Results')	// Set the tooltip text
    			  .click(function() { window.location = matchData.match_url; }); // Redirect to match result page on click
			} else {
				// If no match url then not hoverable and no link
				li.removeClass('accept-hover hover').attr('title', '');
			}
    	},
    	
    	updateStatus: function(li, matchData) {
    		// Remove any previous states first
    		li.removeClass('pre live complete');
    		
			// Handle status changes
			if (matchData.status == "Soon") {
				li.addClass('pre');
			} else if (matchData.status == "Live") {
				li.addClass('live');
			} else if (matchData.status == "Completed") {
				li.addClass('complete');
			}
    	},
    	
    	updateNav: function(navData) {
    		var self = $(this);
    		var moreLinks = self.find('.more-links');
    		
    		if (moreLinks.size() === 0) {
    			moreLinks = $('<ul class="more-links tier-1"></ul>').appendTo(self.find('.more-results'));
    		} else {
	    		// Clear it out first
	    		moreLinks.empty();
	    	}
    		
    		
    		// Create nav links
    		$.each(navData.menu, function(i, navItem) {
    			$('<li><a href="' + navItem.url + '" title="' + navItem.title + '">' + navItem.title + '</a></li>').appendTo(moreLinks);
    		});
    		
    		// Add first and last classes
    		moreLinks.find('li:first').addClass('first');
    		moreLinks.find('li:last').addClass('last');
    	},
    	
    	insertIntoDOM: function(data) {
    		var self = $(this);
    		var api = self.data('scroller-api');
            if(!api)
                return;
    		var itemWrap = api.getItemWrap();
    		
    		functions.removeExpired.call(this, data);
    		
    		var lastID = undefined;
    		
    		// Match data (array that stores all matches)
    		var group = functions.findGroup.call(this, data);
    		var matches = functions.findLiveScoreboardItem.call(this, group).content.match;

    		// Create an li.match lement for each match stored in data
    		$.each(matches, function(i, matchData) {
    			// Find if the match already exist in the scoreboard
    			var li = itemWrap.find('li.match[rel=' + matchData.event_id + ']');
    			
    			if (li.size() > 0) {
    				// If so, then empty its children
    				li.empty();
    			} else {
    				// Otherwise, create new li element
    				li = $('<li class="match" rel="' + matchData.event_id + '"></li>').appendTo(itemWrap);	
    			}
    			
    			// Make sure li is in the correct order (same order as matchData)
    			if (lastID !== undefined) {
    				if (li.prev('li.match').attr('rel') != lastID) {
    					li.insertAfter(itemWrap.find('li.match[rel=' + lastID + ']'));	
    				}
    			} else {
    				li.appendTo(itemWrap);
    			}
    			
    			lastID = matchData.id;
				
    			var h3 = $('<h3 class="sport-name">' + matchData.compdisplay + '</h3>').appendTo(li);
    			var dl = $('<dl class="summary"></dl>').appendTo(li);
    			
    			$.each({ date: "Date", time: "Time", status: "Status", current_period: "Current Period" }, function(key, value) {
    				var className = key.replace(/\_/g, '-');
    				
    				var dt = $('<dt><strong>' + value + '</strong></dt>').appendTo(dl);
    				var dd = $('<dd class="' + className + '">' + matchData[key] + '</dd>').appendTo(dl);
    			});
    			
    			var resultsDt = $('<dt><strong>Results</strong></dt>').appendTo(dl);
    			var resultsDd = $('<dd></dd>').appendTo(dl);
    			var resultsUl = $('<ul class="match-results"></ul>').appendTo(resultsDd);
    			
    			$.each(matchData.results.detail, function(i, teamData) {
    				var teamLi = $('<li class="team"></li>').appendTo(resultsUl);
    				var teamName = $('<strong><abbr class="team-name" title="' + teamData.teamname + '">' + teamData.short_teamname + '</abbr></strong>').appendTo(teamLi);
    				
    				var teamScore = teamData.score;
    				if (matchData.compdisplay.toLowerCase() == "afl") {
    					var regexp = /(\(.+\))/;
    					var str = teamScore;
    					var a = regexp.exec(teamScore);
    					teamScore = a[0].replace(/[\(\)]/g, '');
    				}
    				var score = $('<span class="score">' + teamScore + '</span>').appendTo(teamLi);
    			});
				
				// Update link and state
    			functions.updateLink(li, matchData);
    			functions.updateStatus(li, matchData);
    		});
    		
    		// Update the more links navigation
    		functions.updateNav.call(this, group['group-menu']);
    	},
    	
    	reloadData: function(opts) {
    		var self = this;
    		
    		var updateScoreboard = function() {
    			var size;
    			var scoreboard = $(opts.selector);
				
				// Apply ad styling if ad exists
				if ($.fs.scoreboard.isSponsored()) {
					scoreboard.addClass('scoreboard-with-ad');
					size = 5; // Display one less to fit ad
				} else {
					scoreboard.removeClass('scoreboard-with-ad');
					size = 6; // Display all since no ad
				}
				
				// Populate the scoreboard
				scoreboard.fs.scoreboard($.fs.scoreboard.data, { size: size });
				
				// Reload after refreshInterval amount of seconds has passed
				setTimeout(function() {
					functions.reloadData.call(self, opts);
				}, opts.refreshInterval);
				
				$.fs.scoreboard.data = undefined;
    		};
    		
    		// Check whether we should use ajax or not
    		if ($.fs.scoreboard.data === undefined) {
    			self.service.getScores(updateScoreboard);
    		} else {
    			// If scoreboard is initially set, it means it was injected, we can update right away
    			updateScoreboard();
    		}
    	}
    };
    
    // Create fs.scoreboard jquery call
    $.namespace('fn.fs', {
        scoreboard: function(data, opts) {     
            opts = $.extend({}, $.fn.fs.scoreboard.defaults, opts);
			
            return this.each(function() { 
            	var self = $(this);
            	
            	var api = self.data('scroller-api');
            	
            	// Create matches ul so HTML validates without having empty UL
            	var matchesScroller = self.find('.matches-scroller');
            	var matchesUl = self.find('.matches');
            	if (matchesUl.size() === 0) {
            		matchesUl = $('<ul class="matches"></ul>').appendTo(matchesScroller);
            	}
            	
            	// If no api attach scrollable to the scoreboard
            	if (api === undefined) {
				    api = matchesScroller.scrollable({
				    	api: true,
				    	clickable: false,
				    	items: ".matches",
				    	item: "li.match",
				    	size: opts.size,
				    	keyboard: false
				    });
				    
				    // Store api into the scoreboard DOM (so we can use to reload later)
				    self.data('scroller-api', api);
            	}
            	
            	// Convert data into DOM elements that represent each match
            	functions.insertIntoDOM.call(this, data);
            	functions.focusOnLiveMatches.call(this);
            	
        		// Refresh the scroller with new items
                if(api)
                    api.reload();
            });
        }
    });
    
    // Setup defaults for scoreboard plugin
    $.namespace('fn.fs.scoreboard', {
        defaults: {
        	size: 6   // The number of matches visible on one page
        }
    });
    
    // Scoreboard utility functions
	$.namespace('fs.scoreboard', {
        defaults: {
        	selector: '.scoreboard',	// Which scoreboards to apply to
        	refreshInterval: 60000		// The refresh rate in milliseconds
        },
        
        // Function to start the JSON loading process
        init: function(service, opts) {
        	var self = this;
        	
            this.opts = $.extend({}, $.fs.scoreboard.defaults, opts);
            this.service = service;
            
            // Ignore if no data was loaded
            if ($.fs.scoreboard.data !== undefined) {
                // Load the data on dom ready
                $(function() {
                	functions.reloadData.call(self, self.opts);	
                });
            }
        },
        
        isSponsored: function() {
        	if ($.fs.scoreboard.data === undefined) { return false; }  
        	      	
        	var group = functions.findGroup.call(this, $.fs.scoreboard.data);
        	return functions.findAdItem.call(this, group) !== undefined;
        },
        
        // This variable is set by the scoreboard json file
        // We use this when updating the scoreboard
        data: undefined
    });
})(jQuery);/*jslint evil: true */

(function($) {
	$.namespace('fs.scoreboard.service');

	// Interface for scoreboard Service implementation
	$.fs.scoreboard.service.intaface = $.klass({
		/**
		 * init - Constructure, responsible for doing any setup work required
		 * by your delegate, eg. preloading data.
		 **/
		initialize: function() {
			throw "init not implemented";
		},
		
		/**
		 * getScores - Should grab scores from stats central and store it in
		 * jQuery.fs.scoreboard.data
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getScores: function(successDelegate, failureDelegate) {
			throw "getScores not implemented";
		}
	});
	
	// Mock Scoreboard Service implementation for testing
	$.fs.scoreboard.service.mock = $.klass($.fs.scoreboard.service.intaface, {
		defaults: {
		},
		
		initialize: function() {
		},
		
		getScores: function(successDelegate, failureDelegate) {
			setTimeout(function() {
				$.fs.scoreboard.data = { "response": { "type" : "page", "id": "livescoreboard", "container-1" : [ { "type" : "group", "id" : "1208930890283", "name" : "Live Scoreboard Group", "title" : "Live Scoreboard Group", "classname" : "", "group-content-1" : [  { "type" : "nmdata", "id" : "1208930890534", "name": "Live Scoreboard", "title": "", "classname": "", "total": "15", "content" : { "match": [ { "event_id": "EPL2009-101110BIRMANC", "date": "02/11", "time": "03:00", "url": "http://www.foxsports.com.au/football/results/", "sport": "Football", "compname": "EPL", "current_period": "Full Time", "match_url": "http://www.foxsports.com.au/football/matchresults/0,,fwEPL2009-101110BIRMANC,00.html", "results": { "detail": [ { "teamname": "Birmingham", "short_teamname": "BIR", "score": "0" }, { "teamname": "Man City", "short_teamname": "MANC", "score": "0" } ] }, "status": "Completed" } , { "event_id": "EPL2009-101109MANUBLA", "date": "01/11", "time": "04:30", "url": "http://www.foxsports.com.au/football/results/", "sport": "Football", "compname": "EPL", "current_period": "Full Time", "match_url": "http://www.foxsports.com.au/football/matchresults/0,,fwEPL2009-101109MANUBLA,00.html", "results": { "detail": [ { "teamname": "Man United", "short_teamname": "MANU", "score": "2" }, { "teamname": "Blackburn", "short_teamname": "BLA", "score": "0" } ] }, "status": "Completed" } , { "event_id": "EPL2009-101105FULLIV", "date": "01/11", "time": "02:00", "url": "http://www.foxsports.com.au/football/results/", "sport": "Football", "compname": "EPL", "current_period": "Full Time", "match_url": "http://www.foxsports.com.au/football/matchresults/0,,fwEPL2009-101105FULLIV,00.html", "results": { "detail": [ { "teamname": "Fulham", "short_teamname": "FUL", "score": "3" }, { "teamname": "Liverpool", "short_teamname": "LIV", "score": "1" } ] }, "status": "Completed" } , { "event_id": "EPL2009-101106PORWIG", "date": "01/11", "time": "02:00", "url": "http://www.foxsports.com.au/football/results/", "sport": "Football", "compname": "EPL", "current_period": "Full Time", "match_url": "http://www.foxsports.com.au/football/matchresults/0,,fwEPL2009-101106PORWIG,00.html", "results": { "detail": [ { "teamname": "Portsmouth", "short_teamname": "POR", "score": "4" }, { "teamname": "Wigan", "short_teamname": "WIG", "score": "0" } ] }, "status": "Completed" } , { "event_id": "EPL2009-101104EVEAVL", "date": "01/11", "time": "02:00", "url": "http://www.foxsports.com.au/football/results/", "sport": "Football", "compname": "EPL", "current_period": "Full Time", "match_url": "http://www.foxsports.com.au/football/matchresults/0,,fwEPL2009-101104EVEAVL,00.html", "results": { "detail": [ { "teamname": "Everton", "short_teamname": "EVE", "score": "1" }, { "teamname": "Aston Villa", "short_teamname": "AVL", "score": "1" } ] }, "status": "Completed" } , { "event_id": "EPL2009-101107STOWOL", "date": "01/11", "time": "02:00", "url": "http://www.foxsports.com.au/football/results/", "sport": "Football", "compname": "EPL", "current_period": "Full Time", "match_url": "http://www.foxsports.com.au/football/matchresults/0,,fwEPL2009-101107STOWOL,00.html", "results": { "detail": [ { "teamname": "Stoke", "short_teamname": "STO", "score": "2" }, { "teamname": "Wolverhampton", "short_teamname": "WOL", "score": "2" } ] }, "status": "Completed" } , { "event_id": "EPL2009-101108SUNWHU", "date": "01/11", "time": "02:00", "url": "http://www.foxsports.com.au/football/results/", "sport": "Football", "compname": "EPL", "current_period": "Full Time", "match_url": "http://www.foxsports.com.au/football/matchresults/0,,fwEPL2009-101108SUNWHU,00.html", "results": { "detail": [ { "teamname": "Sunderland", "short_teamname": "SUN", "score": "2" }, { "teamname": "West Ham", "short_teamname": "WHU", "score": "2" } ] }, "status": "Completed" } , { "event_id": "EPL2009-101102BOLCHE", "date": "01/11", "time": "02:00", "url": "http://www.foxsports.com.au/football/results/", "sport": "Football", "compname": "EPL", "current_period": "Full Time", "match_url": "http://www.foxsports.com.au/football/matchresults/0,,fwEPL2009-101102BOLCHE,00.html", "results": { "detail": [ { "teamname": "Bolton", "short_teamname": "BOL", "score": "0" }, { "teamname": "Chelsea", "short_teamname": "CHE", "score": "4" } ] }, "status": "Completed" } , { "event_id": "EPL2009-101103BURHUL", "date": "01/11", "time": "02:00", "url": "http://www.foxsports.com.au/football/results/", "sport": "Football", "compname": "EPL", "current_period": "Full Time", "match_url": "http://www.foxsports.com.au/football/matchresults/0,,fwEPL2009-101103BURHUL,00.html", "results": { "detail": [ { "teamname": "Burnley", "short_teamname": "BUR", "score": "2" }, { "teamname": "Hull", "short_teamname": "HUL", "score": "0" } ] }, "status": "Completed" } , { "event_id": "NRL20090308", "date": "30/03", "time": "19:00", "url": "http://www.foxsports.com.au/league/results/", "sport": "League", "compname": "NRL", "current_period": "In Progress", "match_url": "http://www.foxsports.com.au/league/matchresults/0,,fwNRL20090308,00.html", "results": { "detail": [ { "teamname": "Sea Eagles", "short_teamname": "MAN", "score": "17" }, { "teamname": "Panthers", "short_teamname": "PEN", "score": "12" } ] }, "status": "Live" } , { "event_id": "NRL20090901", "date": "09/05", "time": "19:30", "url": "http://www.foxsports.com.au/league/results/", "sport": "League", "compname": "NRL", "current_period": "In Progress", "match_url": "http://www.foxsports.com.au/league/matchresults/0,,fwNRL20090901,00.html", "results": { "detail": [ { "teamname": "Cowboys", "short_teamname": "NQL", "score": "24" }, { "teamname": "Dragons", "short_teamname": "STI", "score": "20" } ] }, "status": "Live" } , { "event_id": "NRL20090903", "date": "10/05", "time": "15:00", "url": "http://www.foxsports.com.au/league/results/", "sport": "League", "compname": "NRL", "current_period": "In Progress", "match_url": "http://www.foxsports.com.au/league/matchresults/0,,fwNRL20090903,00.html", "results": { "detail": [ { "teamname": "Broncos", "short_teamname": "BRI", "score": "20" }, { "teamname": "Sea Eagles", "short_teamname": "MAN", "score": "22" } ] }, "status": "Live" } , { "event_id": "NRL20091505", "date": "22/06", "time": "19:00", "url": "http://www.foxsports.com.au/league/results/", "sport": "League", "compname": "NRL", "current_period": "Half Time", "match_url": "http://www.foxsports.com.au/league/matchresults/0,,fwNRL20091505,00.html", "results": { "detail": [ { "teamname": "Sharks", "short_teamname": "CRO", "score": "18" }, { "teamname": "Broncos", "short_teamname": "BRI", "score": "6" } ] }, "status": "Live" } , { "event_id": "80202", "date": "30/10", "time": "10:30", "url": "http://www.foxsports.com.au/cricket/results/", "sport": "Cricket", "compname": "Domestic-SHEF-Sheffield Shield", "current_period": "Lunch Break", "match_url": "http://www.foxsports.com.au/cricket/matchresults/0,,fw80202,00.html", "results": { "detail": [ { "teamname": "South Australia", "short_teamname": "SA", "score": "10/292 and 2/191" }, { "teamname": "Victoria", "short_teamname": "VIC", "score": "9/643" } ] }, "status": "Soon" } , { "event_id": "80203", "date": "01/11", "time": "11:00", "url": "http://www.foxsports.com.au/cricket/results/", "sport": "Cricket", "compname": "Domestic-SHEF-Sheffield Shield", "current_period": "Lunch Break", "match_url": "http://www.foxsports.com.au/cricket/matchresults/0,,fw80203,00.html", "results": { "detail": [ { "teamname": "Queensland", "short_teamname": "QLD", "score": "4/155" }, { "teamname": "Tasmania", "short_teamname": "TAS", "score": "10/156" } ] }, "status": "Soon" } ] } } , { "type" : "ads", "adType": "adsense", "advertOptions": "" } ] , "group-menu" : { "type" : "nav", "menu" : [ {"title" : "AFL", "url" : "/cs/Satellite/testarea/afl?site=FoxSports"}, {"title" : "NRL", "url" : "/league/results"}, {"title" : "Rugby", "url" : "/rugby/results"}, {"title" : "Football", "url" : "/football/results"}, {"title" : "Cricket", "url" : "/cricket/results"} ] } } ] } };
				successDelegate.call(this, $.fs.scoreboard.data);
			}, Math.random() * 1000);
		}
	});
	
	// JSON based Scoreboard Service implementation
	$.fs.scoreboard.service.json = $.klass($.fs.scoreboard.service.intaface, {
		defaults: {
		},
		
		initialize: function(opts) {
			this.opts = $.extend({}, this.defaults, opts);
			
			// If no path supplied, then grab it for the script tag on the page
			if (this.opts.path === undefined) {
				this.opts.path = $('script[src*=scoreboard][src*=json]').attr('src');
			}
		},
		
		getScores: function(successDelegate, failureDelegate) {
			$.ajax({
				url: this.opts.path,
				success: function(response) {
		        	// If no response, than don't update scoreboard
		        	successDelegate.call(this, $.fs.scoreboard.data);
				},
				dataType: 'script',
				cache: true
			});
		}
	});
})(jQuery);// jquery.fs.sitelogos
// Fox Sports Subsection Site Logos
// (c)2010 Brendan Cartledge/Fox Sports
//
// Used to replace HREF of links for the header and footer logos.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// 
// Initialising:
// $.fs.sitelogos.init({ siteLink: 'http://foxsports.com.au' });

(function($) {
    $.namespace('fs.sitelogos', {
        // Setup default here for utils
        defaults: {
        	siteLink: 'http://www.foxsports.com.au'
        }
    
    });
    $.namespace('fn.fs', {
        sitelogos: function(opts) {
        	this.opts = $.extend({}, $.fs.sitelogos.defaults, opts);
        	var self = $(this);
        	
        	var anchor = self.find('a');
        	anchor.attr('href',opts.siteLink);

        }
    });
})(jQuery);// jquery.fs.soapbox 
// Fox Sports Soapbox Form Submission
// (c)2009 Brendan Cartledge/Fox Sports
//
// Creates an overlayeffect once a comment is submitted in the soapbox module.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('input').fs.soapbox();  for the white overlay to come up upon pressing the submit button


(function($) {    
    var functions = {
    	showOverlay: function(result, clearForm) {
    		var self = $(this);
    		
    		// Find the height of the module-content div (we will use this for the overlay height)
    		var overlay = self.find('.soapbox-overlay');
    		var overlayHeight = self.find('.module-content').attr('offsetHeight');
    		
    		// Update the overlay message
    		var overlayMessage = self.find('.soapbox-overlay-message');
    		overlayMessage.html(result);
    		
    		// Set the height of the overlay
    		overlay.height(overlayHeight).show();
    		
    		// Center the message vertically
    		var overlayMessageHeight = overlayMessage.attr('offsetHeight');
    		overlayMessage.css('margin-top', (overlayHeight - overlayMessageHeight) / 2);
    		
    		self.find('form')[0].reset();
    	}
    };    
    
    // Create fs.soapbox jquery call
    $.namespace('fn.fs', {
        soapbox: function(opts) {     
            opts = $.extend({}, $.fn.fs.soapbox.defaults, opts);
            
			return this.each(function() {
				var self = $(this);
				var form = self.find('form');

				$('.close, .soapbox-overlay').click(function () {
					self.find('.soapbox-overlay').hide(); 
					return false;
				});
				
				form.bind('submitsuccess', function(e, result) {
					functions.showOverlay.call(self, result, true);
				});
				
				form.bind('submitfailure', function(e) {
					functions.showOverlay.call(self, opts.errorMessage, false);
				});
				
				// Add character counters
				self.find('.soapbox-longcomments').each(function() {
					var wrapper = $(this);
					var counterElement = wrapper.find('.soapbox-instr');
					var textarea = wrapper.find('textarea');
					
					textarea.charCounter(parseInt(counterElement.find('em').text(), 10), {
						container: counterElement,
						format: "(%1 characters left)"
					});
				});			    
			});
		}
    });
    
    // Setup defaults for gallery plugin
    $.namespace('fs.soapbox', {
        defaults: {
    		errorMessage: "There was an error processing your comment. Please return to the soapbox and retry"
        }
    });
})(jQuery);// jquery.fs.splashrotate
// Fox Sports Rotating Splash
// (c)2009 Edmond Leung/Fox Sports
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('.featured-fader').fs.splashrotate();

(function($) {    
    var functions = {
    	getData: function() {
    		var self = $(this);
    		
    		return {
    			items: self.data('splashRotateFaderItems'),
    			api: self.data('splashrotateScrollerApi'),
    			opts: self.data('splashrotateOptions'),
    			timer: self.data('splashrotateTimer'),
    			countDown: self.data('splashrotateCountDown'),
    			paused: self.data('splashrotatePaused'),
    			idleTimer: self.data('splashrotateIdleTimer')
    		};
    	},
    	
    	resetTimer: function() {
			var self = $(this);
    		var data = functions.getData.call(this);
    		
    		// Reset the countdown to start all over
    		self.data('splashrotateCountDown', data.opts.delay);
    		
    		// Start time timer after reseting it
    		functions.startTimer.call(this);
    	},
    	
    	startTimer: function() {
    		var self = $(this);
    		var data = functions.getData.call(this);
    		
    		// Stop old timers first
    		clearTimeout(data.timer);
    		
    		// Create new timer that does the countdown
    		data.timer = setInterval(function() {
    			functions.updateTimer.call(self);
    		}, data.opts.delayAccuracy);
    		
    		self.data('splashrotateTimer', data.timer);
    		
    		// Refresh the timer once intially
    		functions.updateTimer.call(self);
    		
    		self.data('splashrotatePaused', false); 
    	},
    	
    	updateTimer: function() {
    		var self = $(this);
    		var data = functions.getData.call(this);
    		
    		// Update visually
    		var faderCountDown = self.find('.fader-countdown');
    		var percentWidth = 100 - parseInt((data.countDown / data.opts.delay) * 100, 10);
    		faderCountDown.css('width', percentWidth + "%");
    		faderCountDown.text(Math.ceil(data.countDown / 1000));
    		
    		// Reduce the count down and save it
    		data.countDown -= data.opts.delayAccuracy;
    		self.data('splashrotateCountDown', data.countDown);
    		
    		// If countdown is less than zero, than countdown is done!
    		if (data.countDown <= 0) {
    			// So we go to next item in the fader
    			var index = (data.api.getClickIndex() + 1) % data.api.getSize();
    			self.find('li:eq(' + index + ')').click();
    			
    			data.countDown = 0;
    		}
    	},
    	
    	pauseTimer: function() {
    		var self = $(this);
    		var data = functions.getData.call(this);
    		
    		// Stop the timer
    		clearTimeout(data.timer);
    		
    		self.data('splashrotatePaused', true);
    	},
    	
    	idlePauseTimer: function() {
    		var self = $(this);
    		var data = functions.getData.call(this);
    		
    		clearTimeout(data.idleTimer);
    		data.idleTimer = setTimeout(function() {
    			functions.startTimer.call(self);
    		}, data.opts.idleTime);
    		self.data('splashrotateIdleTimer', data.idleTimer);
    		
    		functions.pauseTimer.call(this);
    	},
    	
    	show: function(index) {
    		var self = $(this);
    		var data = functions.getData.call(this);
    		
    		$.each(data.items, function(i, item) {
    			if (i == index) {
    				$(item).fadeIn();	
    			} else {
    				$(item).fadeOut();
    			}
    		});
    	},
    	
    	onActive: function() {
    		var self = $(this);
    		var data = functions.getData.call(this);
    		
    		// Reset the timer
    		functions.resetTimer.call(self);
    		
    		// Don't start if currently pause
    		if (data.paused) { functions.pauseTimer.call(self); }
    		
    		// Position the fader count down on top of the fader thumbnail
    		var index = data.api.getClickIndex();
    		var faderControl = self.find('li:eq(' + index + ')');
    		var faderControlPosition = faderControl.position();		
    		
    		var faderCountDownWrapper = self.find('.fader-countdown-container');
    		faderCountDownWrapper.css('left', faderControlPosition.left + 5);
    		faderCountDownWrapper.css('bottom', 5);
    		
    		var faderCounter = self.find('.fader-counter');
    		faderCounter.text(index + 1);
    		
    		functions.show.call(this, index);
    	}
    };
    
    // Create fs.splashrotate jquery call
    $.namespace('fn.fs', {
        splashrotate: function(opts) {     
            opts = $.extend({}, $.fn.fs.splashrotate.defaults, opts);

            return this
                .each(function() {
                	var self = $(this);
                	var faderControls = self.find('.fader-controls');
                	
                	var api = faderControls.scrollable({
				    	api: true,
				    	clickable: true,
				    	items: "ol",
				    	item: "li.fader-control",
				    	size: 4
				    });
				    
                	// Fix for standfirst kicker HTML
                	var moduleContent = self.find('.module-content');
                	var items = moduleContent.find('.fader-item');
                	moduleContent.html('');
                	items.appendTo(moduleContent);
                	
				    // Store the fader items in order and api for later use
				    self.data('splashRotateFaderItems', self.find('.fader-item'));
				    self.data('splashrotateScrollerApi', api);
				    self.data('splashrotateOptions', opts);
				    
				    // Disable click throughs (when links are clicked, simulate click on li element)
				    faderControls.find('a').click(function() { 
				    	var li = $(this).closest('li');
				    	var returnValue = li.hasClass('active'); 
				    	li.click();
				    	return returnValue;
				    });
				    
				    // Handle activate fader control event
				    self.find('li').click(function() {
				    	functions.onActive.call(self);
				    });
				    
				    self.find('.fader-item').hide();
				    self.find('.fader-item:first').show();
				    
				    // Click on first one by default
				    self.find('li:first').click();
				    
				    self.mouseenter(function() { functions.pauseTimer.call(self); });
				    self.mouseleave(function() { functions.startTimer.call(self); });
				    self.mousemove(function() { functions.idlePauseTimer.call(self); });
                });
        }
    });
    
    // Setup defaults for splashrotate plugin
    $.namespace('fn.fs.splashrotate', {
        defaults: {
        	idleTime: 30000,	// 30 seconds of idle time
        	delayAccuracy: 100, // how often the timer is checked and updated
        	delay: 8000		    // how long each feature is shown for in milliseconds
        }
    });
})(jQuery);(function($) {
	$.namespace('fs.tipping.service');

	// Interface for tipping Service implementation
	$.fs.tipping.service.intaface = $.klass({
		/**
		 * init - Constructure, responsible for doing any setup work required
		 * by your delegate, eg. preloading data.
		 **/
		initialize: function() {
			throw "init not implemented";
		},
		
		/**
		 * getLatestRoundNumber - Should return a the latest round number.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getLatestRoundNumber: function(code, successDelegate, failureDelegate) {
			throw "getLatestRoundNumber not implemented";
		},
		
		/**
		 * getTips - Should return a list of the tips for the specified code and round.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getTips: function(code, round, successDelegate, failureDelegate) {
			throw "getTips not implemented";
		}
	});
	
	// Mock Tipping Service implementation for testing
	$.fs.tipping.service.mock = $.klass($.fs.tipping.service.intaface, {
		defaults: {
		},
		
		initialize: function() {
		},
		
		getLatestRoundNumber: function(code, successDelegate, failureDelegate) {
			successDelegate.call(this, 12);
		},
		
		getTips: function(code, round, successDelegate, failureDelegate) {
			setTimeout(function() {
				successDelegate.call(this, {
                    "entry": [
                        {
                            "total_predictions": 201,
                            "total_correct": 118,
                            "prediction": [
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Dragons",
                                    "team_h_name": "Storm",
                                    "team_a_score": "16",
                                    "finished": "1",
                                    "team_h_score": "17",
                                    "-kickoff_time": 1236933300
                                },
                                {
                                    "value": "Away",
                                    "is_correct": 0,
                                    "team_a_name": "Cowboys",
                                    "team_h_name": "Broncos",
                                    "team_a_score": "18",
                                    "finished": "1",
                                    "team_h_score": "19",
                                    "-kickoff_time": 1236936900
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Eels",
                                    "team_h_name": "Warriors",
                                    "team_a_score": "18",
                                    "finished": "1",
                                    "team_h_score": "26",
                                    "-kickoff_time": 1237012200
                                },
                                {
                                    "value": "Away",
                                    "is_correct": 0,
                                    "team_a_name": "Sea Eagles",
                                    "team_h_name": "Bulldogs",
                                    "team_a_score": "12",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237019400
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Panthers",
                                    "team_h_name": "Sharks",
                                    "team_a_score": "10",
                                    "finished": "1",
                                    "team_h_score": "18",
                                    "-kickoff_time": 1237019400
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Knights",
                                    "team_h_name": "Titans",
                                    "team_a_score": "20",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237086000
                                },
                                {
                                    "value": "Away",
                                    "is_correct": 1,
                                    "team_a_name": "Rabbitohs",
                                    "team_h_name": "Roosters",
                                    "team_a_score": "52",
                                    "finished": "1",
                                    "team_h_score": "12",
                                    "-kickoff_time": 1237089600
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Raiders",
                                    "team_h_name": "Tigers",
                                    "team_a_score": "26",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237190400
                                }
                            ],
                            "name": "Warren Smith",
                            "id": "13922",
                            "user_name": "smith"
                        },
                        {
                            "total_predictions": 201,
                            "total_correct": 115,
                            "prediction": [
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Dragons",
                                    "team_h_name": "Storm",
                                    "team_a_score": "16",
                                    "finished": "1",
                                    "team_h_score": "17",
                                    "-kickoff_time": 1236933300
                                },
                                {
                                    "value": "Away",
                                    "is_correct": 0,
                                    "team_a_name": "Cowboys",
                                    "team_h_name": "Broncos",
                                    "team_a_score": "18",
                                    "finished": "1",
                                    "team_h_score": "19",
                                    "-kickoff_time": 1236936900
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Eels",
                                    "team_h_name": "Warriors",
                                    "team_a_score": "18",
                                    "finished": "1",
                                    "team_h_score": "26",
                                    "-kickoff_time": 1237012200
                                },
                                {
                                    "value": "Away",
                                    "is_correct": 0,
                                    "team_a_name": "Sea Eagles",
                                    "team_h_name": "Bulldogs",
                                    "team_a_score": "12",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237019400
                                },
                                {
                                    "value": "Away",
                                    "is_correct": 0,
                                    "team_a_name": "Panthers",
                                    "team_h_name": "Sharks",
                                    "team_a_score": "10",
                                    "finished": "1",
                                    "team_h_score": "18",
                                    "-kickoff_time": 1237019400
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Knights",
                                    "team_h_name": "Titans",
                                    "team_a_score": "20",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237086000
                                },
                                {
                                    "value": "Away",
                                    "is_correct": 1,
                                    "team_a_name": "Rabbitohs",
                                    "team_h_name": "Roosters",
                                    "team_a_score": "52",
                                    "finished": "1",
                                    "team_h_score": "12",
                                    "-kickoff_time": 1237089600
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Raiders",
                                    "team_h_name": "Tigers",
                                    "team_a_score": "26",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237190400
                                }
                            ],
                            "name": "Greg Alexander",
                            "id": "13934",
                            "user_name": "Greg_Alexander"
                        },
                        {
                            "total_predictions": 201,
                            "total_correct": 122,
                            "prediction": [
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Dragons",
                                    "team_h_name": "Storm",
                                    "team_a_score": "16",
                                    "finished": "1",
                                    "team_h_score": "17",
                                    "-kickoff_time": 1236933300
                                },
                                {
                                    "value": "Away",
                                    "is_correct": 0,
                                    "team_a_name": "Cowboys",
                                    "team_h_name": "Broncos",
                                    "team_a_score": "18",
                                    "finished": "1",
                                    "team_h_score": "19",
                                    "-kickoff_time": 1236936900
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Eels",
                                    "team_h_name": "Warriors",
                                    "team_a_score": "18",
                                    "finished": "1",
                                    "team_h_score": "26",
                                    "-kickoff_time": 1237012200
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Sea Eagles",
                                    "team_h_name": "Bulldogs",
                                    "team_a_score": "12",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237019400
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Panthers",
                                    "team_h_name": "Sharks",
                                    "team_a_score": "10",
                                    "finished": "1",
                                    "team_h_score": "18",
                                    "-kickoff_time": 1237019400
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Knights",
                                    "team_h_name": "Titans",
                                    "team_a_score": "20",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237086000
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 0,
                                    "team_a_name": "Rabbitohs",
                                    "team_h_name": "Roosters",
                                    "team_a_score": "52",
                                    "finished": "1",
                                    "team_h_score": "12",
                                    "-kickoff_time": 1237089600
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Raiders",
                                    "team_h_name": "Tigers",
                                    "team_a_score": "26",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237190400
                                }
                            ],
                            "name": "Russell Fairfax",
                            "id": "13909",
                            "user_name": "fairfax"
                        },
                        {
                            "total_predictions": 201,
                            "total_correct": 118,
                            "prediction": [
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Dragons",
                                    "team_h_name": "Storm",
                                    "team_a_score": "16",
                                    "finished": "1",
                                    "team_h_score": "17",
                                    "-kickoff_time": 1236933300
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Cowboys",
                                    "team_h_name": "Broncos",
                                    "team_a_score": "18",
                                    "finished": "1",
                                    "team_h_score": "19",
                                    "-kickoff_time": 1236936900
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Eels",
                                    "team_h_name": "Warriors",
                                    "team_a_score": "18",
                                    "finished": "1",
                                    "team_h_score": "26",
                                    "-kickoff_time": 1237012200
                                },
                                {
                                    "value": "Away",
                                    "is_correct": 0,
                                    "team_a_name": "Sea Eagles",
                                    "team_h_name": "Bulldogs",
                                    "team_a_score": "12",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237019400
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Panthers",
                                    "team_h_name": "Sharks",
                                    "team_a_score": "10",
                                    "finished": "1",
                                    "team_h_score": "18",
                                    "-kickoff_time": 1237019400
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 1,
                                    "team_a_name": "Knights",
                                    "team_h_name": "Titans",
                                    "team_a_score": "20",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237086000
                                },
                                {
                                    "value": "Home",
                                    "is_correct": 0,
                                    "team_a_name": "Rabbitohs",
                                    "team_h_name": "Roosters",
                                    "team_a_score": "52",
                                    "finished": "1",
                                    "team_h_score": "12",
                                    "-kickoff_time": 1237089600
                                },
                                {
                                    "value": "Away",
                                    "is_correct": 0,
                                    "team_a_name": "Raiders",
                                    "team_h_name": "Tigers",
                                    "team_a_score": "26",
                                    "finished": "1",
                                    "team_h_score": "34",
                                    "-kickoff_time": 1237190400
                                }
                            ],
                            "name": "The Fanatic",
                            "id": "13914",
                            "user_name": "fanatic"
                        }
                    ],
                    "name": "Round " + round,
                    "start_date": "13 Mar 18:00",
                    "id": round
                });
			}, Math.random() * 1000);
		}
	});
	
	// JSON based Tipping Service implementation
	$.fs.tipping.service.json = $.klass($.fs.tipping.service.intaface, {
		defaults: {
			path: "http://www.foxsports.com.au/xmlfeed/ism/feeds"
		},
		
		initialize: function(opts) {
			this.opts = $.extend({}, this.defaults, opts);
			
			// Used to store cached data (so we don't have to reload data)
			// We cache each code separately
			this.cachedData = {
				s14: undefined,
				nrl: undefined,
				afl: undefined,
				aleague: undefined,
				epl: undefined
			};
		},
		
		// Private helper method to load the data (handles caching as well)
		_loadData: function(code, successDelegate, failureDelegate) {
			var self = this;
			
			// Once data has loaded (from cache or remotely) then find round we want
			var dataLoaded = function(data) {
				// Cache it
				self.cachedData[code] = data;
				successDelegate.call(self, data);
			};
			
			if (this.cachedData[code] === undefined) {
				$.ajax({
					type: "GET",
					url: this.opts.path + "/foxau_" + code + "p/celtip.json",  
					data: { cacheBuster: parseInt(Math.random() * 1000000000, 10) },
					success: dataLoaded,
					error: failureDelegate,
					dataType: "json"
				});	
			} else {
				// We know cache data is success, because it only gets cached if success
				dataLoaded(this.cachedData[code]);
			}
		},
		
		getLatestRoundNumber: function(code, successDelegate, failureDelegate) {
			var self = this;
			
			// Once data has loaded (from cache or remotely) then find round we want
			var dataLoaded = function(data) {
				try {
					var roundData = data[0].events.event;
					successDelegate.call(self, parseInt(roundData[roundData.length - 1].id, 10));
				} catch (err) {
					if (failureDelegate !== undefined) { failureDelegate.call(self); }
				}	
			};
			
			// Use helper method to load data first
			this._loadData(code, dataLoaded, failureDelegate);
		},
		
		getTips: function(code, round, successDelegate, failureDelegate) {	
			var self = this;
			
			// Once data has loaded (from cache or remotely) then find round we want
			var dataLoaded = function(data) {
				// Find round we want
				var success = false;
				
				try {
					$.each(data.events.event, function(i, roundData) {
						if (roundData.id == round) {
							successDelegate.call(self, roundData);
							success = true;
						}
					});
				} catch (err) {
					if (failureDelegate !== undefined) { failureDelegate.call(self); }
				}
				
				if (!success && failureDelegate !== undefined) { failureDelegate.call(self); }
			};
			
			// Use helper method to load data first
			this._loadData(code, dataLoaded, failureDelegate);
		}
	});
})(jQuery);// jquery.fs.tippingmodule
// Fox Sports tipping Module
// (c)2009 Edmond Leung/Fox Sports
//
// Adds JS functionality to a tipping module.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
// jquery.fs.ism.js
//
// Usage:
// $('.tipping-module').fs.tippingmodule();

(function($) {    
    var functions = {
    	generateHeader: function(tippingModule, data) {
    		var headerRow = $("<tr></tr>");
    		
    		// Retrieve the sport code this tipping module represents
    		var code = tippingModule.data('tippingCode');
    		
    		var highestTotalPredictions = 0;
    		$.each(data.entry, function(i, expert) {
    			if (expert.total_predictions > highestTotalPredictions) {
    				highestTotalPredictions = expert.total_predictions;
    			}
    			
    			// Generate header for each expert
    			var th = $("<th></th>").addClass('expert')
    						  .addClass(expert.user_name)
			    			  .attr('title', expert.name)
			    			  .attr('abbr', expert.name)
			    			  .appendTo(headerRow);

    			$('<span></span>').html("<strong>" + expert.total_correct + "</strong>").appendTo(th);
    		});
    		
    		$("<th></th>").addClass(code)
    					  .addClass('total-tips')
    					  .attr('title', 'Total Tips')
			    		  .attr('abbr', 'Total Tips')
			    		  .prependTo(headerRow)
    					  .html("Total tips made: <strong>" + highestTotalPredictions + "</strong");
    		
    		return headerRow;
    	},
    	
    	generateTable: function(tippingModule, data) {
    		var code = tippingModule.data('tippingCode');
    		
    		var table = $("<table><tbody></tbody></table>");
    		var tbody = table.find('tbody');
    		
    		// Generate the header row
			functions.generateHeader(tippingModule, data).appendTo(tbody);
    		
    		var rows = [];
    		
    		// Generate the data
    		$.each(data.entry, function(i, expert) {
    			$.each(expert.prediction, function(i, prediction) {
    				// See if this row for the match already exists
    				var row = rows[i];
    				
    				// If not, create it
    				if (row === undefined) {
    					row = rows[i] = {
    						name: prediction.team_a_name + " v " + prediction.team_h_name
    					};
    				}
    				
    				// Store the current experts results
    				row[expert.user_name] = {
    					team: prediction.value == "Home" ? prediction.team_h_name : prediction.team_a_name,
    					isCorrect: (prediction.is_correct == 1)
					};
    			});
    		});
    		
    		// Render the restructured data
    		$.each(rows, function(i, row) {
    			var matchRow = $('<tr></tr>').appendTo(tbody);
    			var nameTd = $('<td></td>').appendTo(matchRow).text(row.name);
    			
    			$.each(data.entry, function(j, expert) {
    				var restructuredExpertData = row[expert.user_name];
    				
    				var expertTd = $('<td></td>').addClass('tip')
    											 .addClass(restructuredExpertData.isCorrect ? 'tip-correct' : 'tip-incorrect')
    											 .appendTo(matchRow);
    				
    				// Work out short and long name			 
					var abbrName, longName = restructuredExpertData.team;
					$.each($.fs.ism.teams[code], function(i, team) {
						if (team.name == restructuredExpertData.team) {
							abbrName = team.tla;
						}
					});
					if (abbrName === undefined) {
						abbrName = longName.substring(0, 3);
					}

    				var abbrTeamName = $('<abbr>' + abbrName + '</abbr>')
    											 .attr('title', longName)
												 .appendTo(expertTd)
												 .text();
    			});
    		});
    		
    		// Add first and last classes
    		table.find('th:first-child, td:first-child').addClass('first');
    		table.find('th:last-child, td:last-child').addClass('last');
    		
    		return table;
    	},
    	
    	reloadData: function() {
    		var self = $(this);
    		var parentModule = self.closest('.module');
    		
    		// Retrieve stored variables
    		var code = self.data('tippingCode');
    		var service = self.data('tippingService');
    		var opts = self.data('tippingOptions');
    		var round = self.data('tippingRound');
    		
    		// Success call back method (called when data is successfully loaded)
    		var success = function(data) {
	    		self.find('table, p.module-error').remove();
	    		functions.generateTable(self, data).appendTo(self);
	    		
	    		// Data has loaded, no longer in 'loading' state
    			parentModule.removeClass('loading');
    		};
    		    		
    		var failure = function() {
    			// Show error message, and stop loading indicator
    			self.find('table, p.module-error').remove();
    			
    			var errorMessage = $('<p class="module-error"></p>').text(opts.errorMessage);
    			var tryAgainLink = $('<a href="#reload-tipping">Please try again.</a>').click(function() {
    				functions.reloadData.call(self);
    				return false;
    			}).appendTo(errorMessage);
    			
    			errorMessage.appendTo(self);
    			
    			parentModule.removeClass('loading');
    		};
    		
    		// Called when the latest round number has been retrieved
    		var roundRetrieved = function(roundNumber) {
    			// Handle negative round numbers
    			if (round !== undefined && round !== "") { roundNumber += parseInt(round, 10); }
    			
    			// Update tabs round number displays
    			var tabIndex = parentModule.find('.tab-content').index(self);
    			var tabControl = parentModule.find('ul.tab-set li.tab a:eq(' + tabIndex + ')');
    			
    			// Remove if round is too low and doesn't exist
    			if (roundNumber < 1) {
    				tabControl.parent().remove();
    				self.remove();
    				return;	
    			}   			
    			
    			$(tabControl).text('Round ' + roundNumber);	
    			
    			service.getTips(code, roundNumber, success, failure);
    		};
    		
    		// Let CSS know the module is in 'loading' state
    		parentModule.addClass('loading');
    		
    		if (round === undefined || round === "" || parseInt(round, 10) < 0) {
    			// Get the latest round first
    			service.getLatestRoundNumber(code, roundRetrieved, failure);	
    		} else {
    			roundRetrieved(round);
    		}
    	}
    };
    
    // Create fs.tippingmodule jquery call
    $.namespace('fn.fs', {
        tippingmodule: function(service, opts) {
            opts = $.extend({}, $.fn.fs.tippingmodule.defaults, opts);

            return this
                .each(function() {
                	var self = $(this);
                	var parent = self.closest('.module');
                	
                	// Inject loading indicator
                	var moduleHeader = parent.find('.module-header');
                	var loadingIndicator = $('<span class="module-load-indicator">Loading...</span>').appendTo(moduleHeader);
                	
                	// Get the sport code this tipping module represents
                	var code = null;
                	var classNames = parent.attr('class').toLowerCase().split('-').join('').split(' ');
                	$.each($.fs.ism.teams, function(key, value) {
                		if ($.inArray(key, classNames) > -1) { code = key; }
                	});
                	
                	// Exit if no code found
                	if (code === null) { return; }
                	
                	var round = self.attr('title');
                	self.attr('title', ''); // Clear title now since it's meaningly numbers
                	
                	// Store variables so we can use later
                	self.data('tippingService', service);
                	self.data('tippingCode', code);
                	self.data('tippingOptions', opts);
                	self.data('tippingRound', round);
                	
                	functions.reloadData.call(self);
                });
        }
    });
    
    // Setup defaults for tippingmodule plugin
    $.namespace('fn.fs.tippingmodule', {
        defaults: {
        	errorMessage: "Unable to load the required data. "
        }
    });
})(jQuery);(function($) {
	$.namespace('fs.topgoalscorers.service');

	// Interface for topgoalscorers Service implementation
	$.fs.topgoalscorers.service.intaface = $.klass({
		/**
		 * init - Constructor, responsible for doing any setup work required
		 * by your delegate, eg. preloading data.
		 **/
		initialize: function() {
			throw "init not implemented";
		},
		
		/**
		 * getScorers - Should return a list of the top goal scorers.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getScorers: function(code, successDelegate, failureDelegate) {
			throw "getScorers not implemented";
		}
	});
	
	// Mock Top Goal Scorers Service implementation for testing
	$.fs.topgoalscorers.service.mock = $.klass($.fs.topgoalscorers.service.intaface, {
		defaults: {
		},
		
		initialize: function() {
		},
		
		getScorers: function(code, successDelegate, failureDelegate) {
			setTimeout(function() {
				successDelegate.call(this, {
					"goal_scorers": {
					"series_name": "Hyundai A-League",
					"series_code": "A-League",
					"season": 2010,
					"scorers": [
						{
							"rank": 1,
							"player_name": "Mate Dugandzic",
							"player_short": "M Dugandzic",
							"team_name": "Melbourne Victory",
							"team_code": "MVC",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Alex Wilkinson",
							"player_short": "A Wilkinson",
							"team_name": "Central Coast Mariners",
							"team_code": "CCM",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Billy Celeski",
							"player_short": "B Celeski",
							"team_name": "Melbourne Victory",
							"team_code": "MVC",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Mile Sterjovski",
							"player_short": "M Sterjovski",
							"team_name": "Perth Glory",
							"team_code": "PER",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Scott Neville",
							"player_short": "S Neville",
							"team_name": "Perth Glory",
							"team_code": "PER",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Branko Jelic",
							"player_short": "B Jelic",
							"team_name": "Perth Glory",
							"team_code": "PER",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Shannon Cole",
							"player_short": "S Cole",
							"team_name": "Sydney FC",
							"team_code": "SYD",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Chris Payne",
							"player_short": "C Payne",
							"team_name": "North Queensland Fury",
							"team_code": "NQF",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Alex Brosque",
							"player_short": "A Brosque",
							"team_name": "Sydney FC",
							"team_code": "SYD",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Terry McFlynn",
							"player_short": "T McFlynn",
							"team_name": "Sydney FC",
							"team_code": "SYD",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Leigh Broxham",
							"player_short": "L Broxham",
							"team_name": "Melbourne Victory",
							"team_code": "MVC",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "Chris Grossman",
							"player_short": "C Grossman",
							"team_name": "North Queensland Fury",
							"team_code": "NQF",
							"goals": 1
						},
						{
							"rank": 1,
							"player_name": "David Williams",
							"player_short": "D Williams",
							"team_name": "North Queensland Fury",
							"team_code": "NQF",
							"goals": 1
						}
					]
				}
			});
			}, Math.random() * 1000);
		}
	});
	
	// JSON based Top Goal Scorers Service implementation
	$.fs.topgoalscorers.service.json = $.klass($.fs.topgoalscorers.service.intaface, {
		defaults: {
			path: "http://www.foxsports.com.au/xmlfeed"
		},
		
		initialize: function(opts) {
			this.opts = $.extend({}, this.defaults, opts);
			
			// Used to store cached data (so we don't have to reload data)
			// We cache each code separately
			this.cachedData = {
			};
		},
		
		// Private helper method to load the data (handles caching as well)
		_loadData: function(filename, successDelegate, failureDelegate) {
			var self = this;
			
			// Once data has loaded (from cache or remotely) then find round we want
			var dataLoaded = function(data) {
				// Cache it
				self.cachedData[filename] = data;
				successDelegate.call(self, data);
			};
			
			if (this.cachedData[filename] === undefined) {
				$.ajax({
					type: "GET",
					url: this.opts.path + "/" + filename + ".json",  
					data: { cacheBuster: parseInt(Math.random() * 1000000000, 10) },
					success: dataLoaded,
					error: failureDelegate,
					dataType: "json"
				});	
			} else {
				// We know cache data is success, because it only gets cached if success
				dataLoaded(this.cachedData[filename]);
			}
		},
		
		getScorers: function(filename, successDelegate, failureDelegate) {	
			// Use helper method to load data first
			this._loadData(filename, successDelegate, failureDelegate);
		}
	});
})(jQuery);// jquery.fs.topgoalscorersmodule
// Fox Sports Top Goal Scorers Module
// (c)2009 Edmond Leung/Fox Sports
//
// Adds JS functionality to a top goal scorers module.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
// jquery.fs.ism.js
//
// Usage:
// $('.topgoalscorers-module').fs.topgoalscorersmodule();

(function($) {    
    var functions = {
    	generateHeader: function(topgoalscorersModule, data) {
    		var headerRow = $("<tr></tr>");
    		
    		$.each({ rank: "" , player_name: "Player" , team_code: "Team", goals: "Goals" }, function(key, value) {
    			// Generate header
    			var th = $("<th></th>")
    						  .addClass(key)
			    			  .attr('title', value)
			    			  .attr('abbr', value)
			    			  .html(value)
			    			  .appendTo(headerRow);
    		});
    		
    		return headerRow;
    	},
    	
    	generateTable: function(topgoalscorersModule, data) {
    		var table = $("<table><tbody></tbody></table>");
    		var tbody = table.find('tbody');
    		
    		// Generate the header row
			functions.generateHeader(topgoalscorersModule, data).appendTo(tbody);
    		
    		var rows = [];
    		
    		// Generate the data
    		$.each(data.goal_scorers.scorers, function(i, scorer) {
    			var row = $('<tr></tr>').appendTo(tbody);
    			
        		$.each(["rank", "player_name", "team_code", "goals"], function(j, columnName) {
        			var data;
        			
        			if (columnName == 'rank') {
        				data = i + 1;
        			} else {
        				data = scorer[columnName];
        			}
        			
        			// Generate row
        			var td = $("<td></td>")
        			 			  .addClass(columnName)
    			    			  .html(data)
    			    			  .appendTo(row);
        		});
    		});
    		
    		// Add first and last classes
    		table.find('th:first-child, td:first-child').addClass('first');
    		table.find('th:last-child, td:last-child').addClass('last');
    		
    		return table;
    	},
    	
    	reloadData: function() {
    		var self = $(this);
    		var parentModule = self.closest('.module');
    		
    		// Retrieve stored variables
    		var filename = self.data('topgoalscorersFilename');
    		var service = self.data('topgoalscorersService');
    		var opts = self.data('topgoalscorersOptions');
    		
    		// Success call back method (called when data is successfully loaded)
    		var success = function(data) {
	    		self.find('table, p.module-error').remove();
	    		functions.generateTable(self, data).appendTo(self);
	    		
	    		// Data has loaded, no longer in 'loading' state
    			parentModule.removeClass('loading');
    		};
    		    		
    		var failure = function() {
    			// Show error message, and stop loading indicator
    			self.find('table, p.module-error').remove();
    			
    			var errorMessage = $('<p class="module-error"></p>').text(opts.errorMessage);
    			var tryAgainLink = $('<a href="#reload-topgoalscorers">Please try again.</a>').click(function() {
    				functions.reloadData.call(self);
    				return false;
    			}).appendTo(errorMessage);
    			
    			errorMessage.appendTo(self);
    			
    			parentModule.removeClass('loading');
    		};
    		
    		// Let CSS know the module is in 'loading' state
    		parentModule.addClass('loading');
    		
			service.getScorers(filename, success, failure);
    	}
    };
    
    // Create fs.topgoalscorersmodule jquery call
    $.namespace('fn.fs', {
        topgoalscorersmodule: function(service, opts) {
            opts = $.extend({}, $.fn.fs.topgoalscorersmodule.defaults, opts);

            return this
                .each(function() {
                	var self = $(this);
                	var parent = self.closest('.module');
                	
                	// Inject loading indicator
                	var moduleHeader = parent.find('.module-header');
                	var loadingIndicator = $('<span class="module-load-indicator">Loading...</span>').appendTo(moduleHeader);
                	
                	// Get the sport code this topgoalscorers module represents
                	var filename = null;
                	filename = parent.attr('rel');
                	
                	// Exit if no code found
                	if (filename === null) { return; }
                	
                	// Store variables so we can use later
                	self.data('topgoalscorersService', service);
                	self.data('topgoalscorersFilename', filename);
                	self.data('topgoalscorersOptions', opts);
                	
                	functions.reloadData.call(self);
                });
        }
    });
    
    // Setup defaults for top goal scorers module plugin
    $.namespace('fn.fs.topgoalscorersmodule', {
        defaults: {
        	errorMessage: "Unable to load the required data. "
        }
    });
})(jQuery);/*jslint evil: true */

// jquery.fs.tvguidemodule
// Fox Sports TV Guide Module Show Details
// (c)2009 Brendan Cartledge/Fox Sports
//
// Creates an overlay/lightbox effect for the details of each show in the tv-guide module.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
// jquery.tools.scrollable.navigator.js
//
// Usage:
// $('input').fs.tvguidemodule();  for the overlay show details to come up on the click of each item in the tvguide
// $('input').fs.tvguideaccordian();  for the accordian effect on display of individual show details

(function($) {    
    var functions = {
    	getEnvironmentPath: function() {
    		var location = window.location.href;
    		
    		if (location.indexOf('http') == -1) {
    			return 'json-samples/epg-programme.json';
    		} else if (location.indexOf('cms.news') != -1) {
    			return '/cs/ContentServer/internal-syndication/json/epg-programme?site=FoxSports';
    		} else {
    			return '/internal-syndication/json/epg-programme';
    		}
    	},
    	
    	stringToDate: function(stringDate) {
    		stringDate = stringDate.split('+')[0]; // Get rid of timezone
			return Date.parseExact(stringDate, "yyyy-MM-ddTHH:mm:ss");  // The Date of 15-Oct-2004
    	},
    	
    	stringDateInMilliseconds: function(stringDate) {
    		return functions.stringToDate(stringDate).getTime();
    	},
    	
    	reformatDate: function(stringDate) {
    		return functions.stringToDate(stringDate).toString('dddd, MMMM d');
    	},
    	
    	reformatTime: function(stringDate) {
    		return functions.stringToDate(stringDate).toString('h:mm tt');
    	},

    	createBlankHiddenDetails: function() {
    		var self = $(this);
    		
	    	var hiddenDiv = $('' +
					'<div style="display: none">' +
						'<div class="tvguide-details">' + 
					    	'<div class="module-border">' +
					    		'<div class="module-content loading">' +
					    		'</div>' +
					    	'</div>' +
					    '</div>' +
					'</div>');

			// Finally, add the created hidden div into the tv guide show td
			hiddenDiv.appendTo(self.find('.tvguide-show'));
			
	    	return hiddenDiv.find('.tvguide-details');
    	},
    		
    	// Creates the tvguide details div dynamically using JS from JSON data
    	addHiddenDetails: function(hiddenDiv, data) {
    		var self = $(this);
    		
    		// Retrieve the programme data from the JSON feed
    		var programmeData = data.response['container-1'][0]['group-content-1'][0];
			
			var moduleContent = hiddenDiv.find('.module-content');
			moduleContent.removeClass('loading');
			
			var overlayHeader = $('' +
					'<div class="overlay-show-header">' +
						'<h3 class="heading">' + programmeData.genretitle + ': ' + programmeData.programmetitle + ' ' + programmeData.title + '</h3>' +
					'</div>').appendTo(moduleContent);
			
			var overlayShowInfo = $('' +
					'<div class="overlay-show-info">' + 
						'<ul class="tv-channels">' +
							'<li class="channel-' + programmeData.channelabbreviation + '">' + programmeData.channelabbreviation + '</li>' +
						'</ul>' +
						'<p>' + functions.reformatDate(programmeData.startTime) + '</p>' +
						'<p class="tv-time">' +
							'<span class="showtime">' + functions.reformatTime(programmeData.startTime) + ' - ' + functions.reformatTime(programmeData.endTime) + '</span>' +
						'</p>' +
					'</div>').appendTo(moduleContent);
			
			if (programmeData.isLive) {
				$('<a class="live">live</a>').appendTo(overlayShowInfo.find('.tv-time'));
			}
			
			var accordion = $('' + 
					'<div class="accordian">' +
						'<h3 class="accordheader"><a class="active">&gt;</a>Show Details</h3>' +
						'<div class="overlay-show-details accorditem">' +
							'<p>' + programmeData.details + '</p>' +
							'<div class="show-info">' +
								'<ul class="generalinfo">' +
								'</ul>' +
							'</div>' +
						'</div>' + 
						'<h3 class="accordheader alt-time-header">' +
							'<a class="inactive">&gt;</a> Show Alternate Viewing Times'+
						'</h3>' +
						'<div class="overlay-show-alt accorditem"><div class="details-alt-time"></div></div>' +
					'</div>').appendTo(moduleContent);

			var generalInfo = accordion.find('.generalinfo');
			
			if (programmeData.rating != 'NC') {
				$('<li class="rated-' + programmeData.rating.toLowerCase() + '">Rating</li>').appendTo(generalInfo);
			}
			
			if (programmeData.isWidescreen) {
				$('<li class="widescreen">Widescreen</li>').appendTo(generalInfo);
			}
			
			var overlayShowAlt = accordion.find('.details-alt-time');
		
			// Get the milliseconds of the current episode so we don't show in alternate times
			var currentTimeMilliseconds = new Date().getTime();
			var currentEpisodeMilliseconds = functions.stringDateInMilliseconds(programmeData.startTime); 
			
			// Sort function to sort alternate times by milliseconds on start time
			var sortByMilliseconds = function(a, b) {
				return a.milliseconds > b.milliseconds;
			};
			
			// Sort alternate times first
			for (var i = 0; i < programmeData.alternateTimes.length; i++) {
				var alternateTime = programmeData.alternateTimes[i];
				alternateTime.milliseconds = functions.stringDateInMilliseconds(alternateTime.startTime);
			}
			
			// Perform the sort
			programmeData.alternateTimes.sort(sortByMilliseconds);
			
			// Render the sorted alternate times
			for (var j = 0; j < programmeData.alternateTimes.length; j++) {
				alternateTime = programmeData.alternateTimes[j];
				
				// Don't render if time is the same, or passed already
				if (alternateTime.milliseconds == currentEpisodeMilliseconds ||
					alternateTime.milliseconds < currentTimeMilliseconds) {
					continue;
				}
				
				var overlayAltTime = $('' + 
					'<div class="overlay-alt-time">' +
						'<div class="overlay-alt-channel">' +
							'<a class="channel-' + alternateTime.channelabbreviation + 'vert">' + alternateTime.channelabbreviation + '</a>' +
						'</div>' +
						'<p>' + functions.reformatDate(alternateTime.startTime) + ' at ' + functions.reformatTime(alternateTime.startTime) + '</p>' +
					'</div>').appendTo(overlayShowAlt);
			}
			
			// Add no times message if no alternate times found
			if (accordion.find('.overlay-alt-time').size() === 0) {
				// Show no alternate times message
				var noAltTimes = $('' + 
					'<div class="no-alt-times">' +
	                	'<p>There are no alternative times listed for this program</p>' +
	                '</div>').appendTo(overlayShowAlt);
			}
			
			// Make sure accordion works
			var tvGuideDetails = hiddenDiv;
			$(tvGuideDetails).fs.tvguideaccordian();
			
			return tvGuideDetails;
    	}
    };
    
    // Create fs.tvguidemodule jquery call
    $.namespace('fn.fs', {
        tvguidemodule: function(opts) {
            opts = $.extend({}, $.fn.fs.tvguidemodule.defaults, opts);
            
            this.hover(
            	function() {
            		$(this).find('.tvguide-show').addClass('tvguide-show-hover');
            	}, 
            	function() {
            		$(this).find('.tvguide-show').removeClass('tvguide-show-hover');
            	}
            );
            
            return this.click(function(e) {
				var self = $(this);
				
				e.preventDefault();
				e.stopPropagation();
				
				// Function to show the overlay with the specified element in it
				var showOverlay = function(hiddenDetails) {
					$(self).fs.overlay({ 
						className: "foxsports-tvshowmodule",
						inline: hiddenDetails
					});
				};

				// Find and see if the hidden details already exists
				var hiddenDetails = self.find('.tvguide-details');
				if (hiddenDetails.size() === 0) {
					// Create the tv guide details div with JSON data
					hiddenDetails = functions.createBlankHiddenDetails.call(self);
					showOverlay(hiddenDetails);
					
					// If it doesn't exist, we need to call an AJAX call to create it with JSON data
					$.get(functions.getEnvironmentPath(), {
						epgId: self.attr('id')	// ID is inside the tr row
					}, function(data) {
						// Strip comments before using as json data
						data = data.replace(/<\!\-\-(.*)\-\->/g, '');
						eval('data = ' + data + ';');
						
						// Create the tv guide details div with JSON data
						functions.addHiddenDetails.call(self, hiddenDetails, data);
						
						hiddenDetails.find('.module-content').removeClass('loading');
					});
					
				} else {
					// Since we already have the tvguide details div, we just need to show it
					showOverlay(hiddenDetails);
				}
				
				return false;
			});
        },
		tvguideaccordian: function(opts) {     
			opts = $.extend({}, $.fn.fs.tvguideaccordian.defaults, opts);
			
			$(this).find('.overlay-show-alt').hide();
			
			$(this).find('.accordian .accordheader').click(function() {
				var accordstatus = $(this).children('a').attr('class');
				
				if (accordstatus == "active") {
					$(this).
						next('.accorditem'). 
						slideUp('normal'). 
						siblings('.accorditem').
						slideDown('normal'); 
					
					$(this).children('a').removeClass('active').addClass('inactive');
					$(this).siblings().children('a').removeClass('inactive').addClass('active');
				}
				else {
					$(this).
						next('.accorditem'). 
						slideDown('normal'). 
						siblings('.accorditem').
						slideUp('normal'); 
					
					$(this).children('a').removeClass('inactive').addClass('active');
					$(this).siblings().children('a').removeClass('active').addClass('inactive');
				}
			});
		}
    });
    
    // Setup defaults for gallery plugin
    $.namespace('fs.tvguidemodule', {
        defaults: {
        }
    });
    
    $.namespace('fs.tvguideaccordian', {
        defaults: {
        }
    });	
})(jQuery);

    
    

	(function($) {    
    var functions = {
    	gotoAddress: function(address) {
    		var self = this;
    		
    		var opts = self.data('venuefinderOpts');
    		var geocoder = self.data('venuefinderGeoCoder');
    		var map = self.data('venuefinderMap');
    		var currentEvent = self.data('venuefinderCurrentEvent');
    		
    		if (geocoder) {
				geocoder.geocode( { 'address': address}, function(results, status) {
					if (status == google.maps.GeocoderStatus.OK) {
						map.setCenter(results[0].geometry.location);
						map.setZoom(opts.closeUpZoomLevel);
					} else {
					}
				});
				
				// Clear "../at/eventname" in url
				window.location.hash = functions.getURLName(currentEvent.title) + "/at/";
			}
    	},
    		
    	getURLName: function(s) {
	    	if (s !== null) {
	            if(typeof(s) === "string") {
	                if(s.length) {
	                    if(s.length > 0) {
	                        var r = s.replace(/[()]/gi, "-");
	                        r = r.replace(/[^a-z]+$/gi, "-");
	                        r = r.replace(/\s/gi, "-");
	                        r = r.replace("&", "and", "gi");
	                        r = r.toLowerCase();
	                        return r;
	                    }
	                }
	            }
	        }
    	},
    	
    	navigateToURLName: function(urlName) {
    		// If no url name to navigate to, then don't
    		if (urlName === "") {
    			return;
    		}
    		
    		var self = $(this);
    		var opts = self.data('venuefinderOpts');
    		var map = self.data('venuefinderMap');
    		var markers = self.data('venuefinderMarkers');
    		
    		// Search using the url name and open it up
    		var markerData = markers[urlName];
    		if (markerData === undefined) { return; }
    		
    		var marker = markerData.marker;
    		var venue = markerData.venue;
    		
    		// Grab the venues geo location
			var g = venue.g.split(',');
    		
			// Zoom into the venue
    		map.setZoom(opts.closeUpZoomLevel);
    		map.setCenter(new google.maps.LatLng(g[0], g[1]));
    		
    		functions.showVenue.call(this, marker, venue);
    	},
    	
    	showVenue: function(marker, venue) {
    		var self = $(this);		
    		
			var map = self.data('venuefinderMap');
			var infoWindow = self.data('venuefinderInfoWindow');
			var currentEvent = self.data('venuefinderCurrentEvent');
			
			// Work out how to display address and number (if they exist)
			var address = venue.a1 || "";
			var number = venue.p || "";
			
			if (address !== "") { address += " <br/> "; }
			address += venue.c || "";
			if (address !== "") { address += " " + (venue.z || ""); }
			
			if (address !== "") {
				address = "<p class='address'>" + address + "</p>";
			}
			
			if (number !== "") {
				number = "<p class='number'>" + venue.p + "</p>";
			}
			
			// Make sure url has http in it
			var h3 = "";
			var www = venue.w;
			if (www === undefined || www === null) {
				h3 = "<h3>" + venue.n + "</h3>";
			} else {
				if (www.indexOf('http://') == -1) {
					www = "http://" + www;
				}
				h3 = "<h3><a href='" + www + "'>" + venue.n + "</a></h3>";
			}

			
        	// Set info window content
			infoWindow.setContent(
				"<div class='venuefinder-info'>" +
					h3 +
					address +
					number +
					"<p><em>Call to confirm showing</em></p>" +
				"</div>");
			
        	infoWindow.open(map, marker);
        	
        	// Change the URL to match venue
        	window.location.hash = functions.getURLName(currentEvent.title) + "/at/" + functions.getURLName(venue.n);
    	},
    	
    	addMarker: function(venue) {
    		// Ignore venue if geo location is not given
			if (venue.g === undefined || venue.g === null) { return; }
    		
    		var self = $(this);			
			var map = self.data('venuefinderMap');
			var fluster = self.data('venuefinderFluster');
			var infoWindow = self.data('venuefinderInfoWindow');
			var markerImage = self.data('venuefinderMarkerImage');
    		
			var g = venue.g.split(',');
			
			var image = new google.maps.MarkerImage(markerImage,
				new google.maps.Size(50, 41),
				new google.maps.Point(0, 0),
				new google.maps.Point(25, 41)
			);
		
			// Add market to the clusterer
            var marker = new google.maps.Marker({
                position: new google.maps.LatLng(g[0], g[1]),
                title: venue.n,
                icon: image
            });
            
            // Add click event to open info window
            google.maps.event.addListener(marker, 'click', function() {
            	functions.showVenue.call(self, marker, venue);
        	});
            
            fluster.addMarker(marker);
            
            return marker;
    	},
    	
    	loadEvents: function(events) {
    		var self = $(this);
    		
    		// Remove all previous events first
    		self.find('.venuefinder-events ul li').remove();
    		
    		// Add the events one by ones
    		$.each(events, function(i, event) {
    			functions.addEvent.call(self, event);
    		});
    	},
    	
    	addEvent: function(event) {
    		var self = $(this);
    		
    		// Format desired date
    		var date = Date.parse(event.starts);
    		var formattedDate = date.toString('MMMM d');
    		
    		var lastDigit = parseInt(formattedDate[formattedDate.length - 1], 10);
    		switch (lastDigit) {
	    		case 1: formattedDate += "st"; break;
	    		case 2: formattedDate += "nd"; break;
	    		case 3: formattedDate += "rd"; break;
	    		default: formattedDate += "th"; break;
    		}
    		
    		var eventLi = $('<li></li>').appendTo($(this).find('.venuefinder-events ul'));
    		$('<a class="venuefinder-event-title" href="#' + functions.getURLName(event.title) + '/at/">' + event.title + '</a>').appendTo(eventLi);
    		$('<span class="venuefinder-event-date">' + formattedDate + '</span>').appendTo(eventLi);
    		
    		eventLi.click(function() {
    			functions.showEvent.call(self, event);
				window.location.hash = functions.getURLName(event.title) + "/at/";
    		});
    	},
    	
    	restartMap: function() {
    		var self = $(this);
    		
    		var opts = self.data('venuefinderOpts');
    		var infoWindow = self.data('venuefinderInfoWindow');
    		
    		var mapDiv = self.find('.venuefinder-map').empty();
    		
        	var geocoder = new google.maps.Geocoder();
            var map = new google.maps.Map(mapDiv[0], {
    				zoom: 4,
    				center: new google.maps.LatLng(-26.431228, 135), // Default location is Australia
    				mapTypeId: google.maps.MapTypeId.ROADMAP
            	}
            );
            
            // Create clusterer
        	var fluster = new Fluster2(map);
        	fluster.gridSize = opts.clusterGridSize;
        	
            // Close info window on map click
            google.maps.event.addListener(map, 'click', function() {
            	infoWindow.close();
        	});
            
            self.data('venuefinderGeoCoder', geocoder);
			self.data('venuefinderMap', map);
			self.data('venuefinderFluster', fluster);
    	},
    	
    	showEvent: function(event) {
    		functions.restartMap.call(this);
    		
    		var self = $(this);
    		
			var service = self.data('venuefinderService');
			var markers = self.data('venuefinderMarkers');
			var fluster = self.data('venuefinderFluster');
			
			// Store the current event that we're displaying, and store the previous one too
			self.data('venuefinderPreviousEvent', self.data('venuefinderCurrentEvent'));
			self.data('venuefinderCurrentEvent', event);
			
			var previousEvent = self.data('venuefinderPreviousEvent');
			
			// Add event info to the venuefinder header
			var h3 = self.find('.venuefinder-event-info h3');
			h3.text(event.title);
			
			var dateSpan = self.find('.venuefinder-event-info .venuefinder-event-date');
			if (event.starts !== undefined) {
	    		var date = Date.parse(event.starts);
	    		var formattedDate = date.toString('dddd MMMM d, h:mmtt');
	    		
				dateSpan.text(formattedDate);
			} else {
				dateSpan.text('');
				dateSpan.hide();
			}
			
			// Add and remove class names used for styling specific events
			self.addClass(functions.getURLName(event.title));
			if (previousEvent !== undefined) {
				self.removeClass(functions.getURLName(previousEvent.title));
			}
    		
        	// Retrieve the geolocation files to use 
        	var files = event.file;
        	if (typeof(files) == "string") {
        		files = [ files ];
        	}
        	
        	// Retrieve the venues and add the markers representing them
            service.getVenues(files, function(venues) {
        		$.each(venues, function(i, venue) {
        			var marker = functions.addMarker.call(self, venue);
        			
        			// Store into a list of markers using url name
        			var urlName = functions.getURLName(venue.n);
        			markers[urlName] = { marker: marker, venue: venue };
        		});
                
                fluster.initialize();
                
                // Navigate to a venue right away if it's in the URL
                if (window.location.hash.indexOf('at') >= 0) {
                	var urlName = window.location.hash.split('/at/')[1];
                	functions.navigateToURLName.call(self, urlName);
                }
        	});
    	}
    };
    
    // Create fs.venuefinder jquery call
    $.namespace('fn.fs', {
        venuefinder: function(service, opts) {
            opts = $.extend({}, $.fn.fs.venuefinder.defaults, opts);

            return this.each(function() {
            	var self = $(this);

            	// Create a single info window for efficiency
    			var infoWindow = new google.maps.InfoWindow();
    			
                // Store markers, key is unique id (also the URL name)
                var markers = {};
                
                // Retrieve the master data so we can initialise the venue finder
                service.getMasterData(function(masterData) {
                	self.data('venuefinderMarkerImage', masterData.markerImage);
                	
                	// Add the class name of the mode so we can style differently
                	self.addClass('venuefinder-' + masterData.mode + '-mode');
                	
                	// Add the events into the events list if in 'list' mode
                	if (masterData.mode == "list") {
                		// Add venue finder events divs
                		$('<div class="venuefinder-events"><ul></ul></div>').prependTo(self.find('.venuefinder-content'));
                		
                		functions.loadEvents.call(self, masterData.events);
                		
                		self.find('.venuefinder-events li:first-child').addClass('first');
                		self.find('.venuefinder-events li:last-child').addClass('last');
                	}
                	
                	// Load the first event by default
                	var defaultEvent = masterData.events[0];
                	
                    // Navigate to a event right away if it's in the URL
                    if (window.location.hash.indexOf('at') >= 0) {
                    	var urlName = window.location.hash.split('/at/')[0];
                    	$.each(masterData.events, function(i, event) {
                    		if ("#" + functions.getURLName(event.title) == urlName) { 
                    			defaultEvent = event;
                    		}
                    	});
                    }
                	
                	// Load the event
                	functions.showEvent.call(self, defaultEvent);
                });
                
                // Turn form in JS based form
                var form = self.find('.venuefinder-search form');
                form.submit(function() {
                	var locationInput = form.find('input[name=location]');
                	functions.gotoAddress.call(self, locationInput.val() + " Australia");
                	return false;
                });

                // Store important variables into data for later use
                self.data('venuefinderOpts', opts);
    			self.data('venuefinderInfoWindow', infoWindow);
    			self.data('venuefinderService', service);
    			self.data('venuefinderMarkers', markers);
            });
        }
    });
    
    // Setup defaults for venuefinder plugin
    $.namespace('fn.fs.venuefinder', {
        defaults: {
    		clusterGridSize: 60,
    		closeUpZoomLevel: 16
        }
    });
})(jQuery);(function($) {
	$.namespace('fs.venuefinder.service');
	
	// Interface for venuefinder Service implementation
	$.fs.venuefinder.service.intaface = $.klass({
		/**
		 * init - Constructure, responsible for doing any setup work required
		 * by your delegate, eg. preloading data.
		 **/
		initialize: function() {
			throw "init not implemented";
		},
		
		/**
		 * getVenues - Should return a list of all PVE venues.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getVenues: function(successDelegate, failureDelegate) {
			throw "getVenues not implemented";
		},
		
		/**
		 * getMasterData - Should return the data required to initialise a venue finder.
		 *
	     * If successful, than the successDelegate should be called, otherwise
	     * call the failureDelegate.
		 **/
		getMasterData: function(successDelegate, failureDelegate) {
			throw "getMasterData";
		}
	});
		
	// JSON based venuefinder Service implementation
	$.fs.venuefinder.service.json = $.klass($.fs.venuefinder.service.intaface, {
		defaults: {
			masterFile: null
		},
		
		initialize: function(opts) {
			this.opts = $.extend({}, this.defaults, opts);
		},
		
		_loadNextFile: function(files, successDelegate, failureDelegate, array) {			
			var self = this;
			
			// If empty array, then we load the first file
			if (array === undefined) {
				array = [];
				this.currentFile = 0;
			} else {
				this.currentFile ++;
			}
			
			// Check if we're finished loading all files
			var file = files[this.currentFile];
			if (file === undefined) {
				// If so, call the success delegate
				if (successDelegate !== undefined && successDelegate !== null) {
					successDelegate.call(self, array);
				}
				
				// Don't load next file
				return; 
			}
			
			// Load the file using script injection
			// Method plotVenues is called
			$.ajax({
				url: file,
			  	dataType: 'script',
			  	success: function() {
					$.merge(array, $.fs.venuefinder.service.venuesData);
					self._loadNextFile(files, successDelegate, failureDelegate, array);
				},
				error: function() {
					self._loadNextFile(files, successDelegate, failureDelegate, array);
				}
			});
		},
		
		getVenues: function(files, successDelegate, failureDelegate) {
			this._loadNextFile(files, successDelegate, failureDelegate);
		},
		
		getMasterData: function(successDelegate, failureDelegate) {
			var self = this;
			
			// Load the master file
			$.ajax({
				url: this.opts.masterFile,
			  	dataType: 'script',
			  	success: function() {
					if (successDelegate !== undefined && successDelegate !== null) {
						successDelegate.call(self, $.fs.venuefinder.service.masterData);
					}
				},
				error: function() {
					if (failureDelegate !== undefined && failureDelegate !== null) {
						failureDelegate.call(self);
					}
				}
			});
		}
	});
})(jQuery);

// Global function called by venue finder JSON
// Stores the data into a variable accessibile by the venue finder service
var plotVenues = function(data) {
	jQuery.fs.venuefinder.service.venuesData = data;
};

// Global function called by venue finder events JSON
// Stores the data into a variable accessibile by the venue finder service
var loadVenueFinder = function(data) {
	jQuery.fs.venuefinder.service.masterData = data;
};(function($) {
    $.namespace('fs.videoplayer', {
        defaults: {
    		externalPauseCallbackName: "externalPause",
    		flashUnloadCallbackName: "flashUnload"
        },
        
        selector: "",
        elements: null,
        
        init: function(selector, opts) {
            this.opts = $.extend({}, $.fs.videoplayer.defaults, opts);
            
            // Retrieve the elements as a jquery object
            this.selector = selector;
        },
        
        printTraceData: function(traceData) {
        	$('.video-feedback-trace-box').html(traceData);
        	$('input[name=form-tracedata]').val(traceData);
        },
        
        flashCall: function(callbackName) {
        	this.elements = $(this.selector);
        	
        	this.elements.flash(function() {
	        	if (this[callbackName] !== undefined && this[callbackName] !== null) {
	        		this[callbackName](); 
	        	}
        	});
        },
        
        unload: function() {
        	if (this.opts === undefined) { return; }
        	this.flashCall(this.opts.flashUnloadCallbackName);
        },
        
        pause: function() {
        	if (this.opts === undefined) { return; }
        	this.flashCall(this.opts.externalPauseCallbackName);
        }
    });
})(jQuery);// jquery.fs.watermark
// Fox Sports Watermarked Textbox
// (c)2009 Edmond Leung/Fox Sports
//
// Creates a watermark for textboxes (default text when textbox is empty).
// The textbox uses the contents of its 'title' attribute as the watermark text.
//
// Note: Uses 'fs' namespace.
//
// Dependencies:
// jquery.namespace.js
//
// Usage:
// $('input').fs.watermark();

(function($) {    
    var functions = {
        checkBlur: function(opts) {
            var self = $(this);
            if (self.val() === '' || self.val() == self.attr('title')) {
                self.addClass(opts.watermarkedClass);
                self.val(self.attr('title'));
            }
        }
    };
    
    // Create fs.watermark jquery call
    $.namespace('fn.fs', {
        watermark: function(opts) {     
            opts = $.extend({}, $.fn.fs.watermark.defaults, opts);

            return this
                .each(function() { 
                    var self = $(this);                                        
                    functions.checkBlur.call(this, opts);
                                        
                    // Make sure watermark is gone when submitting form
                    self.closest('form').submit(function() {
                        self.focus();
                    });
                })
                .blur(function() { functions.checkBlur.call(this, opts); })
                .focus(function() {
                    var self = $(this);
                    if (self.attr('title') == self.val()) { self.val(''); }
                    self.removeClass(opts.watermarkedClass);
                });
        }
    });
    
    // Setup defaults for watermark plugin
    $.namespace('fn.fs.watermark', {
        defaults: {
            watermarkedClass: "watermarked" // Class applied when watermark is visible
        }
    });
})(jQuery);


