/*
 - Description
 	Plugin for jQuery. Populate html with a json data source.
 - Author
 	Alexandre Caprais
 - Licence
 	GNU Lesser General Public License
*/

jQuery.fn.fill = function(obj, options) {
	function browseJSON(obj, element) {
		// prepare
		var path = path || '';
		// no object
		if(obj == undefined) {
		}
		// branch
		else if (obj.constructor == Object) {
			for(var prop in obj){
				var child = jQuery.makeArray(jQuery("."+prop, element)).length > 0 ? jQuery("."+prop, element) : jQuery("#"+prop, element);
				browseJSON(obj[prop], jQuery(child, element));
			}
		}
		// array
		else if(obj.constructor == Array) {
			var arr = jQuery.makeArray(element);
			//how many duplicate
			var nbToCreate = obj.length - arr.length;
			var i = 0;
			for(iExist = 0; iExist < arr.length; iExist++) {
				if(i < obj.length) {
					$(element).eq(iExist).fill(obj[i]);
				}
				i++;
			}
			//fill started by last
			i = obj.length - 1;
			for(iCreate = 0; iCreate < nbToCreate; iCreate++) {
				//duplicate the last
				$(arr[arr.length - 1]).clone(true).insertAfter(arr[arr.length - 1]).fill(obj[i]);
				i--;
			}
		}
		// data only
		else {
			$(element).html(obj);
		}
	}

	this.each(function() {
		browseJSON(obj, this);
	});
return this;
}

/*

jQuery.displayRss - Rss feed display

Arguments:

feedUrl = rss feed url
options = options
- options.maxElements = max element number
- outputDateFormat = output date format
- options.scroll = do scroll
- options speed = speed (px per second)
- options classOvf = div overflow class name

Global:

jQuery.fn.displayRss.proxy = proxy for cross domain xmlhttp

*/

jQuery.fn.displayRss = function(feedUrl, options)
{
	options = jQuery.extend({
		maxElements: 1000,
		outputDateFormat: "dd/MM/yyyy HH:mm",
		scroll: true,
		speed: 10, // 10pixel/second
		classOvf: "scrollspace",
		gmtCorrection: false,
		gmtDelay: 0
	}, options);

	var targetObj = $(this);

	var pad = function(str, chnum, ch)
	{
		if ( str.length >= chnum ) return str;
		var newstr = "";
		for ( var i=0;i<(chnum-str.length);i++ ) newstr+=ch;
		newstr+=str;
		return newstr;
	}

	var formatDate = function(dt, format)
	{
		var month = dt.getMonth() + 1;
		var year = dt.getFullYear();
		format = format.replace("MM", pad(month+"",2,"0"));
		if (format.indexOf("yyyy") > -1)
			format = format.replace("yyyy",year+"");
		else if (format.indexOf("yy") > -1)
			format = format.replace("yy",(year+"").substr(2,2));
		format = format.replace("dd", pad(dt.getDate()+"",2,"0"));
		var hours = dt.getHours();
		if(options.gmtCorrection){
			hours = hours + options.gmtDelay;
			if(hours > 23){
				hours = hours - 23;
			}else if(hours < 0){
				hours = hours + 23;
			}
		}
		if (format.indexOf("t") > -1)
		{
			if (hours > 11)
				format = format.replace("t","pm")
			else
				format = format.replace("t","am")
		}
		if (format.indexOf("HH") > -1)
			format = format.replace("HH", pad(hours+"",2,"0"));
		if (format.indexOf("hh") > -1)
		{
			if (hours > 12) hours - 12;
			if (hours == 0) hours = 12;
			format = format.replace("hh", pad(hours+"",2,"0"));
		}
		if (format.indexOf("mm") > -1)
			format = format.replace("mm", pad(dt.getMinutes()+"",2,"0"));
		if (format.indexOf("ss") > -1)
			format = format.replace("ss", pad(dt.getSeconds()+"",2,"0"));
		return format;
	}

	var makeLink = function(txt, href)
	{
		return "<a href=\"" + href + "\" onclick=\"window.open(this.href);return false;\">" + txt + "</a>";
	}
	
	$.ajax(
		{
			type: "GET",
			url: jQuery.fn.displayRss.proxy ? jQuery.fn.displayRss.proxy + escape(feedUrl) : feedUrl,
			dataType: "xml",
			success: function(xml)
			{
				var xmlItems = $("item",xml);
				var itemList = new Array();
				
				var endTo=xmlItems.length;
				if ( options.scroll )
					endTo = options.maxElements > xmlItems.length ? xmlItems.length : options.maxElements;
				
				for (var i=0;i<endTo;i++)
				{
					var item = new Object();

					// try to parse date
					var dateObj;
					try { dateObj = new Date(Date.parse($("pubDate",xmlItems[i]).text())); } catch ( er ) {}

					// fill pubDate
					if ( dateObj && dateObj!=null ){
						item.pubDate = formatDate(dateObj, options.outputDateFormat);
					}else{
						item.pubDate = $("pubDate",xmlItems[i]).text();
					}
					item.title = $("title",xmlItems[i]).text();
					item.description = $("description",xmlItems[i]).text();
					item.link = $("link",xmlItems[i]).text();

					// fill linked properties
					item.linkedPubdate = makeLink(item.pubDate, item.link);
					item.linkedTitle = makeLink(item.title, item.link);
					item.linkedDescription = makeLink(item.description, item.link);

					itemList[itemList.length] = item;
				}
				targetObj.fill(itemList);
					
				if(options.scroll)
				{
					var ul = $($(targetObj[0]).parent()[0]);
					
					//IE7 Fix
					if(ul.css("top")=="auto"){
						ul.css("top",0)
					}
					
					if(options.classOvf != ul.parent().className){
						ul.wrap("<div class=\""+ options.classOvf +"\"></div>");
					}
					doScroll(ul, options.speed);
				}
			},
			error:function (XMLHttpRequest, textStatus, errorThrown) {
			}

		}
	)
	
	var doScroll = function(ul, speed)
	{
		if ( !ul._status )
		{	
			ul._status = "animated";
			
			ul.mouseover( function()
						{
							if ( ul._status=="animated" )
							{
								ul._status = "stopped";
								ul.stop();
							}
						});
						
			ul.mouseout( function()
						{
							if ( ul._status=="stopped" )
							{
								ul._status = "animated";
								doScroll(ul, speed);
							}
						});
			
		}
		
		
		var cont = ul.parent();

		var animationLength = Math.abs( parseInt(ul.css("top"),10) + ul.height() - cont.height() );
		
		var topMax = "-=" + animationLength + "px";
		
		ul.animate({"top": topMax }, ((animationLength/speed)*1000), "linear",
			function()
			{
				ul._status=="animated";
				ul.css("top",0);
				doScroll(ul,speed);
			});
		
	}
	
	return this;
}
